class.c 60.6 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
}

ksss's avatar
ksss committed
243 244 245 246 247 248 249 250
static void
mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
{
  if (!super)
    super = mrb->object_class;
  mrb_funcall(mrb, mrb_obj_value(super), "inherited", 1, mrb_obj_value(klass));
}

251
MRB_API struct RClass*
mimaki's avatar
mimaki committed
252 253
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
254 255
  struct RClass *s;
  struct RClass *c;
mimaki's avatar
mimaki committed
256

257 258
  if (!mrb_nil_p(super)) {
    if (mrb_type(super) != MRB_TT_CLASS) {
259
      mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
260
    }
261
    s = mrb_class_ptr(super);
mimaki's avatar
mimaki committed
262
  }
263
  else {
264
    s = 0;
265
  }
266
  check_if_class_or_module(mrb, outer);
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
  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;
  }
282
  c = define_class(mrb, id, s, mrb_class_ptr(outer));
ksss's avatar
ksss committed
283
  mrb_class_inherited(mrb, mrb_class_real(c->super), c);
mimaki's avatar
mimaki committed
284 285 286 287

  return c;
}

288
MRB_API mrb_bool
289 290
mrb_class_defined(mrb_state *mrb, const char *name)
{
291
  mrb_value sym = mrb_check_intern_cstr(mrb, name);
292 293 294 295
  if (mrb_nil_p(sym)) {
    return FALSE;
  }
  return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
296 297
}

298
MRB_API mrb_bool
299
mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name)
300 301 302 303 304 305 306 307
{
  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));
}

308
MRB_API struct RClass *
309
mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
310
{
311
  return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
312 313
}

314
MRB_API struct RClass *
315 316
mrb_class_get(mrb_state *mrb, const char *name)
{
h2so5's avatar
h2so5 committed
317 318 319
  return mrb_class_get_under(mrb, mrb->object_class, name);
}

320 321 322 323 324 325 326 327 328 329 330 331 332 333
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;
}

334
MRB_API struct RClass *
335
mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
h2so5's avatar
h2so5 committed
336
{
337 338 339
  return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
}

340
MRB_API struct RClass *
341 342 343
mrb_module_get(mrb_state *mrb, const char *name)
{
  return mrb_module_get_under(mrb, mrb->object_class, name);
344 345
}

mimaki's avatar
mimaki committed
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
/*!
 * 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.
 */
362
MRB_API struct RClass *
mimaki's avatar
mimaki committed
363 364
mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
{
365
  mrb_sym id = mrb_intern_cstr(mrb, name);
mimaki's avatar
mimaki committed
366 367
  struct RClass * c;

368 369
#if 0
  if (!super) {
370
    mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
371
             mrb_obj_value(outer), mrb_sym2str(mrb, id));
mimaki's avatar
mimaki committed
372
  }
373 374 375
#endif
  c = define_class(mrb, id, super, outer);
  setup_class(mrb, outer, c, id);
mimaki's avatar
mimaki committed
376 377 378
  return c;
}

379
MRB_API void
mimaki's avatar
mimaki committed
380 381
mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
{
382
  khash_t(mt) *h;
mimaki's avatar
mimaki committed
383
  khiter_t k;
384 385
  MRB_CLASS_ORIGIN(c);
  h = c->mt;
mimaki's avatar
mimaki committed
386

387 388 389 390 391 392
  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
393
  if (!h) h = c->mt = kh_init(mt, mrb);
394
  k = kh_put(mt, mrb, h, mid);
mimaki's avatar
mimaki committed
395
  kh_value(h, k) = p;
Masamitsu MURASE's avatar
Masamitsu MURASE committed
396 397 398
  if (p) {
    mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
  }
mimaki's avatar
mimaki committed
399 400
}

401
MRB_API void
402
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
403 404
{
  struct RProc *p;
405
  int ai = mrb_gc_arena_save(mrb);
mimaki's avatar
mimaki committed
406 407

  p = mrb_proc_new_cfunc(mrb, func);
take_cheeze's avatar
take_cheeze committed
408
  p->target_class = c;
mimaki's avatar
mimaki committed
409
  mrb_define_method_raw(mrb, c, mid, p);
410
  mrb_gc_arena_restore(mrb, ai);
mimaki's avatar
mimaki committed
411 412
}

413
MRB_API void
414
mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
mimaki's avatar
mimaki committed
415
{
416
  mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
417 418
}

419 420 421
/* a function to raise NotImplementedError with current method name */
MRB_API void
mrb_notimplement(mrb_state *mrb)
ksss's avatar
ksss committed
422 423 424 425 426 427 428 429
{
  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
430
      "%S() function is unimplemented on this machine",
ksss's avatar
ksss committed
431 432
      mrb_str_new_static(mrb, str, (size_t)len));
  }
433 434 435 436 437 438 439 440
}

/* 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
441 442 443
  return mrb_nil_value();
}

444 445 446 447 448 449 450
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)) {
451
    mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
  }
  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");
}

474 475 476 477 478 479 480 481 482 483 484 485
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);
486 487
    /* not reached */
    return 0;
488 489 490
  }
}

