class.c 60.7 KB
Newer Older
mimaki's avatar
mimaki committed
1 2
/*
** class.c - Class class
roco's avatar
roco committed
3
**
mimaki's avatar
mimaki committed
4 5 6
** See Copyright Notice in mruby.h
*/

cremno's avatar
cremno committed
7
#include <stdarg.h>
8 9 10 11 12 13 14 15 16
#include <mruby.h>
#include <mruby/array.h>
#include <mruby/class.h>
#include <mruby/numeric.h>
#include <mruby/proc.h>
#include <mruby/string.h>
#include <mruby/variable.h>
#include <mruby/error.h>
#include <mruby/data.h>
17
#include <mruby/istruct.h>
mimaki's avatar
mimaki committed
18

19
KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
mimaki's avatar
mimaki committed
20 21 22 23 24 25 26 27 28

void
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
{
  khiter_t k;
  khash_t(mt) *h = c->mt;

  if (!h) return;
  for (k = kh_begin(h); k != kh_end(h); k++) {
yui-knk's avatar
yui-knk committed
29
    if (kh_exist(h, k)) {
mimaki's avatar
mimaki committed
30 31
      struct RProc *m = kh_value(h, k);
      if (m) {
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
32
        mrb_gc_mark(mrb, (struct RBasic*)m);
mimaki's avatar
mimaki committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
      }
    }
  }
}

size_t
mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c)
{
  khash_t(mt) *h = c->mt;

  if (!h) return 0;
  return kh_size(h);
}

void
mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
{
50
  kh_destroy(mt, mrb, c->mt);
mimaki's avatar
mimaki committed
51 52
}

53 54
static void
name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mimaki's avatar
mimaki committed
55 56
{
  mrb_obj_iv_set(mrb, (struct RObject*)c,
57
                 mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
mimaki's avatar
mimaki committed
58
}
take_cheeze's avatar
take_cheeze committed
59

60 61 62 63 64 65 66 67 68 69 70
static void
setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
{
  name_class(mrb, c, id);
  mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
  if (outer != mrb->object_class) {
    mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
                   mrb_obj_value(outer));
  }
}

71 72
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))

mimaki's avatar
mimaki committed
73
static void
74
prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
mimaki's avatar
mimaki committed
75
{
76
  struct RClass *sc, *c;
mimaki's avatar
mimaki committed
77

78
  if (o->c->tt == MRB_TT_SCLASS) return;
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
79
  sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
80
  sc->mt = kh_init(mt, mrb);
81
  sc->iv = 0;
82 83
  if (o->tt == MRB_TT_CLASS) {
    c = (struct RClass*)o;
84 85 86 87
    if (!c->super) {
      sc->super = mrb->class_class;
    }
    else {
88 89
      sc->super = c->super->c;
    }
90
  }
91 92
  else if (o->tt == MRB_TT_SCLASS) {
    c = (struct RClass*)o;
93 94
    while (c->super->tt == MRB_TT_ICLASS)
      c = c->super;
95
    make_metaclass(mrb, c->super);
96 97
    sc->super = c->super->c;
  }
98 99 100 101 102 103
  else {
    sc->super = o->c;
  }
  o->c = sc;
  mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
  mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
104
  mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
mimaki's avatar
mimaki committed
105 106
}

107 108
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
mimaki's avatar
mimaki committed
109
{
110
  mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
mimaki's avatar
mimaki committed
111

112 113
  mrb_check_type(mrb, c, MRB_TT_CLASS);
  return mrb_class_ptr(c);
mimaki's avatar
mimaki committed
114 115
}

116 117
static struct RClass *
module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
mimaki's avatar
mimaki committed
118
{
119
  mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
mimaki's avatar
mimaki committed
120

121 122
  mrb_check_type(mrb, c, MRB_TT_MODULE);
  return mrb_class_ptr(c);
mimaki's avatar
mimaki committed
123 124
}

125
MRB_API struct RClass*
mimaki's avatar
mimaki committed
126 127 128 129
mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
{
  mrb_value outer;

130
  outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
131
  if (mrb_nil_p(outer)) return NULL;
mimaki's avatar
mimaki committed
132 133 134
  return mrb_class_ptr(outer);
}

135 136 137 138 139 140 141 142 143 144 145 146 147
static void
check_if_class_or_module(mrb_state *mrb, mrb_value obj)
{
  switch (mrb_type(obj)) {
  case MRB_TT_CLASS:
  case MRB_TT_SCLASS:
  case MRB_TT_MODULE:
    return;
  default:
    mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj));
  }
}

148 149 150 151 152
static struct RClass*
define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
{
  struct RClass *m;

153
  if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
154 155 156 157 158 159 160 161
    return module_from_sym(mrb, outer, name);
  }
  m = mrb_module_new(mrb);
  setup_class(mrb, outer, m, name);

  return m;
}

162
MRB_API struct RClass*
163 164 165 166 167
mrb_define_module_id(mrb_state *mrb, mrb_sym name)
{
  return define_module(mrb, name, mrb->object_class);
}

168
MRB_API struct RClass*
169 170 171 172 173
mrb_define_module(mrb_state *mrb, const char *name)
{
  return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
}

174
MRB_API struct RClass*
mimaki's avatar
mimaki committed
175 176
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
177
  check_if_class_or_module(mrb, outer);
178 179 180 181 182 183 184 185
  if (mrb_const_defined_at(mrb, outer, id)) {
    mrb_value old = mrb_const_get(mrb, outer, id);

    if (mrb_type(old) != MRB_TT_MODULE) {
      mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old));
    }
    return mrb_class_ptr(old);
  }
186 187
  return define_module(mrb, id, mrb_class_ptr(outer));
}
mimaki's avatar
mimaki committed
188

189
MRB_API struct RClass*
190 191 192 193 194 195
mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
  mrb_sym id = mrb_intern_cstr(mrb, name);
  struct RClass * c = define_module(mrb, id, outer);

  setup_class(mrb, outer, c, id);
mimaki's avatar
mimaki committed
196 197 198
  return c;
}

199 200 201 202 203 204 205
static struct RClass*
find_origin(struct RClass *c)
{
  MRB_CLASS_ORIGIN(c);
  return c;
}

206 207
static struct RClass*
define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
mimaki's avatar
mimaki committed
208
{
209 210
  struct RClass * c;

211
  if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
212
    c = class_from_sym(mrb, outer, name);
213
    MRB_CLASS_ORIGIN(c);
214 215 216 217 218 219 220
    if (super && mrb_class_real(c->super) != super) {
      mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
                 mrb_sym2str(mrb, name),
                 mrb_obj_value(c->super), mrb_obj_value(super));
    }
    return c;
  }
mimaki's avatar
mimaki committed
221

222 223
  c = mrb_class_new(mrb, super);
  setup_class(mrb, outer, c, name);
mimaki's avatar
mimaki committed
224 225 226 227

  return c;
}

228
MRB_API struct RClass*
229 230 231
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
{
  if (!super) {
232
    mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name));
233 234 235 236
  }
  return define_class(mrb, name, super, mrb->object_class);
}

237
MRB_API struct RClass*
mimaki's avatar
mimaki committed
238 239
mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
{
240
  return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
mimaki's avatar
mimaki committed
241 242
}

243 244
static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value cv);

ksss's avatar
ksss committed
245 246 247
static void
mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
{
248 249 250
  mrb_value s;
  mrb_sym mid;

ksss's avatar
ksss committed
251 252
  if (!super)
    super = mrb->object_class;
253 254 255 256 257 258
  s = mrb_obj_value(super);
  mid = mrb_intern_lit(mrb, "inherited");
  if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) {
    mrb_value c = mrb_obj_value(klass);
    mrb_funcall_argv(mrb, mrb_obj_value(super), mid, 1, &c);
  }
ksss's avatar
ksss committed
259 260
}

261
MRB_API struct RClass*
mimaki's avatar
mimaki committed
262 263
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
264 265
  struct RClass *s;
  struct RClass *c;
mimaki's avatar
mimaki committed
266

267 268
  if (!mrb_nil_p(super)) {
    if (mrb_type(super) != MRB_TT_CLASS) {
269
      mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
270
    }
271
    s = mrb_class_ptr(super);
mimaki's avatar
mimaki committed
272
  }
273
  else {
274
    s = 0;
275
  }
276
  check_if_class_or_module(mrb, outer);
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
  if (mrb_const_defined_at(mrb, outer, id)) {
    mrb_value old = mrb_const_get(mrb, outer, id);

    if (mrb_type(old) != MRB_TT_CLASS) {
      mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old));
    }
    c = mrb_class_ptr(old);
    if (s) {
      /* check super class */
      if (mrb_class_real(c->super) != s) {
        mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old);
      }
    }
    return c;
  }
292
  c = define_class(mrb, id, s, mrb_class_ptr(outer));
ksss's avatar
ksss committed
293
  mrb_class_inherited(mrb, mrb_class_real(c->super), c);
mimaki's avatar
mimaki committed
294 295 296 297

  return c;
}

298
MRB_API mrb_bool
299 300
mrb_class_defined(mrb_state *mrb, const char *name)
{
301
  mrb_value sym = mrb_check_intern_cstr(mrb, name);
302 303 304 305
  if (mrb_nil_p(sym)) {
    return FALSE;
  }
  return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
306 307
}

308
MRB_API mrb_bool
309
mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name)
310 311 312 313 314 315 316 317
{
  mrb_value sym = mrb_check_intern_cstr(mrb, name);
  if (mrb_nil_p(sym)) {
    return FALSE;
  }
  return mrb_const_defined_at(mrb, mrb_obj_value(outer), mrb_symbol(sym));
}

318
MRB_API struct RClass *
319
mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
320
{
321
  return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
322 323
}

324
MRB_API struct RClass *
325 326
mrb_class_get(mrb_state *mrb, const char *name)
{
h2so5's avatar
h2so5 committed
327 328 329
  return mrb_class_get_under(mrb, mrb->object_class, name);
}

