class.c 44.1 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
*/

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

19
KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal)
mimaki's avatar
mimaki committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

typedef struct fc_result {
    mrb_sym name;
    struct RClass * klass;
    mrb_value path;
    struct RClass * track;
    struct fc_result *prev;
} fcresult_t;

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++) {
    if (kh_exist(h, k)){
      struct RProc *m = kh_value(h, k);
      if (m) {
40
	mrb_gc_mark(mrb, (struct RBasic*)m);
mimaki's avatar
mimaki committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
      }
    }
  }
}

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)
{
  kh_destroy(mt, c->mt);
}

void
mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
{
  mrb_obj_iv_set(mrb, (struct RObject*)c,
                 mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
}

68 69
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))

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

75
  if (o->c->tt == MRB_TT_SCLASS) return;
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
76
  sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
mimaki's avatar
mimaki committed
77
  sc->mt = 0;
78
  sc->iv = 0;
79 80 81 82 83 84 85 86
  if (o->tt == MRB_TT_CLASS) {
    c = (struct RClass*)o;
    if (!c->super) {
      sc->super = mrb->class_class;
    }
    else {
      sc->super = c->super->c;
    }
87
  }
88 89 90
  else if (o->tt == MRB_TT_SCLASS) {
    c = (struct RClass*)o;
    make_metaclass(mrb, c->super);
91 92
    sc->super = c->super->c;
  }
93 94 95 96 97 98 99
  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);
  mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o));
mimaki's avatar
mimaki committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
}

struct RClass*
mrb_define_module_id(mrb_state *mrb, mrb_sym name)
{
  struct RClass *m = mrb_module_new(mrb);

  mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
             name, mrb_obj_value(m));
  mrb_name_class(mrb, m, name);

  return m;
}

struct RClass*
mrb_define_module(mrb_state *mrb, const char *name)
{
  return mrb_define_module_id(mrb, mrb_intern(mrb, name));
}

static void
setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id)
{
  mrb_name_class(mrb, c, id);
  mrb_const_set(mrb, outer, id, mrb_obj_value(c));
  mrb_obj_iv_set(mrb, (struct RObject*)c,
                 mrb_intern(mrb, "__outer__"), outer);
}

struct RClass*
mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
{
  mrb_value outer;

  outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__"));
  if (mrb_nil_p(outer)) return 0;
  return mrb_class_ptr(outer);
}

struct RClass*
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
  struct RClass *c;
  mrb_value v;

  if (mrb_const_defined(mrb, outer, id)) {
    v = mrb_const_get(mrb, outer, id);
    c = mrb_class_ptr(v);
  }
  else {
    c = mrb_module_new(mrb);
    setup_class(mrb, outer, c, id);
  }
  return c;
}

struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
{
  struct RClass *c = mrb_class_new(mrb, super);

  mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
roco's avatar
roco committed
162
                 name, mrb_obj_value(c));
mimaki's avatar
mimaki committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
  mrb_name_class(mrb, c, name);

  return c;
}

struct RClass*
mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
{
  struct RClass *c;
  c = mrb_define_class_id(mrb, mrb_intern(mrb, name), super);
  return c;
}

struct RClass*
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
179
  struct RClass *c, *s;
mimaki's avatar
mimaki committed
180 181 182 183

  if (mrb_const_defined(mrb, outer, id)) {
    mrb_value v = mrb_const_get(mrb, outer, id);

184
    mrb_check_type(mrb, v, MRB_TT_CLASS);
mimaki's avatar
mimaki committed
185
    c = mrb_class_ptr(v);
186 187
    if (!mrb_nil_p(super)) {
      if (mrb_type(super) != MRB_TT_CLASS) {
188
        mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
189 190 191
      }

      if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
192
        mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
193
      }
mimaki's avatar
mimaki committed
194
    }
195
    return c;
mimaki's avatar
mimaki committed
196 197
  }

198 199
  if (!mrb_nil_p(super)) {
    if (mrb_type(super) != MRB_TT_CLASS) {
200
      mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
201
    }
202
    s = mrb_class_ptr(super);
mimaki's avatar
mimaki committed
203
  }
204 205 206 207 208 209 210
  else {
    s = mrb->object_class;
  }

  c = mrb_class_new(mrb, s);
  setup_class(mrb, outer, c, id);
  mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c));
mimaki's avatar
mimaki committed
211 212 213 214

  return c;
}

215 216 217 218 219
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
  mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);

Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
220
  if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) {
221
    mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a class/module", mrb_sym2name(mrb, id));
222 223 224 225 226 227 228 229 230 231
  }
  return mrb_class_ptr(c);
}

struct RClass *
mrb_class_get(mrb_state *mrb, const char *name)
{
  return class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name));
}

mimaki's avatar
mimaki committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*!
 * 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.
 */
struct RClass *
mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
{
  struct RClass * c;
  mrb_sym id = mrb_intern(mrb, name);

  if (mrb_const_defined_at(mrb, outer, id)) {
255
    c = class_from_sym(mrb, outer, id);
mimaki's avatar
mimaki committed
256 257 258 259 260 261 262
    if (mrb_class_real(c->super) != super) {
        mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id));
    }
    return c;
  }
  if (!super) {
    mrb_warn("no super class for `%s::%s', Object assumed",
roco's avatar
roco committed
263
             mrb_obj_classname(mrb, mrb_obj_value(outer)), mrb_sym2name(mrb, id));
mimaki's avatar
mimaki committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277
  }
  c = mrb_class_new(mrb, super);
  setup_class(mrb, mrb_obj_value(outer), c, id);

  return c;
}