491 492 493 494
/*
  retrieve arguments from mrb_state.

  mrb_get_args(mrb, format, ...)
495

496 497
  returns number of arguments parsed.

Carson McDonald's avatar
Carson McDonald committed
498
  format specifiers:
499

500 501 502
    string  mruby type     C type                 note
    ----------------------------------------------------------------------------------------------
    o:      Object         [mrb_value]
503
    C:      class/module   [mrb_value]
504 505 506
    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
507 508 509
    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
510 511 512 513
    f:      Float          [mrb_float]
    i:      Integer        [mrb_int]
    b:      Boolean        [mrb_bool]
    n:      Symbol         [mrb_sym]
514
    d:      Data           [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
515
    I:      Inline struct  [void*]
516
    &:      Block          [mrb_value]
517
    *:      rest argument  [mrb_value*,mrb_int]   Receive the rest of the arguments as an array.
518
    |:      optional                              Next argument of '|' and later are optional.
519
    ?:      optional given [mrb_bool]             true if preceding argument (optional) is given.
520
 */
521
MRB_API mrb_int
mimaki's avatar
mimaki committed
522 523 524
mrb_get_args(mrb_state *mrb, const char *format, ...)
{
  char c;
525
  int i = 0;
mimaki's avatar
mimaki committed
526
  va_list ap;
527
  int argc = mrb->c->ci->argc;
528 529
  int arg_i = 0;
  mrb_bool array_argv;
Jun Hiroe's avatar
Jun Hiroe committed
530 531
  mrb_bool opt = FALSE;
  mrb_bool given = TRUE;
mimaki's avatar
mimaki committed
532 533 534

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

    argc = a->len;
538 539 540
    array_argv = TRUE;
  } else {
    array_argv = FALSE;
mimaki's avatar
mimaki committed
541
  }
542 543 544 545

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