330 331 332 333 334 335 336 337 338 339 340 341 342 343
MRB_API struct RClass *
mrb_exc_get(mrb_state *mrb, const char *name)
{
  struct RClass *exc = mrb_class_get_under(mrb, mrb->object_class, name);
  struct RClass *e = exc;

  while (e) {
    if (e == mrb->eException_class)
      return exc;
    e = e->super;
  }
  return mrb->eException_class;
}

344
MRB_API struct RClass *
345
mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
h2so5's avatar
h2so5 committed
346
{
347 348 349
  return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
}

350
MRB_API struct RClass *
351 352 353
mrb_module_get(mrb_state *mrb, const char *name)
{
  return mrb_module_get_under(mrb, mrb->object_class, name);
354 355
}

mimaki's avatar
mimaki committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
/*!
 * Defines a class under the namespace of \a outer.
 * \param outer  a class which contains the new class.
 * \param id     name of the new class
 * \param super  a class from which the new class will derive.
 *               NULL means \c Object class.
 * \return the created class
 * \throw TypeError if the constant name \a name is already taken but
 *                  the constant is not a \c Class.
 * \throw NameError if the class is already defined but the class can not
 *                  be reopened because its superclass is not \a super.
 * \post top-level constant named \a name refers the returned class.
 *
 * \note if a class named \a name is already defined and its superclass is
 *       \a super, the function just returns the defined class.
 */
372
MRB_API struct RClass *
mimaki's avatar
mimaki committed
373 374
mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
{
375
  mrb_sym id = mrb_intern_cstr(mrb, name);
mimaki's avatar
mimaki committed
376 377
  struct RClass * c;

378 379
#if 0
  if (!super) {
380
    mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
381
             mrb_obj_value(outer), mrb_sym2str(mrb, id));
mimaki's avatar
mimaki committed
382
  }
383 384 385
#endif
  c = define_class(mrb, id, super, outer);
  setup_class(mrb, outer, c, id);
mimaki's avatar
mimaki committed
386 387 388
  return c;
}

389
MRB_API void
mimaki's avatar
mimaki committed
390 391
mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
{
392
  khash_t(mt) *h;
mimaki's avatar
mimaki committed
393
  khiter_t k;
394 395
  MRB_CLASS_ORIGIN(c);
  h = c->mt;
mimaki's avatar
mimaki committed
396

397 398 399 400 401 402
  if (MRB_FROZEN_P(c)) {
    if (c->tt == MRB_TT_MODULE)
      mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen module");
    else
      mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen class");
  }
mimaki's avatar
mimaki committed
403
  if (!h) h = c->mt = kh_init(mt, mrb);
404
  k = kh_put(mt, mrb, h, mid);
mimaki's avatar
mimaki committed
405
  kh_value(h, k) = p;
Masamitsu MURASE's avatar
Masamitsu MURASE committed
406 407 408
  if (p) {
    mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
  }
mimaki's avatar
mimaki committed
409 410
}

411
MRB_API void
412
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
mimaki's avatar
mimaki committed
413 414
{
  struct RProc *p;
415
  int ai = mrb_gc_arena_save(mrb);
mimaki's avatar
mimaki committed
416 417

  p = mrb_proc_new_cfunc(mrb, func);
take_cheeze's avatar
take_cheeze committed
418
  p->target_class = c;
mimaki's avatar
mimaki committed
419
  mrb_define_method_raw(mrb, c, mid, p);
420
  mrb_gc_arena_restore(mrb, ai);
mimaki's avatar
mimaki committed
421 422
}

423
MRB_API void
424
mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
mimaki's avatar
mimaki committed
425
{
426
  mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
427 428
}

429 430 431
/* a function to raise NotImplementedError with current method name */
MRB_API void
mrb_notimplement(mrb_state *mrb)
ksss's avatar
ksss committed
432 433 434 435 436 437 438 439
{
  const char *str;
  mrb_int len;
  mrb_callinfo *ci = mrb->c->ci;

  if (ci->mid) {
    str = mrb_sym2name_len(mrb, ci->mid, &len);
    mrb_raisef(mrb, E_NOTIMP_ERROR,
Robert Mosolgo's avatar
Robert Mosolgo committed
440
      "%S() function is unimplemented on this machine",
ksss's avatar
ksss committed
441 442
      mrb_str_new_static(mrb, str, (size_t)len));
  }
443 444 445 446 447 448 449 450
}

/* a function to be replacement of unimplemented method */
MRB_API mrb_value
mrb_notimplement_m(mrb_state *mrb, mrb_value self)
{
  mrb_notimplement(mrb);
  /* not reached */
ksss's avatar
ksss committed
451 452 453
  return mrb_nil_value();
}

454 455 456 457 458 459 460
static mrb_value
check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
{
  mrb_value tmp;

  tmp = mrb_check_convert_type(mrb, val, t, c, m);
  if (mrb_nil_p(tmp)) {
461
    mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
  }
  return tmp;
}

static mrb_value
to_str(mrb_state *mrb, mrb_value val)
{
  return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
}

static mrb_value
to_ary(mrb_state *mrb, mrb_value val)
{
  return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
}

static mrb_value
to_hash(mrb_state *mrb, mrb_value val)
{
  return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
}

484 485 486 487 488 489 490 491 492 493 494 495
static mrb_sym
to_sym(mrb_state *mrb, mrb_value ss)
{
  if (mrb_type(ss) == MRB_TT_SYMBOL) {
    return mrb_symbol(ss);
  }
  else if (mrb_string_p(ss)) {
    return mrb_intern_str(mrb, to_str(mrb, ss));
  }
  else {
    mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
    mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
496 497
    /* not reached */
    return 0;
498 499 500
  }
}

501 502 503 504
/*
  retrieve arguments from mrb_state.

  mrb_get_args(mrb, format, ...)
505

506 507
  returns number of arguments parsed.

Carson McDonald's avatar
Carson McDonald committed
508
  format specifiers:
509

510 511 512
    string  mruby type     C type                 note
    ----------------------------------------------------------------------------------------------
    o:      Object         [mrb_value]
513
    C:      class/module   [mrb_value]
514 515 516
    S:      String         [mrb_value]            when ! follows, the value may be nil
    A:      Array          [mrb_value]            when ! follows, the value may be nil
    H:      Hash           [mrb_value]            when ! follows, the value may be nil
517 518 519
    s:      String         [char*,mrb_int]        Receive two arguments; s! gives (NULL,0) for nil
    z:      String         [char*]                NUL terminated string; z! gives NULL for nil
    a:      Array          [mrb_value*,mrb_int]   Receive two arguments; a! gives (NULL,0) for nil
520 521 522 523
    f:      Float          [mrb_float]
    i:      Integer        [mrb_int]
    b:      Boolean        [mrb_bool]
    n:      Symbol         [mrb_sym]
524
    d:      Data           [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
525
    I:      Inline struct  [void*]
526
    &:      Block          [mrb_value]
527
    *:      rest argument  [mrb_value*,mrb_int]   Receive the rest of the arguments as an array.
528
    |:      optional                              Next argument of '|' and later are optional.
529
    ?:      optional given [mrb_bool]             true if preceding argument (optional) is given.
530
 */