struct RClass *
mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
  struct RClass * c;
  mrb_sym id = mrb_intern(mrb, name);

  if (mrb_const_defined_at(mrb, outer, id)) {
278
    c = class_from_sym(mrb, outer, id);
mimaki's avatar
mimaki committed
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
    return c;
  }
  c = mrb_module_new(mrb);
  setup_class(mrb, mrb_obj_value(outer), c, id);

  return c;
}

void
mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
{
  khash_t(mt) *h = c->mt;
  khiter_t k;

  if (!h) h = c->mt = kh_init(mt, mrb);
294
  k = kh_put(mt, h, mid);
mimaki's avatar
mimaki committed
295
  kh_value(h, k) = p;
Masamitsu MURASE's avatar
Masamitsu MURASE committed
296 297 298
  if (p) {
    mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
  }
mimaki's avatar
mimaki committed
299 300 301 302 303 304 305 306 307 308 309 310 311
}

void
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec)
{
  struct RProc *p;

  p = mrb_proc_new_cfunc(mrb, func);
  p->target_class = c;
  mrb_define_method_raw(mrb, c, mid, p);
}

void
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
312
mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
mimaki's avatar
mimaki committed
313
{
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
314
  mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
315 316 317 318 319 320 321
}

void
mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value body)
{
  khash_t(mt) *h = c->mt;
  khiter_t k;
322
  struct RProc *p;
mimaki's avatar
mimaki committed
323 324

  if (!h) h = c->mt = kh_init(mt, mrb);
325
  k = kh_put(mt, h, name);
326 327
  p = mrb_proc_ptr(body);
  kh_value(h, k) = p;
Masamitsu MURASE's avatar
Masamitsu MURASE committed
328 329 330
  if (p) {
    mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
  }
mimaki's avatar
mimaki committed
331 332
}

333 334 335 336 337 338 339
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)) {
340
    mrb_raisef(mrb, E_TYPE_ERROR, "expected %s", c);
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
  }
  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");
}

/*
  retrieve arguments from mrb_state.

  mrb_get_args(mrb, format, ...)
  
  returns number of arguments parsed.

  fortmat specifiers:

   o: Object [mrb_value]
   S: String [mrb_value]
   A: Array [mrb_value]
   H: Hash [mrb_value]
   s: String [char*,int]
   z: String [char*]
   a: Array [mrb_value*,int]
   f: Float [mrb_float]
   i: Integer [mrb_int]
381
   b: Binary [int]
382
   n: Symbol [mrb_sym]
383 384 385 386
   &: Block [mrb_value]
   *: rest argument [mrb_value*,int]
   |: optional
 */