mimaki's avatar
mimaki committed
546
  while ((c = *format++)) {
547
    switch (c) {
548
    case '|': case '*': case '&': case '?':
549 550
      break;
    default:
551 552
      if (argc <= i) {
        if (opt) {
Jun Hiroe's avatar
Jun Hiroe committed
553
          given = FALSE;
554 555 556 557
        }
        else {
          mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
        }
558
      }
559
      break;
560
    }
561

mimaki's avatar
mimaki committed
562 563 564 565
    switch (c) {
    case 'o':
      {
        mrb_value *p;
566

mimaki's avatar
mimaki committed
567
        p = va_arg(ap, mrb_value*);
skandhas's avatar
skandhas committed
568
        if (i < argc) {
569
          *p = ARGV[arg_i++];
skandhas's avatar
skandhas committed
570 571
          i++;
        }
mimaki's avatar
mimaki committed
572 573
      }
      break;
574 575 576 577 578 579 580 581
    case 'C':
      {
        mrb_value *p;

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

582
          ss = ARGV[arg_i++];
583 584 585 586 587 588 589 590 591 592 593 594 595 596
          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;
597
    case 'S':
mimaki's avatar
mimaki committed
598
      {
599
        mrb_value *p;
mimaki's avatar
mimaki committed
600

601
        p = va_arg(ap, mrb_value*);
602 603
        if (*format == '!') {
          format++;
604 605
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
606 607 608 609
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
610
        if (i < argc) {
611
          *p = to_str(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
612 613
          i++;
        }
614 615 616 617 618
      }
      break;
    case 'A':
      {
        mrb_value *p;
619

620
        p = va_arg(ap, mrb_value*);
621 622
        if (*format == '!') {
          format++;
623 624
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
625 626 627 628
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
629
        if (i < argc) {
630
          *p = to_ary(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
631 632
          i++;
        }
633 634 635 636 637 638 639
      }
      break;
    case 'H':
      {
        mrb_value *p;

        p = va_arg(ap, mrb_value*);
640 641
        if (*format == '!') {
          format++;
642 643
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
            *p = ARGV[arg_i++];
644 645 646 647
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
648
        if (i < argc) {
649
          *p = to_hash(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
650 651
          i++;
        }
652 653 654 655
      }
      break;
    case 's':
      {
skandhas's avatar
skandhas committed
656
        mrb_value ss;
657
        char **ps = 0;
658
        mrb_int *pl = 0;
659

skandhas's avatar
skandhas committed
660
        ps = va_arg(ap, char**);
661
        pl = va_arg(ap, mrb_int*);
662 663
        if (*format == '!') {
          format++;
664
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
665 666 667 668 669 670
            *ps = NULL;
            *pl = 0;
            i++;
            break;
          }
        }
skandhas's avatar
skandhas committed
671
        if (i < argc) {
672
          ss = to_str(mrb, ARGV[arg_i++]);
673 674
          *ps = RSTRING_PTR(ss);
          *pl = RSTRING_LEN(ss);
skandhas's avatar
skandhas committed
675 676
          i++;
        }
677 678 679 680
      }
      break;
    case 'z':
      {
skandhas's avatar
skandhas committed
681
        mrb_value ss;
682
        const char **ps;
683

684
        ps = va_arg(ap, const char**);
685 686
        if (*format == '!') {
          format++;
687
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
688
            *ps = NULL;
689
            i++; arg_i++;
690 691 692
            break;
          }
        }
skandhas's avatar
skandhas committed
693
        if (i < argc) {
694
          ss = to_str(mrb, ARGV[arg_i++]);
695
          *ps = mrb_string_value_cstr(mrb, &ss);
skandhas's avatar
skandhas committed
696 697
          i++;
        }
698 699 700 701
      }
      break;
    case 'a':
      {
skandhas's avatar
skandhas committed
702
        mrb_value aa;
703 704
        struct RArray *a;
        mrb_value **pb;
705
        mrb_int *pl;
706

skandhas's avatar
skandhas committed
707
        pb = va_arg(ap, mrb_value**);
708
        pl = va_arg(ap, mrb_int*);
709 710
        if (*format == '!') {
          format++;
711
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
712 713
            *pb = 0;
            *pl = 0;
714
            i++; arg_i++;
715 716 717
            break;
          }
        }
skandhas's avatar
skandhas committed
718
        if (i < argc) {
719
          aa = to_ary(mrb, ARGV[arg_i++]);
skandhas's avatar
skandhas committed
720 721 722 723 724
          a = mrb_ary_ptr(aa);
          *pb = a->ptr;
          *pl = a->len;
          i++;
        }
mimaki's avatar
mimaki committed
725 726
      }
      break;
727 728 729 730 731 732 733 734
    case 'I':
      {
        void* *p;
        mrb_value ss;

        p = va_arg(ap, void**);
        if (i < argc) {
          ss = ARGV[arg_i];
735
          if (mrb_type(ss) != MRB_TT_ISTRUCT)
736 737 738
          {
            mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss);
          }
739
          *p = mrb_istruct_ptr(ss);
740 741 742 743 744
          arg_i++;
          i++;
        }
      }
      break;
mimaki's avatar
mimaki committed
745 746 747 748 749
    case 'f':
      {
        mrb_float *p;

        p = va_arg(ap, mrb_float*);
skandhas's avatar
skandhas committed
750
        if (i < argc) {
751 752
          *p = mrb_to_flo(mrb, ARGV[arg_i]);
          arg_i++;
skandhas's avatar
skandhas committed
753 754
          i++;
        }
mimaki's avatar
mimaki committed
755 756
      }
      break;
757
    case 'i':
mimaki's avatar
mimaki committed
758
      {
759
        mrb_int *p;
mimaki's avatar
mimaki committed
760

761
        p = va_arg(ap, mrb_int*);
skandhas's avatar
skandhas committed
762
        if (i < argc) {
763
          switch (mrb_type(ARGV[arg_i])) {
skandhas's avatar
skandhas committed
764
            case MRB_TT_FIXNUM:
765
              *p = mrb_fixnum(ARGV[arg_i]);
skandhas's avatar
skandhas committed
766 767 768
              break;
            case MRB_TT_FLOAT:
              {
769
                mrb_float f = mrb_float(ARGV[arg_i]);
skandhas's avatar
skandhas committed
770 771 772 773 774 775 776

                if (!FIXABLE(f)) {
                  mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
                }
                *p = (mrb_int)f;
              }
              break;
777
            case MRB_TT_STRING:
778
              mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
779
              break;
skandhas's avatar
skandhas committed
780
            default:
781
              *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
skandhas's avatar
skandhas committed
782 783
              break;
          }
784
          arg_i++;
skandhas's avatar
skandhas committed
785 786
          i++;
        }
mimaki's avatar
mimaki committed
787 788
      }
      break;
789 790
    case 'b':
      {
791
        mrb_bool *boolp = va_arg(ap, mrb_bool*);
792

skandhas's avatar
skandhas committed
793
        if (i < argc) {
794
          mrb_value b = ARGV[arg_i++];
skandhas's avatar
skandhas committed
795 796 797
          *boolp = mrb_test(b);
          i++;
        }
798 799
      }
      break;
800 801
    case 'n':
      {
skandhas's avatar
skandhas committed
802 803 804 805 806 807
        mrb_sym *symp;

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

808
          ss = ARGV[arg_i++];
809
          *symp = to_sym(mrb, ss);
skandhas's avatar
skandhas committed
810 811
          i++;
        }
812 813
      }
      break;
814 815 816 817 818 819 820
    case 'd':
      {
        void** datap;
        struct mrb_data_type const* type;

        datap = va_arg(ap, void**);
        type = va_arg(ap, struct mrb_data_type const*);
821 822
        if (*format == '!') {
          format++;
823
          if (i < argc && mrb_nil_p(ARGV[arg_i])) {
824
            *datap = 0;
825
            i++; arg_i++;
826 827 828
            break;
          }
        }
829
        if (i < argc) {
830
          *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type);
831 832 833 834
          ++i;
        }
      }
      break;
mimaki's avatar
mimaki committed
835 836 837

    case '&':
      {
838
        mrb_value *p, *bp;
mimaki's avatar
mimaki committed
839 840

        p = va_arg(ap, mrb_value*);
841 842
        if (mrb->c->ci->argc < 0) {
          bp = mrb->c->stack + 2;
roco's avatar
roco committed
843
        }
skandhas's avatar
skandhas committed
844
        else {
845
          bp = mrb->c->stack + mrb->c->ci->argc + 1;
skandhas's avatar
skandhas committed
846
        }
roco's avatar
roco committed
847
        *p = *bp;
mimaki's avatar
mimaki committed
848 849
      }
      break;
850
    case '|':
Jun Hiroe's avatar
Jun Hiroe committed
851
      opt = TRUE;
852
      break;
853 854 855 856 857 858 859 860
    case '?':
      {
        mrb_bool *p;

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

mimaki's avatar
mimaki committed
862 863 864
    case '*':
      {
        mrb_value **var;
865
        mrb_int *pl;
866

mimaki's avatar
mimaki committed
867
        var = va_arg(ap, mrb_value**);
868
        pl = va_arg(ap, mrb_int*);
roco's avatar
roco committed
869
        if (argc > i) {
870 871
          *pl = argc-i;
          if (*pl > 0) {
872
            *var = ARGV + arg_i;
roco's avatar
roco committed
873
          }
skandhas's avatar
skandhas committed
874
          i = argc;
875
          arg_i += *pl;
roco's avatar
roco committed
876 877
        }
        else {
878
          *pl = 0;
roco's avatar
roco committed
879 880
          *var = NULL;
        }
mimaki's avatar
mimaki committed
881 882
      }
      break;
883
    default:
884
      mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
885
      break;
mimaki's avatar
mimaki committed
886 887
    }
  }
888 889 890

#undef ARGV

891
  if (!c && argc > i) {
892 893
    mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
  }
mimaki's avatar
mimaki committed
894
  va_end(ap);
895
  return i;
mimaki's avatar
mimaki committed
896 897 898 899 900 901 902
}

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

Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
903
  c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
904 905 906 907 908 909 910
  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
911 912 913 914
  c->mt = kh_init(mt, mrb);
  return c;
}