531
MRB_API mrb_int
mimaki's avatar
mimaki committed
532 533 534
mrb_get_args(mrb_state *mrb, const char *format, ...)
{
  char c;
535
  int i = 0;
mimaki's avatar
mimaki committed
536
  va_list ap;
537
  int argc = mrb->c->ci->argc;
538 539
  int arg_i = 0;
  mrb_bool array_argv;
Jun Hiroe's avatar
Jun Hiroe committed
540 541
  mrb_bool opt = FALSE;
  mrb_bool given = TRUE;
mimaki's avatar
mimaki committed
542 543 544

  va_start(ap, format);
  if (argc < 0) {
545
    struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
mimaki's avatar
mimaki committed
546 547

    argc = a->len;
548 549 550
    array_argv = TRUE;
  } else {
    array_argv = FALSE;
mimaki's avatar
mimaki committed
551
  }
552 553 554 555

#define ARGV \
  (array_argv ? mrb_ary_ptr(mrb->c->stack[1])->ptr : (mrb->c->stack + 1))

mimaki's avatar
mimaki committed
556
  while ((c = *format++)) {
557
    switch (c) {
558
    case '|': case '*': case '&': case '?':
559 560
      break;
    default:
561 562
      if (argc <= i) {
        if (opt) {
Jun Hiroe's avatar
Jun Hiroe committed
563
          given = FALSE;
564 565 566 567
        }
        else {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
        }
568
      }
569
      break;
570
    }
571

mimaki's avatar
mimaki committed
572 573 574 575
    switch (c) {
    case 'o':
      {
        mrb_value *p;
576

mimaki's avatar
mimaki committed
577
        p = va_arg(ap, mrb_value*);
skandhas's avatar
skandhas committed
578
        if (i < argc) {
579
          *p = ARGV[arg_i++];
skandhas's avatar
skandhas committed
580 581
          i++;
        }
mimaki's avatar
mimaki committed
582 583
      }
      break;
584 585 586 587 588 589 590 591
    case 'C':
      {
        mrb_value *p;

        p = va_arg(ap, mrb_value*);
        if (i < argc) {
          mrb_value ss;

592
          ss = ARGV[arg_i++];
593 594 595 596 597 598 599 600 601 602 603 604 605 606
          switch (mrb_type(ss)) {
          case MRB_TT_CLASS:
          case MRB_TT_MODULE:
          case MRB_TT_SCLASS:
            break;
          default:
            mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
            break;
          }
          *p = ss;
          i++;
        }
      }
      break;
607
    case 'S':
mimaki's avatar
mimaki committed
608
      {
609
        mrb_value *p;
mimaki's avatar
mimaki committed
610

611
        p = va_arg(ap, mrb_value*);
612 613
        if (*format == '!') {
          format++;
614 615
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
616 617 618 619
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
620
        if (i < argc) {
621
          *p = to_str(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
622 623
          i++;
        }
624 625 626 627 628
      }
      break;
    case 'A':
      {
        mrb_value *p;
629

630
        p = va_arg(ap, mrb_value*);
631 632
        if (*format == '!') {
          format++;
633 634
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
635 636 637 638
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
639
        if (i < argc) {
640
          *p = to_ary(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
641 642
          i++;
        }
643 644 645 646 647 648 649
      }
      break;
    case 'H':
      {
        mrb_value *p;

        p = va_arg(ap, mrb_value*);
650 651
        if (*format == '!') {
          format++;
652 653
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
654 655 656 657
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
658
        if (i < argc) {
659
          *p = to_hash(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
660 661
          i++;
        }
662 663 664 665
      }
      break;
    case 's':
      {
skandhas's avatar
skandhas committed
666
        mrb_value ss;
667
        char **ps = 0;
668
        mrb_int *pl = 0;
669

skandhas's avatar
skandhas committed
670
        ps = va_arg(ap, char**);
671
        pl = va_arg(ap, mrb_int*);
672 673
        if (*format == '!') {
          format++;
674
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
675 676 677 678 679 680
            *ps = NULL;
            *pl = 0;
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
681
        if (i < argc) {
682
          ss = to_str(mrb, ARGV[arg_i++]);
683 684
          *ps = RSTRING_PTR(ss);
          *pl = RSTRING_LEN(ss);
skandhas's avatar
skandhas committed
685 686
          i++;
        }
687 688 689 690
      }
      break;
    case 'z':
      {
skandhas's avatar
skandhas committed
691
        mrb_value ss;
692
        const char **ps;
693

694
        ps = va_arg(ap, const char**);
695 696
        if (*format == '!') {
          format++;
697
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
698
            *ps = NULL;
699
            i++; arg_i++;
700 701 702
            break;
          }
        }
skandhas's avatar
skandhas committed
703
        if (i < argc) {
704
          ss = to_str(mrb, ARGV[arg_i++]);
705
          *ps = mrb_string_value_cstr(mrb, &ss);
skandhas's avatar
skandhas committed
706 707
          i++;
        }
708 709 710 711
      }
      break;
    case 'a':
      {
skandhas's avatar
skandhas committed
712
        mrb_value aa;
713 714
        struct RArray *a;
        mrb_value **pb;
715
        mrb_int *pl;
716

skandhas's avatar
skandhas committed
717
        pb = va_arg(ap, mrb_value**);
718
        pl = va_arg(ap, mrb_int*);
719 720
        if (*format == '!') {
          format++;
721
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
722 723
            *pb = 0;
            *pl = 0;
724
            i++; arg_i++;
725 726 727
            break;
          }
        }
skandhas's avatar
skandhas committed
728
        if (i < argc) {
729
          aa = to_ary(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
730 731 732 733 734
          a = mrb_ary_ptr(aa);
          *pb = a->ptr;
          *pl = a->len;
          i++;
        }
mimaki's avatar
mimaki committed
735 736
      }
      break;
737 738 739 740 741 742 743 744
    case 'I':
      {
        void* *p;
        mrb_value ss;

        p = va_arg(ap, void**);
        if (i < argc) {
          ss = ARGV[arg_i];
745
          if (mrb_type(ss) != MRB_TT_ISTRUCT)
746 747 748
          {
            mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss);
          }
749
          *p = mrb_istruct_ptr(ss);
750 751 752 753 754
          arg_i++;
          i++;
        }
      }
      break;
mimaki's avatar
mimaki committed
755 756 757 758 759
    case 'f':
      {
        mrb_float *p;

        p = va_arg(ap, mrb_float*);
skandhas's avatar
skandhas committed
760
        if (i < argc) {
761 762
          *p = mrb_to_flo(mrb, ARGV[arg_i]);
          arg_i++;
skandhas's avatar
skandhas committed
763 764
          i++;
        }
mimaki's avatar
mimaki committed
765 766
      }
      break;
767
    case 'i':
mimaki's avatar
mimaki committed
768
      {
769
        mrb_int *p;
mimaki's avatar
mimaki committed
770

771
        p = va_arg(ap, mrb_int*);
skandhas's avatar
skandhas committed
772
        if (i < argc) {
773
          switch (mrb_type(ARGV[arg_i])) {
skandhas's avatar
skandhas committed
774
            case MRB_TT_FIXNUM:
775
              *p = mrb_fixnum(ARGV[arg_i]);
skandhas's avatar
skandhas committed
776 777 778
              break;
            case MRB_TT_FLOAT:
              {
779
                mrb_float f = mrb_float(ARGV[arg_i]);
skandhas's avatar
skandhas committed
780 781 782 783 784 785 786

                if (!FIXABLE(f)) {
                  mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
                }
                *p = (mrb_int)f;
              }
              break;
787
            case MRB_TT_STRING:
788
              mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
789
              break;
skandhas's avatar
skandhas committed
790
            default:
791
              *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
skandhas's avatar
skandhas committed
792 793
              break;
          }
794
          arg_i++;
skandhas's avatar
skandhas committed
795 796
          i++;
        }
mimaki's avatar
mimaki committed
797 798
      }
      break;
799 800
    case 'b':
      {
801
        mrb_bool *boolp = va_arg(ap, mrb_bool*);
802

skandhas's avatar
skandhas committed
803
        if (i < argc) {
804
          mrb_value b = ARGV[arg_i++];
skandhas's avatar
skandhas committed
805 806 807
          *boolp = mrb_test(b);
          i++;
        }
808 809
      }
      break;
810 811
    case 'n':
      {
skandhas's avatar
skandhas committed
812 813 814 815 816 817
        mrb_sym *symp;

        symp = va_arg(ap, mrb_sym*);
        if (i < argc) {
          mrb_value ss;

818
          ss = ARGV[arg_i++];
819
          *symp = to_sym(mrb, ss);
skandhas's avatar
skandhas committed
820 821
          i++;
        }
822 823
      }
      break;
824 825 826 827 828 829 830
    case 'd':
      {
        void** datap;
        struct mrb_data_type const* type;

        datap = va_arg(ap, void**);
        type = va_arg(ap, struct mrb_data_type const*);
831 832
        if (*format == '!') {
          format++;
833
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
834
            *datap = 0;
835
            i++; arg_i++;
836 837 838
            break;
          }
        }
839
        if (i < argc) {
840
          *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type);
841 842 843 844
          ++i;
        }
      }
      break;
mimaki's avatar
mimaki committed
845 846 847

    case '&':
      {
848
        mrb_value *p, *bp;
mimaki's avatar
mimaki committed
849 850

        p = va_arg(ap, mrb_value*);
851 852
        if (mrb->c->ci->argc < 0) {
          bp = mrb->c->stack + 2;
roco's avatar
roco committed
853
        }
skandhas's avatar
skandhas committed
854
        else {
855
          bp = mrb->c->stack + mrb->c->ci->argc + 1;
skandhas's avatar
skandhas committed
856
        }
roco's avatar
roco committed
857
        *p = *bp;
mimaki's avatar
mimaki committed
858 859
      }
      break;
860
    case '|':
Jun Hiroe's avatar
Jun Hiroe committed
861
      opt = TRUE;
862
      break;
863 864 865 866 867 868 869 870
    case '?':
      {
        mrb_bool *p;

        p = va_arg(ap, mrb_bool*);
        *p = given;
      }
      break;
871

mimaki's avatar
mimaki committed
872 873 874
    case '*':
      {
        mrb_value **var;
875
        mrb_int *pl;
876

mimaki's avatar
mimaki committed
877
        var = va_arg(ap, mrb_value**);
878
        pl = va_arg(ap, mrb_int*);
roco's avatar
roco committed
879
        if (argc > i) {
880 881
          *pl = argc-i;
          if (*pl > 0) {
882
            *var = ARGV + arg_i;
roco's avatar
roco committed
883
          }
skandhas's avatar
skandhas committed
884
          i = argc;
885
          arg_i += *pl;
roco's avatar
roco committed
886 887
        }
        else {
888
          *pl = 0;
roco's avatar
roco committed
889 890
          *var = NULL;
        }
mimaki's avatar
mimaki committed
891 892
      }
      break;
893
    default:
894
      mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
895
      break;
mimaki's avatar
mimaki committed
896 897
    }
  }
898 899 900

#undef ARGV

901
  if (!c && argc > i) {
902 903
    mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
  }
mimaki's avatar
mimaki committed
904
  va_end(ap);
905
  return i;
mimaki's avatar
mimaki committed
906 907 908 909 910 911 912
}

static struct RClass*
boot_defclass(mrb_state *mrb, struct RClass *super)
{
  struct RClass *c;

Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
913
  c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
914 915 916 917 918 919 920
  if (super) {
    c->super = super;
    mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
  }
  else {
    c->super = mrb->object_class;
  }
mimaki's avatar
mimaki committed
921 922 923 924
  c->mt = kh_init(mt, mrb);
  return c;
}

925 926 927
static void
boot_initmod(mrb_state *mrb, struct RClass *mod)
{
928 929 930
  if (!mod->mt) {
    mod->mt = kh_init(mt, mrb);
  }
931 932
}

933 934 935 936 937 938 939
static struct RClass*
include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super)
{
  struct RClass *ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
  if (m->tt == MRB_TT_ICLASS) {
    m = m->c;
  }
940
  MRB_CLASS_ORIGIN(m);
941
  ic->iv = m->iv;
942
  ic->mt = m->mt;
943 944 945 946 947 948 949 950 951
  ic->super = super;
  if (m->tt == MRB_TT_ICLASS) {
    ic->c = m->c;
  } else {
    ic->c = m;
  }
  return ic;
}

952
static int
953
include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super)
mimaki's avatar
mimaki committed
954
{
955
  struct RClass *p, *ic;
956
  void *klass_mt = find_origin(c)->mt;
mimaki's avatar
mimaki committed
957

958
  while (m) {
959 960
    int superclass_seen = 0;

961
    if (m->flags & MRB_FLAG_IS_PREPENDED)
962 963
      goto skip;

964
    if (klass_mt && klass_mt == m->mt)
965 966
      return -1;

967
    p = c->super;
968 969
    while(p) {
      if (p->tt == MRB_TT_ICLASS) {
970
        if (p->mt == m->mt) {
971
          if (!superclass_seen) {
972
            ins_pos = p; // move insert point
973 974
          }
          goto skip;
skandhas's avatar
skandhas committed
975
        }
976
      } else if (p->tt == MRB_TT_CLASS) {
Blaž Hrastnik's avatar
Blaž Hrastnik committed
977
        if (!search_super) break;
skandhas's avatar
skandhas committed
978
        superclass_seen = 1;
979
      }
980 981
      p = p->super;
    }
982

983
    ic = include_class_new(mrb, m, ins_pos->super);
984
    ins_pos->super = ic;
985
    mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super);
986 987
    ins_pos = ic;
  skip:
988 989
    m = m->super;
  }
990
  return 0;
mimaki's avatar
mimaki committed
991 992
}