mimaki's avatar
mimaki committed
387 388 389 390
int
mrb_get_args(mrb_state *mrb, const char *format, ...)
{
  char c;
391
  int i = 0;
mimaki's avatar
mimaki committed
392 393 394
  mrb_value *sp = mrb->stack + 1;
  va_list ap;
  int argc = mrb->ci->argc;
395
  int opt = 0;
mimaki's avatar
mimaki committed
396 397 398 399 400 401

  va_start(ap, format);
  if (argc < 0) {
    struct RArray *a = mrb_ary_ptr(mrb->stack[1]);

    argc = a->len;
402
    sp = a->ptr;
mimaki's avatar
mimaki committed
403 404
  }
  while ((c = *format++)) {
405 406 407 408
    switch (c) {
    case '|': case '*': case '&':
      break;
    default:
409
      if (argc <= i && !opt) {
410 411
	mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
      }
412
    }
413

mimaki's avatar
mimaki committed
414 415 416 417
    switch (c) {
    case 'o':
      {
        mrb_value *p;
418

mimaki's avatar
mimaki committed
419
        p = va_arg(ap, mrb_value*);
420 421 422 423
	if (i < argc) {
	  *p = *sp++;
	  i++;
	}
mimaki's avatar
mimaki committed
424 425
      }
      break;
426
    case 'S':
mimaki's avatar
mimaki committed
427
      {
428
        mrb_value *p;
mimaki's avatar
mimaki committed
429

430
        p = va_arg(ap, mrb_value*);
431 432 433 434
	if (i < argc) {
	  *p = to_str(mrb, *sp++);
	  i++;
	}
435 436 437 438 439
      }
      break;
    case 'A':
      {
        mrb_value *p;
440

441
        p = va_arg(ap, mrb_value*);
442 443 444 445
	if (i < argc) {
	  *p = to_ary(mrb, *sp++);
	  i++;
	}
446 447 448 449 450 451 452
      }
      break;
    case 'H':
      {
        mrb_value *p;

        p = va_arg(ap, mrb_value*);
453 454 455 456
	if (i < argc) {
	  *p = to_hash(mrb, *sp++);
	  i++;
	}
457 458 459 460 461 462 463 464 465 466 467
      }
      break;
    case 's':
      {
	mrb_value ss;
        struct RString *s;
        char **ps = 0;
        int *pl = 0;

	ps = va_arg(ap, char**);
	pl = va_arg(ap, int*);
468 469 470 471 472 473 474
	if (i < argc) {
	  ss = to_str(mrb, *sp++);
	  s = mrb_str_ptr(ss);
	  *ps = s->ptr;
	  *pl = s->len;
	  i++;
	}
475 476 477 478 479 480 481 482 483
      }
      break;
    case 'z':
      {
	mrb_value ss;
        struct RString *s;
        char **ps;

	ps = va_arg(ap, char**);
484 485 486 487 488 489 490 491 492
	if (i < argc) {
	  ss = to_str(mrb, *sp++);
	  s = mrb_str_ptr(ss);
	  if (strlen(s->ptr) != s->len) {
	    mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
	  }
	  *ps = s->ptr;
	  i++;
	}
493 494 495 496 497 498 499 500 501 502 503
      }
      break;
    case 'a':
      {
	mrb_value aa;
        struct RArray *a;
        mrb_value **pb;
        int *pl;

	pb = va_arg(ap, mrb_value**);
	pl = va_arg(ap, int*);
504 505 506 507 508 509 510
	if (i < argc) {
	  aa = to_ary(mrb, *sp++);
	  a = mrb_ary_ptr(aa);
	  *pb = a->ptr;
	  *pl = a->len;
	  i++;
	}
mimaki's avatar
mimaki committed
511 512 513 514 515 516 517
      }
      break;
    case 'f':
      {
        mrb_float *p;

        p = va_arg(ap, mrb_float*);
518
	if (i < argc) {
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
519
	  switch (mrb_type(*sp)) {
520 521 522 523 524 525
	  case MRB_TT_FLOAT:
	    *p = mrb_float(*sp);
	    break;
	  case MRB_TT_FIXNUM:
	    *p = (mrb_float)mrb_fixnum(*sp);
	    break;
526 527
	  case MRB_TT_STRING:
	    mrb_raise(mrb, E_TYPE_ERROR, "String can't be coerced into Float");
528 529 530 531 532 533 534 535 536
	    break;
	  default:
	    {
	      mrb_value tmp;

	      tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f");
	      *p = mrb_float(tmp);
	    }
	    break;
537
	  }
538 539 540
	  sp++;
	  i++;
	}
mimaki's avatar
mimaki committed
541 542
      }
      break;
543
    case 'i':
mimaki's avatar
mimaki committed
544
      {
545
        mrb_int *p;
mimaki's avatar
mimaki committed
546

547
        p = va_arg(ap, mrb_int*);
548
	if (i < argc) {
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
549
	  switch (mrb_type(*sp)) {
550 551 552 553
	  case MRB_TT_FIXNUM:
	    *p = mrb_fixnum(*sp);
	    break;
	  case MRB_TT_FLOAT:
554 555 556 557 558 559 560 561
	    {
	      mrb_float f = mrb_float(*sp);

	      if (!FIXABLE(f)) {
		mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
	      }
	      *p = (mrb_int)f;
	    }
562 563 564 565 566 567 568 569 570 571 572 573
	    break;
	  case MRB_TT_FALSE:
	    *p = 0;
	    break;
	  default:
	    {
	      mrb_value tmp;

	      tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
	      *p = mrb_fixnum(tmp);
	    }
	    break;
574
	  }
575 576 577
	  sp++;
	  i++;
	}
mimaki's avatar
mimaki committed
578 579
      }
      break;
580 581 582 583 584 585 586 587 588 589 590
    case 'b':
      {
	int *boolp = va_arg(ap, int*);

	if (i < argc) {
	  mrb_value b = *sp++;
	  *boolp = mrb_test(b);
	  i++;
	}
      }
      break;
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
    case 'n':
      {
	mrb_sym *symp;

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

	  ss = *sp++;
	  if (mrb_type(ss) == MRB_TT_SYMBOL) {
	    *symp = mrb_symbol(ss);
	  }
	  else {
	    *symp = mrb_intern_str(mrb, to_str(mrb, ss));
	  }
	  i++;
	}
      }
      break;
mimaki's avatar
mimaki committed
610 611 612

    case '&':
      {
613
        mrb_value *p, *bp;
mimaki's avatar
mimaki committed
614 615

        p = va_arg(ap, mrb_value*);
616 617
        if (mrb->ci->argc < 0) {
          bp = mrb->stack + 2;
roco's avatar
roco committed
618
        }
619 620 621
	else {
          bp = mrb->stack + mrb->ci->argc + 1;
	}
roco's avatar
roco committed
622
        *p = *bp;
mimaki's avatar
mimaki committed
623 624
      }
      break;
625 626 627
    case '|':
      opt = 1;
      break;
628

mimaki's avatar
mimaki committed
629 630 631
    case '*':
      {
        mrb_value **var;
632 633
	int *pl;

mimaki's avatar
mimaki committed
634
        var = va_arg(ap, mrb_value**);
635
        pl = va_arg(ap, int*);
roco's avatar
roco committed
636
        if (argc > i) {
637 638 639 640
          *pl = argc-i;
          if (*pl > 0) {
	    *var = sp;
            i = argc;
roco's avatar
roco committed
641
          }
642 643
	  i = argc;
	  sp += *pl;
roco's avatar
roco committed
644 645
        }
        else {
646
          *pl = 0;
roco's avatar
roco committed
647 648
          *var = NULL;
        }
mimaki's avatar
mimaki committed
649 650
      }
      break;
651
    default:
652
      mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
653
      break;
mimaki's avatar
mimaki committed
654 655
    }
  }
656
  if (!c && argc > i) {
657 658
    mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
  }
mimaki's avatar
mimaki committed
659
  va_end(ap);
660
  return i;
mimaki's avatar
mimaki committed
661 662 663 664 665 666 667
}

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

Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
668
  c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
mimaki's avatar
mimaki committed
669 670 671 672 673 674 675 676 677
  c->super = super ? super : mrb->object_class;
  mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
  c->mt = kh_init(mt, mrb);
  return c;
}

void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
678
  struct RClass *ins_pos;
mimaki's avatar
mimaki committed
679