915 916 917 918 919 920
static void
boot_initmod(mrb_state *mrb, struct RClass *mod)
{
  mod->mt = kh_init(mt, mrb);
}

921 922 923 924 925 926 927
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;
  }
928
  MRB_CLASS_ORIGIN(m);
929
  ic->iv = m->iv;
930
  ic->mt = m->mt;
931 932 933 934 935 936 937 938 939
  ic->super = super;
  if (m->tt == MRB_TT_ICLASS) {
    ic->c = m->c;
  } else {
    ic->c = m;
  }
  return ic;
}

940
static int
941
include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super)
mimaki's avatar
mimaki committed
942
{
943
  struct RClass *p, *ic;
944
  void *klass_mt = find_origin(c)->mt;
mimaki's avatar
mimaki committed
945

946
  while (m) {
947 948
    int superclass_seen = 0;

949
    if (m->flags & MRB_FLAG_IS_PREPENDED)
950 951
      goto skip;

952
    if (klass_mt && klass_mt == m->mt)
953 954
      return -1;

955
    p = c->super;
956 957
    while(p) {
      if (p->tt == MRB_TT_ICLASS) {
958
        if (p->mt == m->mt) {
959
          if (!superclass_seen) {
960
            ins_pos = p; // move insert point
961 962
          }
          goto skip;
skandhas's avatar
skandhas committed
963
        }
964
      } else if (p->tt == MRB_TT_CLASS) {
Blaž Hrastnik's avatar
Blaž Hrastnik committed
965
        if (!search_super) break;
skandhas's avatar
skandhas committed
966
        superclass_seen = 1;
967
      }
968 969
      p = p->super;
    }
970

971
    ic = include_class_new(mrb, m, ins_pos->super);
972
    ins_pos->super = ic;
973
    mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super);
974 975
    ins_pos = ic;
  skip:
976 977
    m = m->super;
  }
978
  return 0;
mimaki's avatar
mimaki committed
979 980
}

Blaž Hrastnik's avatar
Blaž Hrastnik committed
981 982 983
MRB_API void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
984
  int changed = include_module_at(mrb, c, find_origin(c), m, 1);
985 986 987
  if (changed < 0) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
  }
Blaž Hrastnik's avatar
Blaž Hrastnik committed
988 989 990 991 992 993 994 995
}

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

996
  if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
Blaž Hrastnik's avatar
Blaž Hrastnik committed
997
    origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
998
    origin->flags |= MRB_FLAG_IS_ORIGIN;
Blaž Hrastnik's avatar
Blaž Hrastnik committed
999 1000 1001 1002
    origin->super = c->super;
    c->super = origin;
    origin->mt = c->mt;
    c->mt = kh_init(mt, mrb);
1003 1004
    mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
    c->flags |= MRB_FLAG_IS_PREPENDED;
Blaž Hrastnik's avatar
Blaž Hrastnik committed
1005
  }
1006 1007 1008
  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
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
  }
}

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
1023
static mrb_value
1024
mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mimaki's avatar
mimaki committed
1025
{
1026
  mrb_value klass;
mimaki's avatar
mimaki committed
1027

1028
  mrb_check_type(mrb, mod, MRB_TT_MODULE);
1029
  mrb_get_args(mrb, "C", &klass);
mimaki's avatar
mimaki committed
1030 1031 1032 1033
  mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
  return mod;
}