Blaž Hrastnik's avatar
Blaž Hrastnik committed
993 994 995
MRB_API void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
996
  int changed = include_module_at(mrb, c, find_origin(c), m, 1);
997 998 999
  if (changed < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
  }
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1000 1001 1002 1003 1004 1005 1006 1007
}

MRB_API void
mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
  struct RClass *origin;
  int changed = 0;

1008
  if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1009
    origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
1010
    origin->flags |= MRB_FLAG_IS_ORIGIN;
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1011 1012 1013 1014
    origin->super = c->super;
    c->super = origin;
    origin->mt = c->mt;
    c->mt = kh_init(mt, mrb);
1015 1016
    mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
    c->flags |= MRB_FLAG_IS_PREPENDED;
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1017
  }
1018 1019 1020
  changed = include_module_at(mrb, c, c, m, 0);
  if (changed < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected");
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
  }
}

static mrb_value
mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod)
{
  mrb_value klass;

  mrb_check_type(mrb, mod, MRB_TT_MODULE);
  mrb_get_args(mrb, "C", &klass);
  mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
  return mod;
}

mimaki's avatar
mimaki committed
1035
static mrb_value
1036
mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mimaki's avatar
mimaki committed
1037
{
1038
  mrb_value klass;
mimaki's avatar
mimaki committed
1039

1040
  mrb_check_type(mrb, mod, MRB_TT_MODULE);
1041
  mrb_get_args(mrb, "C", &klass);
mimaki's avatar
mimaki committed
1042 1043 1044 1045
  mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
  return mod;
}

skandhas's avatar
skandhas committed
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
/* 15.2.2.4.28 */
/*
 *  call-seq:
 *     mod.include?(module)    -> true or false
 *
 *  Returns <code>true</code> if <i>module</i> is included in
 *  <i>mod</i> or one of <i>mod</i>'s ancestors.
 *
 *     module A
 *     end
 *     class B
 *       include A
 *     end
 *     class C < B
 *     end
 *     B.include?(A)   #=> true
 *     C.include?(A)   #=> true
 *     A.include?(A)   #=> false
 */
skandhas's avatar
skandhas committed
1065 1066 1067 1068 1069 1070
static mrb_value
mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
{
  mrb_value mod2;
  struct RClass *c = mrb_class_ptr(mod);

1071
  mrb_get_args(mrb, "C", &mod2);
skandhas's avatar
skandhas committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
  mrb_check_type(mrb, mod2, MRB_TT_MODULE);

  while (c) {
    if (c->tt == MRB_TT_ICLASS) {
      if (c->c == mrb_class_ptr(mod2)) return mrb_true_value();
    }
    c = c->super;
  }
  return mrb_false_value();
}
1082

1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
static mrb_value
mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
{
  mrb_value result;
  struct RClass *c = mrb_class_ptr(self);
  result = mrb_ary_new(mrb);
  while (c) {
    if (c->tt == MRB_TT_ICLASS) {
      mrb_ary_push(mrb, result, mrb_obj_value(c->c));
    }
1093
    else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
1094 1095 1096 1097 1098 1099 1100 1101
      mrb_ary_push(mrb, result, mrb_obj_value(c));
    }
    c = c->super;
  }

  return result;
}

1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
static mrb_value
mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
{
  mrb_value obj;

  mrb_check_type(mrb, mod, MRB_TT_MODULE);
  mrb_get_args(mrb, "o", &obj);
  mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
  return mod;
}

1113 1114 1115 1116 1117
static mrb_value
mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
{
  mrb_value result;
  struct RClass *c = mrb_class_ptr(self);
1118
  struct RClass *origin = c;
1119

1120
  MRB_CLASS_ORIGIN(origin);
1121 1122
  result = mrb_ary_new(mrb);
  while (c) {
1123
    if (c != origin && c->tt == MRB_TT_ICLASS) {
1124 1125 1126
      if (c->c->tt == MRB_TT_MODULE) {
        mrb_ary_push(mrb, result, mrb_obj_value(c->c));
      }
1127 1128 1129 1130 1131 1132 1133
    }
    c = c->super;
  }

  return result;
}

1134 1135 1136 1137
static mrb_value
mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
{
  mrb_value b;
1138
  struct RClass *m = mrb_class_ptr(mod);
1139 1140
  boot_initmod(mrb, m); // bootstrap a newly initialized module
  mrb_get_args(mrb, "|&", &b);
1141
  if (!mrb_nil_p(b)) {
1142
    mrb_yield_with_class(mrb, b, 1, &mod, mod, m);
1143 1144 1145 1146
  }
  return mod;
}

cremno's avatar
cremno committed
1147
mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
skandhas's avatar
skandhas committed
1148

1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
/* 15.2.2.4.33 */
/*
 *  call-seq:
 *     mod.instance_methods(include_super=true)   -> array
 *
 *  Returns an array containing the names of the public and protected instance
 *  methods in the receiver. For a module, these are the public and protected methods;
 *  for a class, they are the instance (not singleton) methods. With no
 *  argument, or with an argument that is <code>false</code>, the
 *  instance methods in <i>mod</i> are returned, otherwise the methods
 *  in <i>mod</i> and <i>mod</i>'s superclasses are returned.
 *
 *     module A
 *       def method1()  end
 *     end
 *     class B
 *       def method2()  end
 *     end
 *     class C < B
 *       def method3()  end
 *     end
 *
 *     A.instance_methods                #=> [:method1]
 *     B.instance_methods(false)         #=> [:method2]
 *     C.instance_methods(false)         #=> [:method3]
 *     C.instance_methods(true).length   #=> 43
 */

skandhas's avatar
skandhas committed
1177 1178 1179 1180
static mrb_value
mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
1181
  mrb_bool recur = TRUE;
h2so5's avatar
h2so5 committed
1182
  mrb_get_args(mrb, "|b", &recur);
cremno's avatar
cremno committed
1183
  return mrb_class_instance_method_list(mrb, recur, c, 0);
skandhas's avatar
skandhas committed
1184 1185
}

1186 1187
/* implementation of module_eval/class_eval */
mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
skandhas's avatar
skandhas committed
1188

1189
static mrb_value
1190 1191 1192 1193 1194
mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
{
  return mod;
}

1195
MRB_API mrb_value
mimaki's avatar
mimaki committed
1196 1197 1198 1199 1200 1201
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
  struct RBasic *obj;

  switch (mrb_type(v)) {
  case MRB_TT_FALSE:
1202 1203 1204
    if (mrb_nil_p(v))
      return mrb_obj_value(mrb->nil_class);
    return mrb_obj_value(mrb->false_class);
mimaki's avatar
mimaki committed
1205
  case MRB_TT_TRUE:
1206
    return mrb_obj_value(mrb->true_class);
1207
  case MRB_TT_CPTR:
1208
    return mrb_obj_value(mrb->object_class);
mimaki's avatar
mimaki committed
1209 1210 1211
  case MRB_TT_SYMBOL:
  case MRB_TT_FIXNUM:
  case MRB_TT_FLOAT:
1212 1213
    mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
    return mrb_nil_value();    /* not reached */
mimaki's avatar
mimaki committed
1214
  default:
roco's avatar
roco committed
1215
    break;
mimaki's avatar
mimaki committed
1216
  }
1217
  obj = mrb_basic_ptr(v);
1218
  prepare_singleton_class(mrb, obj);
1219 1220 1221 1222
  if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) {
    mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"),
                   mrb_obj_value(mrb->c->ci->target_class));
  }
mimaki's avatar
mimaki committed
1223 1224 1225
  return mrb_obj_value(obj->c);
}

1226
MRB_API void
1227
mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
mimaki's avatar
mimaki committed
1228
{
1229
  prepare_singleton_class(mrb, (struct RBasic*)o);
1230
  mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
1231 1232
}

1233
MRB_API void
1234
mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
1235
{
1236
  mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
1237 1238
}

1239
MRB_API void
1240
mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
1241 1242 1243 1244 1245
{
  mrb_define_class_method(mrb, c, name, func, aspec);
  mrb_define_method(mrb, c, name, func, aspec);
}

1246
MRB_API struct RProc*
mimaki's avatar
mimaki committed
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
{
  khiter_t k;
  struct RProc *m;
  struct RClass *c = *cp;

  while (c) {
    khash_t(mt) *h = c->mt;

    if (h) {
1257
      k = kh_get(mt, mrb, h, mid);
mimaki's avatar
mimaki committed
1258
      if (k != kh_end(h)) {
roco's avatar
roco committed
1259 1260 1261 1262
        m = kh_value(h, k);
        if (!m) break;
        *cp = c;
        return m;
mimaki's avatar
mimaki committed
1263 1264 1265 1266
      }
    }
    c = c->super;
  }
1267
  return NULL;                  /* no method */
mimaki's avatar
mimaki committed
1268 1269
}

1270
MRB_API struct RProc*
mimaki's avatar
mimaki committed
1271 1272 1273 1274 1275 1276
mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
{
  struct RProc *m;

  m = mrb_method_search_vm(mrb, &c, mid);
  if (!m) {
1277
    mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
1278
    if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
1279 1280
      inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
    }
1281
    mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
1282
               mrb_sym2str(mrb, mid), inspect);
mimaki's avatar
mimaki committed
1283 1284 1285 1286
  }
  return m;
}