680 681
  ins_pos = c;
  while (m) {
682 683 684 685 686 687
    struct RClass *p = c, *ic;
    int superclass_seen = 0;

    while(p) {
      if (c != p && p->tt == MRB_TT_CLASS) {
	superclass_seen = 1;
688
      }
689 690 691 692 693
      else if (p->mt == m->mt){
	if (p->tt == MRB_TT_ICLASS && !superclass_seen) {
	  ins_pos = p;
	}
	goto skip;
694
      }
695 696 697 698 699 700 701 702
      p = p->super;
    }
    ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
    if (m->tt == MRB_TT_ICLASS) {
      ic->c = m->c;
    }
    else {
      ic->c = m;
703
    }
704 705 706 707 708 709 710
    ic->mt = m->mt;
    ic->iv = m->iv;
    ic->super = ins_pos->super;
    ins_pos->super = ic;
    mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
    ins_pos = ic;
  skip:
711 712
    m = m->super;
  }
mimaki's avatar
mimaki committed
713 714 715
}

static mrb_value
716
mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mimaki's avatar
mimaki committed
717
{
718
  mrb_value klass;
mimaki's avatar
mimaki committed
719

720
  mrb_check_type(mrb, mod, MRB_TT_MODULE);
721
  mrb_get_args(mrb, "o", &klass);
mimaki's avatar
mimaki committed
722 723 724 725
  mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
  return mod;
}

726 727 728 729 730 731 732 733 734 735 736
static mrb_value
mrb_mod_include(mrb_state *mrb, mrb_value klass)
{
  mrb_value *argv;
  int argc, i;

  mrb_get_args(mrb, "*", &argv, &argc);
  for (i=0; i<argc; i++) {
    mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
  }
  while (argc--) {
737 738
    mrb_funcall(mrb, argv[argc], "append_features", 1, klass);
    mrb_funcall(mrb, argv[argc], "included", 1, klass);
739 740 741 742 743
  }

  return klass;
}

skandhas's avatar
skandhas committed
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
/* 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
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
static mrb_value
mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
{
  mrb_value mod2;
  struct RClass *c = mrb_class_ptr(mod);

  mrb_get_args(mrb, "o", &mod2);
  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();
}
 
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
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));
    }
    else {
      mrb_ary_push(mrb, result, mrb_obj_value(c));
    }
    c = c->super;
  }

  return result;
}

801 802 803 804 805 806 807 808 809 810 811
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;
}

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
static mrb_value
mrb_mod_included_modules(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));
    }
    c = c->super;
  }

  return result;
}

skandhas's avatar
skandhas committed
829 830
mrb_value class_instance_method_list(mrb_state*, int, mrb_value*, struct RClass*, int);

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
/* 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
859 860 861 862 863 864 865 866 867 868 869
static mrb_value
mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
{
  mrb_value *argv;
  int argc;
  struct RClass *c = mrb_class_ptr(mod);

  mrb_get_args(mrb, "*", &argv, &argc);
  return class_instance_method_list(mrb, argc, argv, c, 0);
}

skandhas's avatar
skandhas committed
870 871
mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);

872 873 874 875 876 877 878 879 880 881 882
/* 15.2.2.4.35 */
/*
 *  call-seq:
 *     mod.class_eval {| | block }  -> obj
 *     mod.module_eval {| | block } -> obj
 *
 *  Evaluates block in the context of _mod_. This can
 *  be used to add methods to a class. <code>module_eval</code> returns
 *  the result of evaluating its argument.
 */

skandhas's avatar
skandhas committed
883 884 885 886 887 888 889 890 891 892 893 894 895
mrb_value
mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
{
  mrb_value a, b;
  struct RClass *c;

  if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
    mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
  }
  c = mrb_class_ptr(mod);
  return mrb_yield_internal(mrb, b, 0, 0, mod, c);
}

mimaki's avatar
mimaki committed
896 897 898 899 900 901 902
mrb_value
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
  struct RBasic *obj;

  switch (mrb_type(v)) {
  case MRB_TT_FALSE:
903 904 905
    if (mrb_nil_p(v))
      return mrb_obj_value(mrb->nil_class);
    return mrb_obj_value(mrb->false_class);
mimaki's avatar
mimaki committed
906
  case MRB_TT_TRUE:
907
    return mrb_obj_value(mrb->true_class);
908
  case MRB_TT_MAIN:
909
  case MRB_TT_VOIDP:
910
    return mrb_obj_value(mrb->object_class);
mimaki's avatar
mimaki committed
911 912 913
  case MRB_TT_SYMBOL:
  case MRB_TT_FIXNUM:
  case MRB_TT_FLOAT:
914 915
    mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
    return mrb_nil_value();    /* not reached */
mimaki's avatar
mimaki committed
916
  default:
roco's avatar
roco committed
917
    break;
mimaki's avatar
mimaki committed
918
  }
919
  obj = mrb_object(v);
920
  prepare_singleton_class(mrb, obj);
mimaki's avatar
mimaki committed
921 922 923 924
  return mrb_obj_value(obj->c);
}

void
925
mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec)
mimaki's avatar
mimaki committed
926
{
927
  prepare_singleton_class(mrb, (struct RBasic*)o);
928
  mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
mimaki's avatar
mimaki committed
929 930
}

931
void
932
mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
933
{
934
  mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
935 936 937 938 939 940 941 942 943
}

void
mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
{
  mrb_define_class_method(mrb, c, name, func, aspec);
  mrb_define_method(mrb, c, name, func, aspec);
}