skandhas's avatar
skandhas committed
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
/* 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
1053 1054 1055 1056 1057 1058
static mrb_value
mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
{
  mrb_value mod2;
  struct RClass *c = mrb_class_ptr(mod);

1059
  mrb_get_args(mrb, "C", &mod2);
skandhas's avatar
skandhas committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
  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();
}
1070

1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
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));
    }
1081
    else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
1082 1083 1084 1085 1086 1087 1088 1089
      mrb_ary_push(mrb, result, mrb_obj_value(c));
    }
    c = c->super;
  }

  return result;
}

1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
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;
}

1101 1102 1103 1104 1105
static mrb_value
mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
{
  mrb_value result;
  struct RClass *c = mrb_class_ptr(self);
1106
  struct RClass *origin = c;
1107

1108
  MRB_CLASS_ORIGIN(origin);
1109 1110
  result = mrb_ary_new(mrb);
  while (c) {
1111
    if (c != origin && c->tt == MRB_TT_ICLASS) {
1112 1113 1114
      if (c->c->tt == MRB_TT_MODULE) {
        mrb_ary_push(mrb, result, mrb_obj_value(c->c));
      }
1115 1116 1117 1118 1119 1120 1121
    }
    c = c->super;
  }

  return result;
}

1122 1123 1124 1125
static mrb_value
mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
{
  mrb_value b;
1126
  struct RClass *m = mrb_class_ptr(mod);
1127 1128
  boot_initmod(mrb, m); // bootstrap a newly initialized module
  mrb_get_args(mrb, "|&", &b);
1129
  if (!mrb_nil_p(b)) {
1130
    mrb_yield_with_class(mrb, b, 1, &mod, mod, m);
1131 1132 1133 1134
  }
  return mod;
}

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

1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
/* 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
1165 1166 1167 1168
static mrb_value
mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
1169
  mrb_bool recur = TRUE;
h2so5's avatar
h2so5 committed
1170
  mrb_get_args(mrb, "|b", &recur);
cremno's avatar
cremno committed
1171
  return mrb_class_instance_method_list(mrb, recur, c, 0);
skandhas's avatar
skandhas committed
1172 1173
}

1174 1175
/* implementation of module_eval/class_eval */
mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
skandhas's avatar
skandhas committed
1176

1177
static mrb_value
1178 1179 1180 1181 1182
mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
{
  return mod;
}

1183
MRB_API mrb_value
mimaki's avatar
mimaki committed
1184 1185 1186 1187 1188 1189
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
  struct RBasic *obj;

  switch (mrb_type(v)) {
  case MRB_TT_FALSE:
1190 1191 1192
    if (mrb_nil_p(v))
      return mrb_obj_value(mrb->nil_class);
    return mrb_obj_value(mrb->false_class);
mimaki's avatar
mimaki committed
1193
  case MRB_TT_TRUE:
1194
    return mrb_obj_value(mrb->true_class);
1195
  case MRB_TT_CPTR:
1196
    return mrb_obj_value(mrb->object_class);
mimaki's avatar
mimaki committed
1197 1198 1199
  case MRB_TT_SYMBOL:
  case MRB_TT_FIXNUM:
  case MRB_TT_FLOAT:
1200 1201
    mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
    return mrb_nil_value();    /* not reached */
mimaki's avatar
mimaki committed
1202
  default:
roco's avatar
roco committed
1203
    break;
mimaki's avatar
mimaki committed
1204
  }
1205
  obj = mrb_basic_ptr(v);
1206
  prepare_singleton_class(mrb, obj);
1207 1208 1209 1210
  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
1211 1212 1213
  return mrb_obj_value(obj->c);
}

1214
MRB_API void
1215
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
1216
{
1217
  prepare_singleton_class(mrb, (struct RBasic*)o);
1218
  mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
1219 1220
}

1221
MRB_API void
1222
mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
1223
{
1224
  mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
1225 1226
}

1227
MRB_API void
1228
mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
1229 1230 1231 1232 1233
{
  mrb_define_class_method(mrb, c, name, func, aspec);
  mrb_define_method(mrb, c, name, func, aspec);
}

1234
MRB_API struct RProc*
mimaki's avatar
mimaki committed
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
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) {
1245
      k = kh_get(mt, mrb, h, mid);
mimaki's avatar
mimaki committed
1246
      if (k != kh_end(h)) {
roco's avatar
roco committed
1247 1248 1249 1250
        m = kh_value(h, k);
        if (!m) break;
        *cp = c;
        return m;
mimaki's avatar
mimaki committed
1251 1252 1253 1254
      }
    }
    c = c->super;
  }
1255
  return NULL;                  /* no method */
mimaki's avatar
mimaki committed
1256 1257
}

1258
MRB_API struct RProc*
mimaki's avatar
mimaki committed
1259 1260 1261 1262 1263 1264
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) {
1265
    mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
1266
    if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
1267 1268
      inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
    }
1269
    mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
1270
               mrb_sym2str(mrb, mid), inspect);
mimaki's avatar
mimaki committed
1271 1272 1273 1274
  }
  return m;
}

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
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;
1288
  int ai;
1289 1290

  mrb_get_args(mrb, "*", &argv, &argc);
1291
  ai = mrb_gc_arena_save(mrb);
1292 1293 1294 1295 1296 1297 1298
  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);
1299
    mrb_str_cat_lit(mrb, str, "@");
1300 1301 1302 1303 1304 1305
    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));
1306
    mrb_gc_arena_restore(mrb, ai);
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
  }
  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;
1328
  int ai;
1329 1330

  mrb_get_args(mrb, "*", &argv, &argc);
1331
  ai = mrb_gc_arena_save(mrb);
1332 1333 1334 1335 1336 1337 1338 1339 1340
  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);
1341
    mrb_str_cat_lit(mrb, str, "@");
1342 1343 1344 1345 1346 1347 1348 1349
    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);
1350
    mrb_str_cat_lit(mrb, str, "=");