1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
static mrb_value
attr_reader(mrb_state *mrb, mrb_value obj)
{
  mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
  return mrb_iv_get(mrb, obj, to_sym(mrb, name));
}

static mrb_value
mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
  mrb_value *argv;
  mrb_int argc, i;
1300
  int ai;
1301 1302

  mrb_get_args(mrb, "*", &argv, &argc);
1303
  ai = mrb_gc_arena_save(mrb);
1304 1305 1306 1307 1308 1309 1310
  for (i=0; i<argc; i++) {
    mrb_value name, str;
    mrb_sym method, sym;

    method = to_sym(mrb, argv[i]);
    name = mrb_sym2str(mrb, method);
    str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
1311
    mrb_str_cat_lit(mrb, str, "@");
1312 1313 1314 1315 1316 1317
    mrb_str_cat_str(mrb, str, name);
    sym = mrb_intern_str(mrb, str);
    mrb_iv_check(mrb, sym);
    name = mrb_symbol_value(sym);
    mrb_define_method_raw(mrb, c, method,
                          mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
1318
    mrb_gc_arena_restore(mrb, ai);
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
  }
  return mrb_nil_value();
}

static mrb_value
attr_writer(mrb_state *mrb, mrb_value obj)
{
  mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
  mrb_value val;

  mrb_get_args(mrb, "o", &val);
  mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
  return val;
}

static mrb_value
mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
  mrb_value *argv;
  mrb_int argc, i;
1340
  int ai;
1341 1342

  mrb_get_args(mrb, "*", &argv, &argc);
1343
  ai = mrb_gc_arena_save(mrb);
1344 1345 1346 1347 1348 1349 1350 1351 1352
  for (i=0; i<argc; i++) {
    mrb_value name, str, attr;
    mrb_sym method, sym;

    method = to_sym(mrb, argv[i]);

    /* prepare iv name (@name) */
    name = mrb_sym2str(mrb, method);
    str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
1353
    mrb_str_cat_lit(mrb, str, "@");
1354 1355 1356 1357 1358 1359 1360 1361
    mrb_str_cat_str(mrb, str, name);
    sym = mrb_intern_str(mrb, str);
    mrb_iv_check(mrb, sym);
    attr = mrb_symbol_value(sym);

    /* prepare method name (name=) */
    str = mrb_str_buf_new(mrb, RSTRING_LEN(str));
    mrb_str_cat_str(mrb, str, name);
1362
    mrb_str_cat_lit(mrb, str, "=");
1363 1364 1365 1366
    method = mrb_intern_str(mrb, str);

    mrb_define_method_raw(mrb, c, method,
                          mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
1367
    mrb_gc_arena_restore(mrb, ai);
1368 1369 1370 1371
  }
  return mrb_nil_value();
}

1372 1373
static mrb_value
mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
mimaki's avatar
mimaki committed
1374
{
1375 1376 1377 1378 1379 1380 1381 1382
  struct RClass *c = mrb_class_ptr(cv);
  struct RObject *o;
  enum mrb_vtype ttype = MRB_INSTANCE_TT(c);

  if (c->tt == MRB_TT_SCLASS)
    mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");

  if (ttype == 0) ttype = MRB_TT_OBJECT;
1383 1384 1385
  if (ttype <= MRB_TT_CPTR) {
    mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
  }
1386 1387
  o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
  return mrb_obj_value(o);
mimaki's avatar
mimaki committed
1388 1389 1390 1391 1392 1393
}

/*
 *  call-seq:
 *     class.new(args, ...)    ->  obj
 *
Jared Breeden's avatar
Jared Breeden committed
1394 1395 1396 1397 1398
 *  Creates a new object of <i>class</i>'s class, then
 *  invokes that object's <code>initialize</code> method,
 *  passing it <i>args</i>. This is the method that ends
 *  up getting called whenever an object is constructed using
 *  `.new`.
mimaki's avatar
mimaki committed
1399 1400 1401
 *
 */

1402
MRB_API mrb_value
mimaki's avatar
mimaki committed
1403 1404
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
1405
  mrb_value obj, blk;
mimaki's avatar
mimaki committed
1406
  mrb_value *argv;
1407
  mrb_int argc;
mimaki's avatar
mimaki committed
1408

1409
  mrb_get_args(mrb, "*&", &argv, &argc, &blk);
1410
  obj = mrb_instance_alloc(mrb, cv);
1411
  mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk);
mimaki's avatar
mimaki committed
1412 1413 1414 1415

  return obj;
}

1416
MRB_API mrb_value
1417
mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv)
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1418
{
1419
  mrb_value obj;
1420
  mrb_sym mid;
1421

1422
  obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
1423 1424 1425 1426
  mid = mrb_intern_lit(mrb, "initialize");
  if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) {
    mrb_funcall_argv(mrb, obj, mid, argc, argv);
  }
1427
  return obj;
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1428 1429
}

1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
static mrb_value
mrb_class_initialize(mrb_state *mrb, mrb_value c)
{
  mrb_value a, b;

  mrb_get_args(mrb, "|C&", &a, &b);
  if (!mrb_nil_p(b)) {
    mrb_yield_with_class(mrb, b, 1, &c, c, mrb_class_ptr(c));
  }
  return c;
}

1442 1443 1444
static mrb_value
mrb_class_new_class(mrb_state *mrb, mrb_value cv)
{
1445
  mrb_int n;
h2so5's avatar
h2so5 committed
1446 1447
  mrb_value super, blk;
  mrb_value new_class;
1448
  mrb_sym mid;
take_cheeze's avatar
take_cheeze committed
1449

1450 1451
  n = mrb_get_args(mrb, "|C&", &super, &blk);
  if (n == 0) {
1452 1453
    super = mrb_obj_value(mrb->object_class);
  }
h2so5's avatar
h2so5 committed
1454
  new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
1455 1456 1457 1458
  mid = mrb_intern_lit(mrb, "initialize");
  if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
    mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
  }
ksss's avatar
ksss committed
1459
  mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
h2so5's avatar
h2so5 committed
1460
  return new_class;
1461 1462
}

1463
static mrb_value
1464 1465
mrb_class_superclass(mrb_state *mrb, mrb_value klass)
{
1466 1467
  struct RClass *c;

1468
  c = mrb_class_ptr(klass);
1469
  c = find_origin(c)->super;
1470
  while (c && c->tt == MRB_TT_ICLASS) {
1471
    c = find_origin(c)->super;
1472 1473 1474
  }
  if (!c) return mrb_nil_value();
  return mrb_obj_value(c);
1475 1476
}

mimaki's avatar
mimaki committed
1477 1478 1479 1480 1481 1482 1483 1484 1485
static mrb_value
mrb_bob_init(mrb_state *mrb, mrb_value cv)
{
  return mrb_nil_value();
}

static mrb_value
mrb_bob_not(mrb_state *mrb, mrb_value cv)
{
1486
  return mrb_bool_value(!mrb_test(cv));
mimaki's avatar
mimaki committed
1487 1488
}

1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
/* 15.3.1.3.1  */
/* 15.3.1.3.10 */
/* 15.3.1.3.11 */
/*
 *  call-seq:
 *     obj == other        -> true or false
 *     obj.equal?(other)   -> true or false
 *     obj.eql?(other)     -> true or false
 *
 *  Equality---At the <code>Object</code> level, <code>==</code> returns
 *  <code>true</code> only if <i>obj</i> and <i>other</i> are the
 *  same object. Typically, this method is overridden in descendant
 *  classes to provide class-specific meaning.
 *
 *  Unlike <code>==</code>, the <code>equal?</code> method should never be
 *  overridden by subclasses: it is used to determine object identity
 *  (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
 *  object as <code>b</code>).
 *
 *  The <code>eql?</code> method returns <code>true</code> if
 *  <i>obj</i> and <i>anObject</i> have the same value. Used by
 *  <code>Hash</code> to test members for equality.  For objects of
 *  class <code>Object</code>, <code>eql?</code> is synonymous with
 *  <code>==</code>. Subclasses normally continue this tradition, but
 *  there are exceptions. <code>Numeric</code> types, for example,
 *  perform type conversion across <code>==</code>, but not across
 *  <code>eql?</code>, so:
 *
 *     1 == 1.0     #=> true
 *     1.eql? 1.0   #=> false
 */
mrb_value
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
{
  mrb_value arg;

  mrb_get_args(mrb, "o", &arg);
  return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
}

static mrb_value
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
{
  mrb_value arg;

  mrb_get_args(mrb, "o", &arg);
  return mrb_bool_value(!mrb_equal(mrb, self, arg));
}

1538
MRB_API mrb_bool
1539
mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
mimaki's avatar
mimaki committed
1540 1541 1542 1543 1544 1545 1546
{
  khiter_t k;

  while (c) {
    khash_t(mt) *h = c->mt;

    if (h) {
1547
      k = kh_get(mt, mrb, h, mid);
1548 1549
      if (k != kh_end(h)) {
        if (kh_value(h, k)) {
1550
          return TRUE;  /* method exists */
1551 1552
        }
        else {
1553
          return FALSE; /* undefined method */
1554 1555
        }
      }
mimaki's avatar
mimaki committed
1556 1557 1558
    }
    c = c->super;
  }
1559
  return FALSE;         /* no method */
mimaki's avatar
mimaki committed
1560 1561
}

1562
MRB_API mrb_bool
mimaki's avatar
mimaki committed
1563 1564
mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
{
1565
  return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid);
mimaki's avatar
mimaki committed
1566 1567
}