mimaki's avatar
mimaki committed
944 945 946 947 948 949 950 951 952 953 954 955 956
struct RProc*
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) {
      k = kh_get(mt, h, mid);
      if (k != kh_end(h)) {
roco's avatar
roco committed
957 958 959 960
        m = kh_value(h, k);
        if (!m) break;
        *cp = c;
        return m;
mimaki's avatar
mimaki committed
961 962 963 964 965 966 967 968 969 970 971 972 973 974
      }
    }
    c = c->super;
  }
  return 0;                  /* no method */
}

struct RProc*
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) {
975
    mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
976
    if (RSTRING_LEN(inspect) > 64) {
977 978
      inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
    }
979
    mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%s' for class %s",
980
        mrb_sym2name(mrb, mid), RSTRING_PTR(inspect));
mimaki's avatar
mimaki committed
981 982 983 984 985 986 987
  }
  return m;
}

void
mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv)
{
988
  mrb_funcall_argv(mrb, obj, mrb->init_sym, argc, argv);
mimaki's avatar
mimaki committed
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
}

/*
 *  call-seq:
 *     class.new(args, ...)    ->  obj
 *
 *  Calls <code>allocate</code> to create 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.
 *
 */
mrb_value
mrb_class_new_instance(mrb_state *mrb, int argc, mrb_value *argv, struct RClass * klass)
{
  mrb_value obj;
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1006
  struct RClass * c = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, klass);
mimaki's avatar
mimaki committed
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
  c->super = klass;
  obj = mrb_obj_value(c);
  mrb_obj_call_init(mrb, obj, argc, argv);
  return obj;
}

mrb_value
mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass)
{
  mrb_value *argv;
1017
  mrb_value blk;
mimaki's avatar
mimaki committed
1018 1019 1020 1021 1022
  struct RClass *k = mrb_class_ptr(klass);
  struct RClass *c;
  int argc;
  mrb_value obj;

1023
  mrb_get_args(mrb, "*&", &argv, &argc, &blk);
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1024
  c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k);
mimaki's avatar
mimaki committed
1025 1026
  c->super = k;
  obj = mrb_obj_value(c);
1027
  mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk);
mimaki's avatar
mimaki committed
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037

  return obj;
}

mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
  struct RClass *c = mrb_class_ptr(cv);
  struct RObject *o;
  enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
1038
  mrb_value obj, blk;
mimaki's avatar
mimaki committed
1039 1040 1041 1042
  mrb_value *argv;
  int argc;

  if (ttype == 0) ttype = MRB_TT_OBJECT;
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1043
  o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
mimaki's avatar
mimaki committed
1044
  obj = mrb_obj_value(o);
1045
  mrb_get_args(mrb, "*&", &argv, &argc, &blk);
1046
  mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk);
mimaki's avatar
mimaki committed
1047 1048 1049 1050

  return obj;
}

Yuichiro MASUI's avatar
Yuichiro MASUI committed
1051 1052 1053 1054
mrb_value
mrb_class_new_class(mrb_state *mrb, mrb_value cv)
{
  mrb_value super;
1055 1056 1057
  struct RClass *new_class;

  if (mrb_get_args(mrb, "|o", &super) == 0) {
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1058 1059
    super = mrb_obj_value(mrb->object_class);
  }
1060
  new_class = mrb_class_new(mrb, mrb_class_ptr(super));
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1061 1062 1063
  return mrb_obj_value(new_class);
}

1064 1065 1066
mrb_value
mrb_class_superclass(mrb_state *mrb, mrb_value klass)
{
1067 1068
  struct RClass *c;

1069
  c = mrb_class_ptr(klass);
1070 1071 1072 1073 1074 1075
  c = c->super;
  while (c && c->tt == MRB_TT_ICLASS) {
    c = c->super;
  }
  if (!c) return mrb_nil_value();
  return mrb_obj_value(c);
1076 1077
}

mimaki's avatar
mimaki committed
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
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)
{
  if (mrb_test(cv))
    return mrb_false_value();
  return mrb_true_value();
}

/* 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)
{
  mrb_value name, *a;
  int alen;
1130
  mrb_value inspect;
mimaki's avatar
mimaki committed
1131 1132

  mrb_get_args(mrb, "o*", &name, &a, &alen);
1133
  if (!mrb_symbol_p(name)) {
mimaki's avatar
mimaki committed
1134 1135
    mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol");
  }
1136

1137
  inspect = mrb_funcall(mrb, mod, "inspect", 0);
1138
  if (RSTRING_LEN(inspect) > 64) {
1139 1140 1141
    inspect = mrb_any_to_s(mrb, mod);
  }

1142
  mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%s' for %s",
1143
      mrb_sym2name(mrb, mrb_symbol(name)), RSTRING_PTR(inspect));
mimaki's avatar
mimaki committed
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
  /* not reached */
  return mrb_nil_value();
}

int
mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
{
  khiter_t k;

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

    if (h) {
      k = kh_get(mt, h, mid);
1158 1159
      if (k != kh_end(h)) {
        if (kh_value(h, k)) {
1160
          return TRUE;		/* method exists */
1161 1162
        }
        else {
1163
          return FALSE;		/* undefined method */
1164 1165
        }
      }
mimaki's avatar
mimaki committed
1166 1167 1168
    }
    c = c->super;
  }
1169
  return FALSE;			/* no method */
mimaki's avatar
mimaki committed
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
}

int
mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
{
  return mrb_obj_respond_to(mrb_class(mrb, obj), mid);
}