1351 1352 1353 1354
    method = mrb_intern_str(mrb, str);

    mrb_define_method_raw(mrb, c, method,
                          mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
1355
    mrb_gc_arena_restore(mrb, ai);
1356 1357 1358 1359
  }
  return mrb_nil_value();
}

1360 1361
static mrb_value
mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
mimaki's avatar
mimaki committed
1362
{
1363 1364 1365 1366 1367 1368 1369 1370
  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;
1371 1372 1373
  if (ttype <= MRB_TT_CPTR) {
    mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
  }
1374 1375
  o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
  return mrb_obj_value(o);
mimaki's avatar
mimaki committed
1376 1377 1378 1379 1380 1381
}

/*
 *  call-seq:
 *     class.new(args, ...)    ->  obj
 *
Jared Breeden's avatar
Jared Breeden committed
1382 1383 1384 1385 1386
 *  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
1387 1388 1389
 *
 */

1390
MRB_API mrb_value
mimaki's avatar
mimaki committed
1391 1392
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
1393
  mrb_value obj, blk;
mimaki's avatar
mimaki committed
1394
  mrb_value *argv;
1395
  mrb_int argc;
mimaki's avatar
mimaki committed
1396

1397
  mrb_get_args(mrb, "*&", &argv, &argc, &blk);
1398
  obj = mrb_instance_alloc(mrb, cv);
1399
  mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk);
mimaki's avatar
mimaki committed
1400 1401 1402 1403

  return obj;
}

1404
MRB_API mrb_value
1405
mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv)
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1406
{
1407
  mrb_value obj;
1408

1409
  obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
1410
  mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv);
1411 1412

  return obj;
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1413 1414
}

1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
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;
}

1427 1428 1429
static mrb_value
mrb_class_new_class(mrb_state *mrb, mrb_value cv)
{
1430
  mrb_int n;
h2so5's avatar
h2so5 committed
1431 1432
  mrb_value super, blk;
  mrb_value new_class;
take_cheeze's avatar
take_cheeze committed
1433

1434 1435
  n = mrb_get_args(mrb, "|C&", &super, &blk);
  if (n == 0) {
1436 1437
    super = mrb_obj_value(mrb->object_class);
  }
h2so5's avatar
h2so5 committed
1438
  new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
1439
  mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "initialize"), n, &super, blk);
ksss's avatar
ksss committed
1440
  mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
h2so5's avatar
h2so5 committed
1441
  return new_class;
1442 1443
}

1444
static mrb_value
1445 1446
mrb_class_superclass(mrb_state *mrb, mrb_value klass)
{
1447 1448
  struct RClass *c;

1449
  c = mrb_class_ptr(klass);
1450
  c = find_origin(c)->super;
1451
  while (c && c->tt == MRB_TT_ICLASS) {
1452
    c = find_origin(c)->super;
1453 1454 1455
  }
  if (!c) return mrb_nil_value();
  return mrb_obj_value(c);
1456 1457
}

mimaki's avatar
mimaki committed
1458 1459 1460 1461 1462 1463 1464 1465 1466
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)
{
1467
  return mrb_bool_value(!mrb_test(cv));
mimaki's avatar
mimaki committed
1468 1469
}

1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
void
mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
{
  mrb_sym inspect;
  mrb_value repr;

  inspect = mrb_intern_lit(mrb, "inspect");
  if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
    /* method missing in inspect; avoid recursion */
    repr = mrb_any_to_s(mrb, self);
  }
  else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
    repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
    if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
      repr = mrb_any_to_s(mrb, self);
    }
  }
  else {
    repr = mrb_any_to_s(mrb, self);
  }

  mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
                      mrb_sym2str(mrb, name), repr);
}

mimaki's avatar
mimaki committed
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
/* 15.3.1.3.30 */
/*
 *  call-seq:
 *     obj.method_missing(symbol [, *args] )   -> result
 *
 *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
 *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
 *  are any arguments that were passed to it. By default, the interpreter
 *  raises an error when this method is called. However, it is possible
 *  to override the method to provide more dynamic behavior.
 *  If it is decided that a particular method should not be handled, then
 *  <i>super</i> should be called, so that ancestors can pick up the
 *  missing method.
 *  The example below creates
 *  a class <code>Roman</code>, which responds to methods with names
 *  consisting of roman numerals, returning the corresponding integer
 *  values.
 *
 *     class Roman
 *       def romanToInt(str)
 *         # ...
 *       end
 *       def method_missing(methId)
 *         str = methId.id2name
 *         romanToInt(str)
 *       end
 *     end
 *
 *     r = Roman.new
 *     r.iv      #=> 4
 *     r.xxiii   #=> 23
 *     r.mm      #=> 2000
 */
static mrb_value
mrb_bob_missing(mrb_state *mrb, mrb_value mod)
{
1531 1532
  mrb_sym name;
  mrb_value *a;
1533
  mrb_int alen;
mimaki's avatar
mimaki committed
1534

1535
  mrb_get_args(mrb, "n*", &name, &a, &alen);
1536
  mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
mimaki's avatar
mimaki committed
1537 1538 1539 1540
  /* not reached */
  return mrb_nil_value();
}

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

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

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

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

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

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

1584 1585 1586 1587
    if (sym == 0) {
      return mrb_nil_value();
    }
    else if (outer && outer != mrb->object_class) {
mimaki's avatar
mimaki committed
1588
      mrb_value base = mrb_class_path(mrb, outer);
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
      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, "::");