1568
MRB_API mrb_value
mimaki's avatar
mimaki committed
1569 1570 1571
mrb_class_path(mrb_state *mrb, struct RClass *c)
{
  mrb_value path;
1572
  const char *name;
1573
  mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__");
mimaki's avatar
mimaki committed
1574

1575
  path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
mimaki's avatar
mimaki committed
1576 1577
  if (mrb_nil_p(path)) {
    struct RClass *outer = mrb_class_outer_module(mrb, c);
1578
    mrb_sym sym = mrb_class_sym(mrb, c, outer);
1579 1580
    mrb_int len;

1581 1582 1583
    if (sym == 0) {
      return mrb_nil_value();
    }
1584
    else if (outer && outer != c && outer != mrb->object_class) {
mimaki's avatar
mimaki committed
1585
      mrb_value base = mrb_class_path(mrb, outer);
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595
      path = mrb_str_buf_new(mrb, 0);
      if (mrb_nil_p(base)) {
        mrb_str_cat_lit(mrb, path, "#<Class:");
        mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, outer));
        mrb_str_cat_lit(mrb, path, ">");
      }
      else {
        mrb_str_concat(mrb, path, base);
      }
      mrb_str_cat_lit(mrb, path, "::");
1596
      name = mrb_sym2name_len(mrb, sym, &len);
1597
      mrb_str_cat(mrb, path, name, len);
mimaki's avatar
mimaki committed
1598 1599
    }
    else {
1600 1601
      name = mrb_sym2name_len(mrb, sym, &len);
      path = mrb_str_new(mrb, name, len);
mimaki's avatar
mimaki committed
1602
    }
1603 1604 1605
    if (!MRB_FROZEN_P(c)) {
      mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
    }
mimaki's avatar
mimaki committed
1606
  }
1607
  return mrb_str_dup(mrb, path);
mimaki's avatar
mimaki committed
1608 1609
}

1610
MRB_API struct RClass *
mimaki's avatar
mimaki committed
1611 1612
mrb_class_real(struct RClass* cl)
{
ksss's avatar
ksss committed
1613
  if (cl == 0)
1614
    return NULL;
mimaki's avatar
mimaki committed
1615 1616 1617 1618 1619 1620
  while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
    cl = cl->super;
  }
  return cl;
}

1621
MRB_API const char*
mimaki's avatar
mimaki committed
1622 1623 1624
mrb_class_name(mrb_state *mrb, struct RClass* c)
{
  mrb_value path = mrb_class_path(mrb, c);
1625
  if (mrb_nil_p(path)) {
1626
    path = mrb_str_new_lit(mrb, "#<Class:");
1627
    mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
1628
    mrb_str_cat_lit(mrb, path, ">");
1629
  }
1630
  return RSTRING_PTR(path);
mimaki's avatar
mimaki committed
1631 1632
}

1633
MRB_API const char*
mimaki's avatar
mimaki committed
1634 1635
mrb_obj_classname(mrb_state *mrb, mrb_value obj)
{
1636
  return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
mimaki's avatar
mimaki committed
1637 1638 1639 1640 1641 1642 1643 1644
}

/*!
 * Ensures a class can be derived from super.
 *
 * \param super a reference to an object.
 * \exception TypeError if \a super is not a Class or \a super is a singleton class.
 */
1645
static void
mimaki's avatar
mimaki committed
1646 1647 1648
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
  if (super->tt != MRB_TT_CLASS) {
1649
    mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
mimaki's avatar
mimaki committed
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
  }
  if (super->tt == MRB_TT_SCLASS) {
    mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
  }
  if (super == mrb->class_class) {
    mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of Class");
  }
}

/*!
 * Creates a new class.
 * \param super     a class from which the new class derives.
 * \exception TypeError \a super is not inheritable.
 * \exception TypeError \a super is the Class class.
1664
 */
1665
MRB_API struct RClass*
mimaki's avatar
mimaki committed
1666 1667 1668 1669 1670 1671 1672 1673
mrb_class_new(mrb_state *mrb, struct RClass *super)
{
  struct RClass *c;

  if (super) {
    mrb_check_inheritable(mrb, super);
  }
  c = boot_defclass(mrb, super);
yui-knk's avatar
yui-knk committed
1674
  if (super) {
Masamitsu MURASE's avatar
Masamitsu MURASE committed
1675 1676
    MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
  }
mimaki's avatar
mimaki committed
1677 1678 1679 1680 1681 1682 1683 1684
  make_metaclass(mrb, c);

  return c;
}

/*!
 * Creates a new module.
 */
1685
MRB_API struct RClass*
mimaki's avatar
mimaki committed
1686 1687
mrb_module_new(mrb_state *mrb)
{
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1688
  struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
1689
  boot_initmod(mrb, m);
mimaki's avatar
mimaki committed
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
  return m;
}

/*
 *  call-seq:
 *     obj.class    => class
 *
 *  Returns the class of <i>obj</i>, now preferred over
 *  <code>Object#type</code>, as an object's type in Ruby is only
 *  loosely tied to that object's class. This method must always be
 *  called with an explicit receiver, as <code>class</code> is also a
 *  reserved word in Ruby.
 *
 *     1.class      #=> Fixnum
 *     self.class   #=> Object
 */

1707
MRB_API struct RClass*
mimaki's avatar
mimaki committed
1708 1709
mrb_obj_class(mrb_state *mrb, mrb_value obj)
{
1710
  return mrb_class_real(mrb_class(mrb, obj));
mimaki's avatar
mimaki committed
1711 1712
}

1713
MRB_API void
mimaki's avatar
mimaki committed
1714 1715 1716
mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
{
  struct RProc *m = mrb_method_search(mrb, c, b);
roco's avatar
roco committed
1717

1718
  mrb_define_method_raw(mrb, c, a, m);
mimaki's avatar
mimaki committed
1719 1720 1721 1722 1723 1724 1725 1726
}

/*!
 * Defines an alias of a method.
 * \param klass  the class which the original method belongs to
 * \param name1  a new name for the method
 * \param name2  the original name of the method
 */
1727
MRB_API void
mimaki's avatar
mimaki committed
1728 1729
mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
{
1730
  mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2));
mimaki's avatar
mimaki committed
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
}

/*
 * call-seq:
 *   mod.to_s   -> string
 *
 * Return a string representing this module or class. For basic
 * classes and modules, this is the name. For singletons, we
 * show information on the thing we're attached to as well.
 */

static mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
1745 1746
  mrb_value str;

mimaki's avatar
mimaki committed
1747
  if (mrb_type(klass) == MRB_TT_SCLASS) {
1748
    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
mimaki's avatar
mimaki committed
1749

1750
    str = mrb_str_new_lit(mrb, "#<Class:");
1751

mimaki's avatar
mimaki committed
1752 1753 1754
    switch (mrb_type(v)) {
      case MRB_TT_CLASS:
      case MRB_TT_MODULE:
1755
      case MRB_TT_SCLASS:
1756
        mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v));
mimaki's avatar
mimaki committed
1757 1758
        break;
      default:
1759
        mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v));
mimaki's avatar
mimaki committed
1760 1761
        break;
    }
1762
    return mrb_str_cat_lit(mrb, str, ">");
mimaki's avatar
mimaki committed
1763 1764
  }
  else {
1765 1766 1767
    struct RClass *c;
    mrb_value path;

1768
    str = mrb_str_buf_new(mrb, 32);
1769 1770
    c = mrb_class_ptr(klass);
    path = mrb_class_path(mrb, c);
roco's avatar
roco committed
1771

1772
    if (mrb_nil_p(path)) {
mimaki's avatar
mimaki committed
1773
      switch (mrb_type(klass)) {
1774
        case MRB_TT_CLASS:
1775
          mrb_str_cat_lit(mrb, str, "#<Class:");
1776 1777 1778
          break;

        case MRB_TT_MODULE:
1779
          mrb_str_cat_lit(mrb, str, "#<Module:");
1780 1781 1782
          break;

        default:
1783
          /* Shouldn't be happened? */
1784
          mrb_str_cat_lit(mrb, str, "#<??????:");
1785
          break;
mimaki's avatar
mimaki committed
1786
      }
1787
      mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
1788
      return mrb_str_cat_lit(mrb, str, ">");
mimaki's avatar
mimaki committed
1789 1790
    }
    else {
1791
      return path;
mimaki's avatar
mimaki committed
1792 1793 1794 1795
    }
  }
}

1796
static mrb_value
mimaki's avatar
mimaki committed
1797 1798 1799
mrb_mod_alias(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
1800
  mrb_sym new_name, old_name;
mimaki's avatar
mimaki committed
1801

1802 1803
  mrb_get_args(mrb, "nn", &new_name, &old_name);
  mrb_alias_method(mrb, c, new_name, old_name);
mimaki's avatar
mimaki committed
1804 1805 1806
  return mrb_nil_value();
}

1807 1808
static void
undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
mimaki's avatar
mimaki committed
1809
{
1810
  if (!mrb_obj_respond_to(mrb, c, a)) {
1811
    mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
1812 1813
  }
  else {
1814
    mrb_define_method_raw(mrb, c, a, NULL);
1815
  }
mimaki's avatar
mimaki committed
1816 1817
}

1818
MRB_API void
1819 1820
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
1821
  undef_method(mrb, c, mrb_intern_cstr(mrb, name));
1822 1823
}

1824
MRB_API void
1825 1826 1827 1828 1829
mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name)
{
  mrb_undef_method(mrb,  mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
}

1830
static mrb_value
mimaki's avatar
mimaki committed
1831 1832 1833
mrb_mod_undef(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
1834
  mrb_int argc;
mimaki's avatar
mimaki committed
1835 1836 1837 1838
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);
  while (argc--) {
1839
    undef_method(mrb, c, to_sym(mrb, *argv));
mimaki's avatar
mimaki committed
1840 1841 1842 1843 1844
    argv++;
  }
  return mrb_nil_value();
}

1845 1846 1847 1848
static mrb_value
mod_define_method(mrb_state *mrb, mrb_value self)
{
  struct RClass *c = mrb_class_ptr(self);
1849
  struct RProc *p;
1850
  mrb_sym mid;
1851
  mrb_value proc = mrb_undef_value();
1852 1853
  mrb_value blk;

1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
  mrb_get_args(mrb, "n|o&", &mid, &proc, &blk);
  switch (mrb_type(proc)) {
    case MRB_TT_PROC:
      blk = proc;
      break;
    case MRB_TT_UNDEF:
      /* ignored */
      break;
    default:
      mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc)));
      break;
  }
1866
  if (mrb_nil_p(blk)) {
1867
    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
1868
  }
1869 1870
  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
  mrb_proc_copy(p, mrb_proc_ptr(blk));