mrb_value
mrb_class_path(mrb_state *mrb, struct RClass *c)
{
  mrb_value path;
1182 1183
  const char *name;
  int len;
mimaki's avatar
mimaki committed
1184 1185 1186 1187

  path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"));
  if (mrb_nil_p(path)) {
    struct RClass *outer = mrb_class_outer_module(mrb, c);
1188 1189 1190 1191 1192
    mrb_sym sym = mrb_class_sym(mrb, c, outer);
    if (sym == 0) {
      return mrb_nil_value();
    }
    else if (outer && outer != mrb->object_class) {
mimaki's avatar
mimaki committed
1193
      mrb_value base = mrb_class_path(mrb, outer);
1194 1195 1196
      path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2));
      name = mrb_sym2name_len(mrb, sym, &len);
      mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len));
mimaki's avatar
mimaki committed
1197 1198
    }
    else {
1199 1200
      name = mrb_sym2name_len(mrb, sym, &len);
      path = mrb_str_new(mrb, name, len);
mimaki's avatar
mimaki committed
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
    }
    mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path);
  }
  return path;
}

struct RClass *
mrb_class_real(struct RClass* cl)
{
  while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
    cl = cl->super;
  }
  return cl;
}

const char*
mrb_class_name(mrb_state *mrb, struct RClass* c)
{
  mrb_value path = mrb_class_path(mrb, c);
1220 1221 1222 1223 1224 1225
  if (mrb_nil_p(path)) {
    char buf[32];

    snprintf(buf, 32, "#<Class:%p>", c);
    path = mrb_str_new_cstr(mrb, buf);
  }
1226
  return mrb_str_ptr(path)->ptr;
mimaki's avatar
mimaki committed
1227 1228 1229 1230 1231
}

const char*
mrb_obj_classname(mrb_state *mrb, mrb_value obj)
{
1232
  return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
mimaki's avatar
mimaki committed
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
}

/*!
 * 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.
 */
void
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
  if (super->tt != MRB_TT_CLASS) {
1245
    mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)",
mimaki's avatar
mimaki committed
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
           mrb_obj_classname(mrb, mrb_obj_value(super)));
  }
  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.
1261 1262
 */
struct RClass *
mimaki's avatar
mimaki committed
1263 1264 1265 1266 1267 1268 1269 1270
mrb_class_new(mrb_state *mrb, struct RClass *super)
{
  struct RClass *c;

  if (super) {
    mrb_check_inheritable(mrb, super);
  }
  c = boot_defclass(mrb, super);
Masamitsu MURASE's avatar
Masamitsu MURASE committed
1271 1272 1273
  if (super){
    MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
  }
mimaki's avatar
mimaki committed
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
  make_metaclass(mrb, c);

  return c;
}

/*!
 * Creates a new module.
 */
struct RClass *
mrb_module_new(mrb_state *mrb)
{
Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1285
  struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
1286
  m->mt = kh_init(mt, mrb);
mimaki's avatar
mimaki committed
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314

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

struct RClass*
mrb_obj_class(mrb_state *mrb, mrb_value obj)
{
    return mrb_class_real(mrb_class(mrb, obj));
}

void
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
1315

mimaki's avatar
mimaki committed
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
  mrb_define_method_vm(mrb, c, a, mrb_obj_value(m));
}

/*!
 * 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
 */
void
mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
{
  mrb_alias_method(mrb, klass, mrb_intern(mrb, name1), mrb_intern(mrb, name2));
}