1599
      name = mrb_sym2name_len(mrb, sym, &len);
1600
      mrb_str_cat(mrb, path, name, len);
mimaki's avatar
mimaki committed
1601 1602
    }
    else {
1603 1604
      name = mrb_sym2name_len(mrb, sym, &len);
      path = mrb_str_new(mrb, name, len);
mimaki's avatar
mimaki committed
1605
    }
1606 1607 1608
    if (!MRB_FROZEN_P(c)) {
      mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
    }
mimaki's avatar
mimaki committed
1609
  }
1610
  return mrb_str_dup(mrb, path);
mimaki's avatar
mimaki committed
1611 1612
}

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

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

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

/*!
 * 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.
 */
1648
static void
mimaki's avatar
mimaki committed
1649 1650 1651
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
  if (super->tt != MRB_TT_CLASS) {
1652
    mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
mimaki's avatar
mimaki committed
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
  }
  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.
1667
 */
1668
MRB_API struct RClass*
mimaki's avatar
mimaki committed
1669 1670 1671 1672 1673 1674 1675 1676
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
1677
  if (super) {
Masamitsu MURASE's avatar
Masamitsu MURASE committed
1678 1679
    MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
  }
mimaki's avatar
mimaki committed
1680 1681 1682 1683 1684 1685 1686 1687
  make_metaclass(mrb, c);

  return c;
}

/*!
 * Creates a new module.
 */
1688
MRB_API struct RClass*
mimaki's avatar
mimaki committed
1689 1690
mrb_module_new(mrb_state *mrb)
{
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1691
  struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
1692
  boot_initmod(mrb, m);
mimaki's avatar
mimaki committed
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
  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
 */

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

1716
MRB_API void
mimaki's avatar
mimaki committed
1717 1718 1719
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
1720

1721
  mrb_define_method_raw(mrb, c, a, m);
mimaki's avatar
mimaki committed
1722 1723 1724 1725 1726 1727 1728 1729
}

/*!
 * 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
 */
1730
MRB_API void
mimaki's avatar
mimaki committed
1731 1732
mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
{
1733
  mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2));
mimaki's avatar
mimaki committed
1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
}

/*
 * 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)
{
1748 1749
  mrb_value str;

mimaki's avatar
mimaki committed
1750
  if (mrb_type(klass) == MRB_TT_SCLASS) {
1751
    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
mimaki's avatar
mimaki committed
1752

1753
    str = mrb_str_new_lit(mrb, "#<Class:");
1754

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

1771
    str = mrb_str_buf_new(mrb, 32);
1772 1773
    c = mrb_class_ptr(klass);
    path = mrb_class_path(mrb, c);
roco's avatar
roco committed
1774

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

        case MRB_TT_MODULE:
1782
          mrb_str_cat_lit(mrb, str, "#<Module:");
1783 1784 1785
          break;

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

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

1805 1806
  mrb_get_args(mrb, "nn", &new_name, &old_name);
  mrb_alias_method(mrb, c, new_name, old_name);
mimaki's avatar
mimaki committed
1807 1808 1809
  return mrb_nil_value();
}

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

1821
MRB_API void
1822 1823
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
1824
  undef_method(mrb, c, mrb_intern_cstr(mrb, name));
1825 1826
}

1827
MRB_API void
1828 1829 1830 1831 1832
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);
}

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

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

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

1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868
  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;
  }
1869
  if (mrb_nil_p(blk)) {
1870
    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
1871
  }
1872 1873
  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
  mrb_proc_copy(p, mrb_proc_ptr(blk));
1874
  p->flags |= MRB_PROC_STRICT;
1875
  mrb_define_method_raw(mrb, c, mid, p);
1876
  return mrb_symbol_value(mid);
1877 1878
}

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

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

1890 1891 1892 1893 1894 1895
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
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
/* 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)
{
1914
  mrb_sym id;
skandhas's avatar
skandhas committed
1915

1916
  mrb_get_args(mrb, "n", &id);
1917 1918
  check_cv_name_sym(mrb, id);
  return mrb_bool_value(mrb_cv_defined(mrb, mod, id));
skandhas's avatar
skandhas committed
1919 1920
}

skandhas's avatar
skandhas committed
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940
/* 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;

1941
  mrb_get_args(mrb, "n", &id);
1942
  check_cv_name_sym(mrb, id);
skandhas's avatar
skandhas committed
1943 1944 1945
  return mrb_cv_get(mrb, mod, id);
}

skandhas's avatar
skandhas committed
1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
/* 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)
{
1967
  mrb_value value;
skandhas's avatar
skandhas committed
1968 1969
  mrb_sym id;

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

skandhas's avatar
skandhas committed
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
/* 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]
 *     []
 */

1999
static mrb_value
skandhas's avatar
skandhas committed
2000 2001
mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
{
2002
  mrb_value val;
skandhas's avatar
skandhas committed
2003 2004
  mrb_sym id;

2005
  mrb_get_args(mrb, "n", &id);
2006
  check_cv_name_sym(mrb, id);
skandhas's avatar
skandhas committed
2007 2008 2009 2010

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

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

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

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

skandhas's avatar
skandhas committed
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 2050 2051 2052
/* 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)
{
2053
  mrb_sym id;
skandhas's avatar
skandhas committed
2054

2055
  mrb_get_args(mrb, "n", &id);
2056
  return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id));
skandhas's avatar
skandhas committed
2057 2058
}

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

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

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

/* 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>.
 */

2088
static mrb_value
2089 2090
mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
2091
  mrb_int argc;
2092 2093 2094 2095
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);
  while (argc--) {
2096
    remove_method(mrb, mod, to_sym(mrb, *argv));
2097 2098 2099 2100 2101
    argv++;
  }
  return mod;
}