1871
  p->flags |= MRB_PROC_STRICT;
1872
  mrb_define_method_raw(mrb, c, mid, p);
1873
  return mrb_symbol_value(mid);
1874 1875
}

1876 1877 1878 1879
static void
check_cv_name_str(mrb_state *mrb, mrb_value str)
{
  const char *s = RSTRING_PTR(str);
1880 1881
  mrb_int len = RSTRING_LEN(str);

1882
  if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
1883
    mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str);
1884 1885 1886
  }
}

1887 1888 1889 1890 1891 1892
static void
check_cv_name_sym(mrb_state *mrb, mrb_sym id)
{
  check_cv_name_str(mrb, mrb_sym2str(mrb, id));
}

skandhas's avatar
skandhas committed
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910
/* 15.2.2.4.16 */
/*
 *  call-seq:
 *     obj.class_variable_defined?(symbol)    -> true or false
 *
 *  Returns <code>true</code> if the given class variable is defined
 *  in <i>obj</i>.
 *
 *     class Fred
 *       @@foo = 99
 *     end
 *     Fred.class_variable_defined?(:@@foo)    #=> true
 *     Fred.class_variable_defined?(:@@bar)    #=> false
 */

static mrb_value
mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
{
1911
  mrb_sym id;
skandhas's avatar
skandhas committed
1912

1913
  mrb_get_args(mrb, "n", &id);
1914 1915
  check_cv_name_sym(mrb, id);
  return mrb_bool_value(mrb_cv_defined(mrb, mod, id));
skandhas's avatar
skandhas committed
1916 1917
}

skandhas's avatar
skandhas committed
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
/* 15.2.2.4.17 */
/*
 *  call-seq:
 *     mod.class_variable_get(symbol)    -> obj
 *
 *  Returns the value of the given class variable (or throws a
 *  <code>NameError</code> exception). The <code>@@</code> part of the
 *  variable name should be included for regular class variables
 *
 *     class Fred
 *       @@foo = 99
 *     end
 *     Fred.class_variable_get(:@@foo)     #=> 99
 */

static mrb_value
mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod)
{
  mrb_sym id;

1938
  mrb_get_args(mrb, "n", &id);
1939
  check_cv_name_sym(mrb, id);
skandhas's avatar
skandhas committed
1940 1941 1942
  return mrb_cv_get(mrb, mod, id);
}

skandhas's avatar
skandhas committed
1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963
/* 15.2.2.4.18 */
/*
 *  call-seq:
 *     obj.class_variable_set(symbol, obj)    -> obj
 *
 *  Sets the class variable names by <i>symbol</i> to
 *  <i>object</i>.
 *
 *     class Fred
 *       @@foo = 99
 *       def foo
 *         @@foo
 *       end
 *     end
 *     Fred.class_variable_set(:@@foo, 101)     #=> 101
 *     Fred.new.foo                             #=> 101
 */

static mrb_value
mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod)
{
1964
  mrb_value value;
skandhas's avatar
skandhas committed
1965 1966
  mrb_sym id;

1967
  mrb_get_args(mrb, "no", &id, &value);
1968
  check_cv_name_sym(mrb, id);
skandhas's avatar
skandhas committed
1969 1970 1971 1972
  mrb_cv_set(mrb, mod, id, value);
  return value;
}

skandhas's avatar
skandhas committed
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
/* 15.2.2.4.39 */
/*
 *  call-seq:
 *     remove_class_variable(sym)    -> obj
 *
 *  Removes the definition of the <i>sym</i>, returning that
 *  constant's value.
 *
 *     class Dummy
 *       @@var = 99
 *       puts @@var
 *       p class_variables
 *       remove_class_variable(:@@var)
 *       p class_variables
 *     end
 *
 *  <em>produces:</em>
 *
 *     99
 *     [:@@var]
 *     []
 */

1996
static mrb_value
skandhas's avatar
skandhas committed
1997 1998
mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
{
1999
  mrb_value val;
skandhas's avatar
skandhas committed
2000 2001
  mrb_sym id;

2002
  mrb_get_args(mrb, "n", &id);
2003
  check_cv_name_sym(mrb, id);
skandhas's avatar
skandhas committed
2004 2005 2006 2007

  val = mrb_iv_remove(mrb, mod, id);
  if (!mrb_undef_p(val)) return val;

yui-knk's avatar
yui-knk committed
2008
  if (mrb_cv_defined(mrb, mod, id)) {
2009 2010
    mrb_name_error(mrb, id, "cannot remove %S for %S",
                   mrb_sym2str(mrb, id), mod);
skandhas's avatar
skandhas committed
2011 2012
  }

2013 2014
  mrb_name_error(mrb, id, "class variable %S not defined for %S",
                 mrb_sym2str(mrb, id), mod);
skandhas's avatar
skandhas committed
2015 2016 2017 2018 2019

 /* not reached */
 return mrb_nil_value();
}

skandhas's avatar
skandhas committed
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
/* 15.2.2.4.34 */
/*
 *  call-seq:
 *     mod.method_defined?(symbol)    -> true or false
 *
 *  Returns +true+ if the named method is defined by
 *  _mod_ (or its included modules and, if _mod_ is a class,
 *  its ancestors). Public and protected methods are matched.
 *
 *     module A
 *       def method1()  end
 *     end
 *     class B
 *       def method2()  end
 *     end
 *     class C < B
 *       include A
 *       def method3()  end
 *     end
 *
 *     A.method_defined? :method1    #=> true
 *     C.method_defined? "method1"   #=> true
 *     C.method_defined? "method2"   #=> true
 *     C.method_defined? "method3"   #=> true
 *     C.method_defined? "method4"   #=> false
 */

static mrb_value
mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
{
2050
  mrb_sym id;
skandhas's avatar
skandhas committed
2051

2052
  mrb_get_args(mrb, "n", &id);
2053
  return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id));
skandhas's avatar
skandhas committed
2054 2055
}

2056
static void
2057
remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
2058
{
2059
  struct RClass *c = mrb_class_ptr(mod);
2060
  khash_t(mt) *h = find_origin(c)->mt;
2061 2062 2063
  khiter_t k;

  if (h) {
2064
    k = kh_get(mt, mrb, h, mid);
2065
    if (k != kh_end(h)) {
2066
      kh_del(mt, mrb, h, k);
2067
      mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid));
2068 2069 2070 2071
      return;
    }
  }

2072
  mrb_name_error(mrb, mid, "method '%S' not defined in %S",
2073
    mrb_sym2str(mrb, mid), mod);
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084
}

/* 15.2.2.4.41 */
/*
 *  call-seq:
 *     remove_method(symbol)   -> self
 *
 *  Removes the method identified by _symbol_ from the current
 *  class. For an example, see <code>Module.undef_method</code>.
 */

2085
static mrb_value
2086 2087
mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
2088
  mrb_int argc;
2089 2090 2091 2092
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);
  while (argc--) {
2093
    remove_method(mrb, mod, to_sym(mrb, *argv));
2094 2095 2096 2097 2098
    argv++;
  }
  return mod;
}

skandhas's avatar
skandhas committed
2099 2100


2101 2102 2103 2104 2105 2106 2107 2108
static void
check_const_name_str(mrb_state *mrb, mrb_value str)
{
  if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) {
    mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str);
  }
}

2109 2110 2111 2112 2113 2114
static void
check_const_name_sym(mrb_state *mrb, mrb_sym id)
{
  check_const_name_str(mrb, mrb_sym2str(mrb, id));
}

2115 2116 2117 2118 2119 2120 2121 2122 2123
static mrb_value
const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit)
{
  if (inherit) {
    return mrb_bool_value(mrb_const_defined(mrb, mod, id));
  }
  return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
}

2124
static mrb_value
2125 2126
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
{
2127
  mrb_sym id;
2128
  mrb_bool inherit = TRUE;
2129

2130
  mrb_get_args(mrb, "n|b", &id, &inherit);
2131 2132
  check_const_name_sym(mrb, id);
  return const_defined(mrb, mod, id, inherit);
2133 2134
}

2135
static mrb_value
2136 2137
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
2138
  mrb_sym id;
2139

2140
  mrb_get_args(mrb, "n", &id);
2141
  check_const_name_sym(mrb, id);
2142
  return mrb_const_get(mrb, mod, id);
2143 2144
}

2145
static mrb_value
2146 2147
mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
{
2148 2149
  mrb_sym id;
  mrb_value value;
2150

2151
  mrb_get_args(mrb, "no", &id, &value);
2152
  check_const_name_sym(mrb, id);
2153
  mrb_const_set(mrb, mod, id, value);
2154 2155 2156
  return value;
}

2157
static mrb_value
2158 2159
mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
{
2160
  mrb_sym id;
2161 2162
  mrb_value val;

2163
  mrb_get_args(mrb, "n", &id);
2164
  check_const_name_sym(mrb, id);
2165
  val = mrb_iv_remove(mrb, mod, id);
2166
  if (mrb_undef_p(val)) {
2167
    mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
2168 2169 2170
  }
  return val;
}
mimaki's avatar
mimaki committed
2171

2172
static mrb_value
2173 2174 2175 2176 2177
mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
{
  mrb_sym sym;

  mrb_get_args(mrb, "n", &sym);
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187

  if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
    mrb_name_error(mrb, sym, "uninitialized constant %S::%S",
                   mod,
                   mrb_sym2str(mrb, sym));
  }
  else {
    mrb_name_error(mrb, sym, "uninitialized constant %S",
                   mrb_sym2str(mrb, sym));
  }
2188 2189 2190 2191
  /* not reached */
  return mrb_nil_value();
}

2192 2193 2194 2195
static mrb_value
mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
{
  mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
2196
  return mrb_nil_value();       /* not reached */
2197 2198
}

mimaki's avatar
mimaki committed
2199 2200 2201 2202
static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
{
  mrb_value obj;
2203
  mrb_bool eqq;
mimaki's avatar
mimaki committed
2204 2205

  mrb_get_args(mrb, "o", &obj);
2206 2207
  eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));

2208
  return mrb_bool_value(eqq);
mimaki's avatar
mimaki committed
2209 2210
}