/*
 * 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)
{
  if (mrb_type(klass) == MRB_TT_SCLASS) {
1344
    mrb_value s = mrb_str_new(mrb, "#<", 2);
mimaki's avatar
mimaki committed
1345 1346 1347 1348 1349 1350
    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__"));

    mrb_str_cat2(mrb, s, "Class:");
    switch (mrb_type(v)) {
      case MRB_TT_CLASS:
      case MRB_TT_MODULE:
1351
      case MRB_TT_SCLASS:
mimaki's avatar
mimaki committed
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
        mrb_str_append(mrb, s, mrb_inspect(mrb, v));
        break;
      default:
        mrb_str_append(mrb, s, mrb_any_to_s(mrb, v));
        break;
    }
    mrb_str_cat2(mrb, s, ">");

    return s;
  }
  else {
    struct RClass *c = mrb_class_ptr(klass);
1364
    const char *cn = mrb_class_name(mrb, c);
mimaki's avatar
mimaki committed
1365 1366 1367

    if (!cn) {
      char buf[256];
1368
      int n = 0;
roco's avatar
roco committed
1369

mimaki's avatar
mimaki committed
1370
      switch (mrb_type(klass)) {
1371
        case MRB_TT_CLASS:
1372
          n = snprintf(buf, sizeof(buf), "#<Class:%p>", c);
1373 1374 1375
          break;

        case MRB_TT_MODULE:
1376
          n = snprintf(buf, sizeof(buf), "#<Module:%p>", c);
1377 1378 1379 1380
          break;

        default:
          break;
mimaki's avatar
mimaki committed
1381
      }
1382
      return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n));
mimaki's avatar
mimaki committed
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
    }
    else {
      return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn));
    }
  }
}

mrb_value
mrb_mod_alias(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
1394
  mrb_value new_value, old_value;
mimaki's avatar
mimaki committed
1395

1396 1397
  mrb_get_args(mrb, "oo", &new_value, &old_value);
  mrb_alias_method(mrb, c, mrb_symbol(new_value), mrb_symbol(old_value));
mimaki's avatar
mimaki committed
1398 1399 1400 1401
  return mrb_nil_value();
}


1402 1403
static void
undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
mimaki's avatar
mimaki committed
1404 1405 1406
{
  mrb_value m;

Yukihiro Matsumoto's avatar
Yukihiro Matsumoto committed
1407
  MRB_SET_VALUE(m, MRB_TT_PROC, value.p, 0);
mimaki's avatar
mimaki committed
1408 1409 1410
  mrb_define_method_vm(mrb, c, a, m);
}

1411 1412 1413 1414 1415 1416
void
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
  undef_method(mrb, c, mrb_intern(mrb, name));
}

1417 1418 1419 1420 1421 1422
void
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);
}

mimaki's avatar
mimaki committed
1423 1424 1425 1426 1427 1428 1429 1430 1431
mrb_value
mrb_mod_undef(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
  int argc;
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);
  while (argc--) {
1432
    undef_method(mrb, c, mrb_symbol(*argv));
mimaki's avatar
mimaki committed
1433 1434 1435 1436 1437
    argv++;
  }
  return mrb_nil_value();
}

1438 1439 1440 1441
static mrb_value
mod_define_method(mrb_state *mrb, mrb_value self)
{
  struct RClass *c = mrb_class_ptr(self);
1442
  struct RProc *p;
1443 1444 1445 1446 1447
  mrb_sym mid;
  mrb_value blk;

  mrb_get_args(mrb, "n&", &mid, &blk);
  if (mrb_nil_p(blk)) {
1448
    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
1449
  }
1450 1451 1452
  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
  mrb_proc_copy(p, mrb_proc_ptr(blk));
  mrb_define_method_raw(mrb, c, mid, p);
1453 1454 1455
  return blk;
}

1456 1457 1458
static mrb_sym
mrb_sym_value(mrb_state *mrb, mrb_value val)
{
1459
  if (mrb_string_p(val)) {
1460
    return mrb_intern_str(mrb, val);
1461
  }
1462
  else if(!mrb_symbol_p(val)) {
1463
    mrb_value obj = mrb_funcall(mrb, val, "inspect", 0);
1464
    mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
1465 1466 1467 1468 1469
         mrb_string_value_ptr(mrb, obj));
  }
  return mrb_symbol(val);
}

skandhas's avatar
skandhas committed
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
static void
check_cv_name(mrb_state *mrb, mrb_sym id)
{
  const char *s;
  int len;

  s = mrb_sym2name_len(mrb, id, &len);
  if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
    mrb_name_error(mrb, id, "`%s' is not allowed as a class variable name", s);
  }
}

skandhas's avatar
skandhas committed
1482 1483 1484 1485 1486 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
/* 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)
{
  mrb_value sym;
  mrb_sym id;
  mrb_get_args(mrb, "o", &sym);

  id = mrb_sym_value(mrb,sym);
  check_cv_name(mrb, id);

  if(mrb_cv_defined(mrb, mod, id))
    return mrb_true_value();
  return mrb_false_value();
}

skandhas's avatar
skandhas committed
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
/* 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_value sym;
  mrb_sym id;
  mrb_get_args(mrb, "o", &sym);

  id = mrb_sym_value(mrb,sym);
skandhas's avatar
skandhas committed
1535
  check_cv_name(mrb, id);
skandhas's avatar
skandhas committed
1536 1537 1538
  return mrb_cv_get(mrb, mod, id);
}

skandhas's avatar
skandhas committed
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570
/* 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)
{
  mrb_value sym, value;
  mrb_sym id;
  mrb_get_args(mrb, "oo", &sym, &value);

  id = mrb_sym_value(mrb,sym);

  check_cv_name(mrb, id);
  mrb_cv_set(mrb, mod, id, value);
  return value;
}

skandhas's avatar
skandhas committed
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
/* 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]
 *     []
 */

mrb_value
mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
{
  mrb_value sym, val;
  mrb_sym id;

  mrb_get_args(mrb, "o", &sym);

  id = mrb_sym_value(mrb,sym);
  check_cv_name(mrb, id);

  val = mrb_iv_remove(mrb, mod, id);

  if (!mrb_undef_p(val)) return val;

  if (mrb_cv_defined(mrb, mod, id)){
    mrb_name_error(mrb, id, "cannot remove %s for %s",
        mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));
  }

  mrb_name_error(mrb, id, "class variable %s not defined for %s",
      mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));

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