skandhas's avatar
skandhas committed
2102 2103


2104 2105 2106 2107 2108 2109 2110 2111
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);
  }
}

2112 2113 2114 2115 2116 2117
static void
check_const_name_sym(mrb_state *mrb, mrb_sym id)
{
  check_const_name_str(mrb, mrb_sym2str(mrb, id));
}

2118 2119 2120 2121 2122 2123 2124 2125 2126
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));
}

2127
static mrb_value
2128 2129
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
{
2130
  mrb_sym id;
2131
  mrb_bool inherit = TRUE;
2132

2133
  mrb_get_args(mrb, "n|b", &id, &inherit);
2134 2135
  check_const_name_sym(mrb, id);
  return const_defined(mrb, mod, id, inherit);
2136 2137
}

2138
static mrb_value
2139 2140
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
2141
  mrb_sym id;
2142

2143
  mrb_get_args(mrb, "n", &id);
2144
  check_const_name_sym(mrb, id);
2145
  return mrb_const_get(mrb, mod, id);
2146 2147
}

2148
static mrb_value
2149 2150
mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
{
2151 2152
  mrb_sym id;
  mrb_value value;
2153

2154
  mrb_get_args(mrb, "no", &id, &value);
2155
  check_const_name_sym(mrb, id);
2156
  mrb_const_set(mrb, mod, id, value);
2157 2158 2159
  return value;
}

2160
static mrb_value
2161 2162
mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
{
2163
  mrb_sym id;
2164 2165
  mrb_value val;

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

2175
static mrb_value
2176 2177 2178 2179 2180
mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
{
  mrb_sym sym;

  mrb_get_args(mrb, "n", &sym);
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190

  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));
  }
2191 2192 2193 2194
  /* not reached */
  return mrb_nil_value();
}

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

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

  mrb_get_args(mrb, "o", &obj);
2209 2210
  eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));

2211
  return mrb_bool_value(eqq);
mimaki's avatar
mimaki committed
2212 2213
}

2214
MRB_API mrb_value
dreamedge's avatar
dreamedge committed
2215 2216 2217 2218 2219 2220 2221 2222 2223 2224
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
2225

dreamedge's avatar
dreamedge committed
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
  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
2251 2252 2253
void
mrb_init_class(mrb_state *mrb)
{
roco's avatar
roco committed
2254 2255 2256 2257
  struct RClass *bob;           /* BasicObject */
  struct RClass *obj;           /* Object */
  struct RClass *mod;           /* Module */
  struct RClass *cls;           /* Class */
mimaki's avatar
mimaki committed
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271

  /* 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 */
2272
  mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
mimaki's avatar
mimaki committed
2273
  mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2274 2275 2276
  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
2277 2278

  /* name each classes */
2279
  name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
Yukihiro "Matz" Matsumoto's avatar
Yukihiro "Matz" Matsumoto committed
2280 2281 2282
  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
2283

2284 2285 2286
  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
2287
  MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
2288 2289 2290
  mrb_define_method(mrb, bob, "initialize",              mrb_bob_init,             MRB_ARGS_NONE());
  mrb_define_method(mrb, bob, "!",                       mrb_bob_not,              MRB_ARGS_NONE());
  mrb_define_method(mrb, bob, "method_missing",          mrb_bob_missing,          MRB_ARGS_ANY());  /* 15.3.1.3.30 */
MATSUMOTO Ryosuke's avatar
MATSUMOTO Ryosuke committed
2291

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

2298
  MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
2299 2300 2301 2302 2303
  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
2304 2305
  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));
2306 2307 2308 2309 2310
  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 */
2311
  mrb_define_method(mrb, mod, "initialize",              mrb_mod_initialize,       MRB_ARGS_NONE()); /* 15.2.2.4.31 */
2312 2313 2314
  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
2315
  mrb_define_method(mrb, mod, "module_function",         mrb_mod_module_function,  MRB_ARGS_ANY());
2316 2317 2318
  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 */
2319 2320
  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 */
2321
  mrb_define_method(mrb, mod, "method_removed",          mrb_bob_init,             MRB_ARGS_REQ(1));
2322 2323
  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 */
2324 2325 2326 2327 2328
  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 */
2329
  mrb_define_method(mrb, mod, "const_defined?",          mrb_mod_const_defined,    MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */
2330 2331
  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 */
2332
  mrb_define_method(mrb, mod, "constants",               mrb_mod_constants,        MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
2333
  mrb_define_method(mrb, mod, "remove_const",            mrb_mod_remove_const,     MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
2334
  mrb_define_method(mrb, mod, "const_missing",           mrb_mod_const_missing,    MRB_ARGS_REQ(1));
2335
  mrb_define_method(mrb, mod, "define_method",           mod_define_method,        MRB_ARGS_ARG(1,1));
2336 2337 2338
  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
2339

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