2211
MRB_API mrb_value
dreamedge's avatar
dreamedge committed
2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
{
  mrb_value *argv;
  mrb_int argc, i;
  mrb_sym mid;
  struct RProc *method_rproc;
  struct RClass *rclass;
  int ai;

  mrb_check_type(mrb, mod, MRB_TT_MODULE);
Tatsuhiko Kubo's avatar
Tatsuhiko Kubo committed
2222

dreamedge's avatar
dreamedge committed
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247
  mrb_get_args(mrb, "*", &argv, &argc);
  if(argc == 0) {
    /* set MODFUNC SCOPE if implemented */
    return mod;
  }

  /* set PRIVATE method visibility if implemented */
  /* mrb_mod_dummy_visibility(mrb, mod); */

  for (i=0; i<argc; i++) {
    mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);

    mid = mrb_symbol(argv[i]);
    rclass = mrb_class_ptr(mod);
    method_rproc = mrb_method_search(mrb, rclass, mid);

    prepare_singleton_class(mrb, (struct RBasic*)rclass);
    ai = mrb_gc_arena_save(mrb);
    mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
    mrb_gc_arena_restore(mrb, ai);
  }

  return mod;
}

mimaki's avatar
mimaki committed
2248 2249 2250
void
mrb_init_class(mrb_state *mrb)
{
roco's avatar
roco committed
2251 2252 2253 2254
  struct RClass *bob;           /* BasicObject */
  struct RClass *obj;           /* Object */
  struct RClass *mod;           /* Module */
  struct RClass *cls;           /* Class */
mimaki's avatar
mimaki committed
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268

  /* boot class hierarchy */
  bob = boot_defclass(mrb, 0);
  obj = boot_defclass(mrb, bob); mrb->object_class = obj;
  mod = boot_defclass(mrb, obj); mrb->module_class = mod;/* obj -> mod */
  cls = boot_defclass(mrb, mod); mrb->class_class = cls; /* obj -> cls */
  /* fix-up loose ends */
  bob->c = obj->c = mod->c = cls->c = cls;
  make_metaclass(mrb, bob);
  make_metaclass(mrb, obj);
  make_metaclass(mrb, mod);
  make_metaclass(mrb, cls);

  /* name basic classes */
2269
  mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
mimaki's avatar
mimaki committed
2270
  mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2271 2272 2273
  mrb_define_const(mrb, obj, "Object",      mrb_obj_value(obj));
  mrb_define_const(mrb, obj, "Module",      mrb_obj_value(mod));
  mrb_define_const(mrb, obj, "Class",       mrb_obj_value(cls));
mimaki's avatar
mimaki committed
2274 2275

  /* name each classes */
2276
  name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
Yukihiro "Matz" Matsumoto's avatar
Yukihiro "Matz" Matsumoto committed
2277 2278 2279
  name_class(mrb, obj, mrb_intern_lit(mrb, "Object"));           /* 15.2.1 */
  name_class(mrb, mod, mrb_intern_lit(mrb, "Module"));           /* 15.2.2 */
  name_class(mrb, cls, mrb_intern_lit(mrb, "Class"));            /* 15.2.3 */
mimaki's avatar
mimaki committed
2280

2281 2282 2283
  mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);  /* 15.2.17 */
  MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);

mimaki's avatar
mimaki committed
2284
  MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
2285 2286
  mrb_define_method(mrb, bob, "initialize",              mrb_bob_init,             MRB_ARGS_NONE());
  mrb_define_method(mrb, bob, "!",                       mrb_bob_not,              MRB_ARGS_NONE());
2287 2288
  mrb_define_method(mrb, bob, "==",                      mrb_obj_equal_m,          MRB_ARGS_REQ(1)); /* 15.3.1.3.1  */
  mrb_define_method(mrb, bob, "!=",                      mrb_obj_not_equal_m,      MRB_ARGS_REQ(1));
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2289

2290
  mrb_define_class_method(mrb, cls, "new",               mrb_class_new_class,      MRB_ARGS_OPT(1));
2291
  mrb_define_method(mrb, cls, "superclass",              mrb_class_superclass,     MRB_ARGS_NONE()); /* 15.2.3.3.4 */
2292
  mrb_define_method(mrb, cls, "new",                     mrb_instance_new,         MRB_ARGS_ANY());  /* 15.2.3.3.3 */
2293
  mrb_define_method(mrb, cls, "initialize",              mrb_class_initialize,     MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
2294
  mrb_define_method(mrb, cls, "inherited",               mrb_bob_init,             MRB_ARGS_REQ(1));
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2295

2296
  MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
2297 2298 2299 2300 2301
  mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined,     MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */
  mrb_define_method(mrb, mod, "class_variable_get",      mrb_mod_cvar_get,         MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */
  mrb_define_method(mrb, mod, "class_variable_set",      mrb_mod_cvar_set,         MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
  mrb_define_method(mrb, mod, "extend_object",           mrb_mod_extend_object,    MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
  mrb_define_method(mrb, mod, "extended",                mrb_bob_init,             MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
Blaž Hrastnik's avatar
Blaž Hrastnik committed
2302 2303
  mrb_define_method(mrb, mod, "prepended",               mrb_bob_init,             MRB_ARGS_REQ(1));
  mrb_define_method(mrb, mod, "prepend_features",        mrb_mod_prepend_features, MRB_ARGS_REQ(1));
2304 2305 2306 2307 2308
  mrb_define_method(mrb, mod, "include?",                mrb_mod_include_p,        MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
  mrb_define_method(mrb, mod, "append_features",         mrb_mod_append_features,  MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
  mrb_define_method(mrb, mod, "class_eval",              mrb_mod_module_eval,      MRB_ARGS_ANY());  /* 15.2.2.4.15 */
  mrb_define_method(mrb, mod, "included",                mrb_bob_init,             MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
  mrb_define_method(mrb, mod, "included_modules",        mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */
2309
  mrb_define_method(mrb, mod, "initialize",              mrb_mod_initialize,       MRB_ARGS_NONE()); /* 15.2.2.4.31 */
2310 2311 2312
  mrb_define_method(mrb, mod, "instance_methods",        mrb_mod_instance_methods, MRB_ARGS_ANY());  /* 15.2.2.4.33 */
  mrb_define_method(mrb, mod, "method_defined?",         mrb_mod_method_defined,   MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
  mrb_define_method(mrb, mod, "module_eval",             mrb_mod_module_eval,      MRB_ARGS_ANY());  /* 15.2.2.4.35 */
dreamedge's avatar
dreamedge committed
2313
  mrb_define_method(mrb, mod, "module_function",         mrb_mod_module_function,  MRB_ARGS_ANY());
2314 2315 2316
  mrb_define_method(mrb, mod, "private",                 mrb_mod_dummy_visibility, MRB_ARGS_ANY());  /* 15.2.2.4.36 */
  mrb_define_method(mrb, mod, "protected",               mrb_mod_dummy_visibility, MRB_ARGS_ANY());  /* 15.2.2.4.37 */
  mrb_define_method(mrb, mod, "public",                  mrb_mod_dummy_visibility, MRB_ARGS_ANY());  /* 15.2.2.4.38 */
2317 2318
  mrb_define_method(mrb, mod, "remove_class_variable",   mrb_mod_remove_cvar,      MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
  mrb_define_method(mrb, mod, "remove_method",           mrb_mod_remove_method,    MRB_ARGS_ANY());  /* 15.2.2.4.41 */
2319
  mrb_define_method(mrb, mod, "method_removed",          mrb_bob_init,             MRB_ARGS_REQ(1));
2320 2321
  mrb_define_method(mrb, mod, "attr_reader",             mrb_mod_attr_reader,      MRB_ARGS_ANY());  /* 15.2.2.4.13 */
  mrb_define_method(mrb, mod, "attr_writer",             mrb_mod_attr_writer,      MRB_ARGS_ANY());  /* 15.2.2.4.14 */
2322 2323 2324 2325 2326
  mrb_define_method(mrb, mod, "to_s",                    mrb_mod_to_s,             MRB_ARGS_NONE());
  mrb_define_method(mrb, mod, "inspect",                 mrb_mod_to_s,             MRB_ARGS_NONE());
  mrb_define_method(mrb, mod, "alias_method",            mrb_mod_alias,            MRB_ARGS_ANY());  /* 15.2.2.4.8 */
  mrb_define_method(mrb, mod, "ancestors",               mrb_mod_ancestors,        MRB_ARGS_NONE()); /* 15.2.2.4.9 */
  mrb_define_method(mrb, mod, "undef_method",            mrb_mod_undef,            MRB_ARGS_ANY());  /* 15.2.2.4.41 */
2327
  mrb_define_method(mrb, mod, "const_defined?",          mrb_mod_const_defined,    MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */
2328 2329
  mrb_define_method(mrb, mod, "const_get",               mrb_mod_const_get,        MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */
  mrb_define_method(mrb, mod, "const_set",               mrb_mod_const_set,        MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
2330
  mrb_define_method(mrb, mod, "constants",               mrb_mod_constants,        MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
2331
  mrb_define_method(mrb, mod, "remove_const",            mrb_mod_remove_const,     MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
2332
  mrb_define_method(mrb, mod, "const_missing",           mrb_mod_const_missing,    MRB_ARGS_REQ(1));
2333
  mrb_define_method(mrb, mod, "define_method",           mod_define_method,        MRB_ARGS_ARG(1,1));
2334 2335 2336
  mrb_define_method(mrb, mod, "class_variables",         mrb_mod_class_variables,  MRB_ARGS_NONE()); /* 15.2.2.4.19 */
  mrb_define_method(mrb, mod, "===",                     mrb_mod_eqq,              MRB_ARGS_REQ(1));
  mrb_define_class_method(mrb, mod, "constants",         mrb_mod_s_constants,      MRB_ARGS_ANY());  /* 15.2.2.3.1 */
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2337

2338
  mrb_undef_method(mrb, cls, "append_features");
2339
  mrb_undef_method(mrb, cls, "extend_object");
mimaki's avatar
mimaki committed
2340
}