skandhas's avatar
skandhas committed
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662
/* 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)
{
  mrb_value sym;
  mrb_sym id;

  mrb_get_args(mrb, "o", &sym);
  id = mrb_sym_value(mrb,sym);

  if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) {
    return mrb_true_value();
  }
  return mrb_false_value();
}

1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
static void
remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
{
  khash_t(mt) *h = c->mt;
  khiter_t k;

  if (h) {
    k = kh_get(mt, h, mid);
    if (k != kh_end(h)) {
      kh_del(mt, h, k);
      return;
    }
  }

  mrb_name_error(mrb, mid, "method `%s' not defined in %s",
    mrb_sym2name(mrb, mid), mrb_class_name(mrb, c));
}

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

mrb_value
mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
  struct RClass *c = mrb_class_ptr(mod);
  int argc;
  mrb_value *argv;

  mrb_get_args(mrb, "*", &argv, &argc);
  while (argc--) {
    remove_method(mrb, c, mrb_symbol(*argv));
    argv++;
  }
  return mod;
}

skandhas's avatar
skandhas committed
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
static void
check_const_name(mrb_state *mrb, mrb_sym id)
{
  const char *s;
  int len;

  s = mrb_sym2name_len(mrb, id, &len);
  if (len < 1 || !ISUPPER(*s)) {
    mrb_name_error(mrb, id, "wrong constant name %s", s);
  }
}

1717 1718 1719 1720 1721
mrb_value
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
{
  mrb_value sym;
  mrb_get_args(mrb, "o", &sym);
1722 1723

  check_const_name(mrb, mrb_sym_value(mrb,sym));
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
  if(mrb_const_defined(mrb, mod, mrb_sym_value(mrb, sym))) {
    return mrb_true_value();
  }
  return mrb_false_value();
}

mrb_value
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
  mrb_value sym;
  mrb_get_args(mrb, "o", &sym);
1735 1736

  check_const_name(mrb, mrb_sym_value(mrb,sym));
1737 1738 1739 1740 1741 1742 1743 1744
  return mrb_const_get(mrb, mod, mrb_sym_value(mrb, sym));
}

mrb_value
mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
{
  mrb_value sym, value;
  mrb_get_args(mrb, "oo", &sym, &value);
1745 1746

  check_const_name(mrb, mrb_sym_value(mrb,sym));
1747 1748 1749 1750
  mrb_const_set(mrb, mod, mrb_sym_value(mrb, sym), value);
  return value;
}

1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764
mrb_value
mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
{
  mrb_sym sym;
  mrb_value val;

  mrb_get_args(mrb, "n", &sym);
  check_const_name(mrb, sym);
  val = mrb_iv_remove(mrb, mod, sym);
  if (mrb_undef_p(val)) {
    mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
  }
  return val;
}
mimaki's avatar
mimaki committed
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779

static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
{
  mrb_value obj;

  mrb_get_args(mrb, "o", &obj);
  if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)))
    return mrb_false_value();
  return mrb_true_value();
}

void
mrb_init_class(mrb_state *mrb)
{
roco's avatar
roco committed
1780 1781 1782 1783
  struct RClass *bob;           /* BasicObject */
  struct RClass *obj;           /* Object */
  struct RClass *mod;           /* Module */
  struct RClass *cls;           /* Class */
mimaki's avatar
mimaki committed
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
  //struct RClass *krn;    /* Kernel */

  /* 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 */
1799
  mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
mimaki's avatar
mimaki committed
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
  mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
  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));

  /* name each classes */
  mrb_name_class(mrb, bob, mrb_intern(mrb, "BasicObject"));
  mrb_name_class(mrb, obj, mrb_intern(mrb, "Object"));
  mrb_name_class(mrb, mod, mrb_intern(mrb, "Module"));
  mrb_name_class(mrb, cls, mrb_intern(mrb, "Class"));

1811
  mrb_undef_method(mrb, mod, "new");
mimaki's avatar
mimaki committed
1812 1813 1814
  MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
  mrb_define_method(mrb, bob, "initialize", mrb_bob_init, ARGS_NONE());
  mrb_define_method(mrb, bob, "!", mrb_bob_not, ARGS_NONE());
1815
  mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, ARGS_ANY());        /* 15.3.1.3.30 */
Yuichiro MASUI's avatar
Yuichiro MASUI committed
1816
  mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, ARGS_ANY());
1817 1818
  mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, ARGS_NONE());      /* 15.2.3.3.4 */
  mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY());                  /* 15.2.3.3.3 */
1819
  mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1));
skandhas's avatar
skandhas committed
1820
  mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, ARGS_REQ(1));  /* 15.2.2.4.16 */
skandhas's avatar
skandhas committed
1821
  mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1));  /* 15.2.2.4.17 */
skandhas's avatar
skandhas committed
1822
  mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, ARGS_REQ(2));  /* 15.2.2.4.18 */
1823 1824
  mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1));  /* 15.2.2.4.25 */
  mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1));                /* 15.2.2.4.26 */
1825
  mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY());               /* 15.2.2.4.27 */
skandhas's avatar
skandhas committed
1826
  mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, ARGS_REQ(1));           /* 15.2.2.4.28 */
1827
  mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, ARGS_REQ(1)); /* 15.2.2.4.10 */
skandhas's avatar
skandhas committed
1828 1829
  mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, ARGS_ANY());           /* 15.2.2.4.15 */
  mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1));                     /* 15.2.2.4.29 */
1830
  mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */
skandhas's avatar
skandhas committed
1831
  mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, ARGS_ANY());  /* 15.2.2.4.33 */
skandhas's avatar
skandhas committed
1832
  mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, ARGS_REQ(1));    /* 15.2.2.4.34 */
skandhas's avatar
skandhas committed
1833
  mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, ARGS_ANY());            /* 15.2.2.4.35 */
skandhas's avatar
skandhas committed
1834
  mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, ARGS_REQ(1)); /* 15.2.2.4.39 */
1835
  mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, ARGS_ANY());        /* 15.2.2.4.41 */
mimaki's avatar
mimaki committed
1836 1837

  mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE());
1838
  mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, ARGS_NONE());
1839
  mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY());            /* 15.2.2.4.8 */
1840
  mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, ARGS_NONE());          /* 15.2.2.4.9 */
1841 1842 1843 1844
  mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, ARGS_ANY());            /* 15.2.2.4.41 */
  mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1)); /* 15.2.2.4.20 */
  mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1));          /* 15.2.2.4.21 */
  mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2));          /* 15.2.2.4.23 */
1845
  mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, ARGS_REQ(1));    /* 15.2.2.4.40 */
1846
  mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1));
skandhas's avatar
skandhas committed
1847
  mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, ARGS_NONE()); /* 15.2.2.4.19 */
mimaki's avatar
mimaki committed
1848 1849

  mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1));
1850
  mrb_undef_method(mrb, cls, "append_features");
1851
  mrb_undef_method(mrb, cls, "extend_object");
mimaki's avatar
mimaki committed
1852
}