mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** class.c - Class class
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include <ctype.h>
mzta 0:158c61bb030f 8 #include <stdarg.h>
mzta 0:158c61bb030f 9 #include "mruby.h"
mzta 0:158c61bb030f 10 #include "mruby/array.h"
mzta 0:158c61bb030f 11 #include "mruby/class.h"
mzta 0:158c61bb030f 12 #include "mruby/numeric.h"
mzta 0:158c61bb030f 13 #include "mruby/proc.h"
mzta 0:158c61bb030f 14 #include "mruby/string.h"
mzta 0:158c61bb030f 15 #include "mruby/variable.h"
mzta 0:158c61bb030f 16 #include "mruby/error.h"
mzta 0:158c61bb030f 17 #include "mruby/data.h"
mzta 0:158c61bb030f 18
mzta 0:158c61bb030f 19 KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
mzta 0:158c61bb030f 20
mzta 0:158c61bb030f 21 void
mzta 0:158c61bb030f 22 mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
mzta 0:158c61bb030f 23 {
mzta 0:158c61bb030f 24 khiter_t k;
mzta 0:158c61bb030f 25 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 26
mzta 0:158c61bb030f 27 if (!h) return;
mzta 0:158c61bb030f 28 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 29 if (kh_exist(h, k)) {
mzta 0:158c61bb030f 30 struct RProc *m = kh_value(h, k);
mzta 0:158c61bb030f 31 if (m) {
mzta 0:158c61bb030f 32 mrb_gc_mark(mrb, (struct RBasic*)m);
mzta 0:158c61bb030f 33 }
mzta 0:158c61bb030f 34 }
mzta 0:158c61bb030f 35 }
mzta 0:158c61bb030f 36 }
mzta 0:158c61bb030f 37
mzta 0:158c61bb030f 38 size_t
mzta 0:158c61bb030f 39 mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c)
mzta 0:158c61bb030f 40 {
mzta 0:158c61bb030f 41 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 42
mzta 0:158c61bb030f 43 if (!h) return 0;
mzta 0:158c61bb030f 44 return kh_size(h);
mzta 0:158c61bb030f 45 }
mzta 0:158c61bb030f 46
mzta 0:158c61bb030f 47 void
mzta 0:158c61bb030f 48 mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
mzta 0:158c61bb030f 49 {
mzta 0:158c61bb030f 50 kh_destroy(mt, mrb, c->mt);
mzta 0:158c61bb030f 51 }
mzta 0:158c61bb030f 52
mzta 0:158c61bb030f 53 static void
mzta 0:158c61bb030f 54 name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mzta 0:158c61bb030f 55 {
mzta 0:158c61bb030f 56 mrb_obj_iv_set(mrb, (struct RObject*)c,
mzta 0:158c61bb030f 57 mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
mzta 0:158c61bb030f 58 }
mzta 0:158c61bb030f 59
mzta 0:158c61bb030f 60 static void
mzta 0:158c61bb030f 61 setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
mzta 0:158c61bb030f 62 {
mzta 0:158c61bb030f 63 name_class(mrb, c, id);
mzta 0:158c61bb030f 64 mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
mzta 0:158c61bb030f 65 if (outer != mrb->object_class) {
mzta 0:158c61bb030f 66 mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
mzta 0:158c61bb030f 67 mrb_obj_value(outer));
mzta 0:158c61bb030f 68 }
mzta 0:158c61bb030f 69 }
mzta 0:158c61bb030f 70
mzta 0:158c61bb030f 71 #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
mzta 0:158c61bb030f 72
mzta 0:158c61bb030f 73 static void
mzta 0:158c61bb030f 74 prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
mzta 0:158c61bb030f 75 {
mzta 0:158c61bb030f 76 struct RClass *sc, *c;
mzta 0:158c61bb030f 77
mzta 0:158c61bb030f 78 if (o->c->tt == MRB_TT_SCLASS) return;
mzta 0:158c61bb030f 79 sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
mzta 0:158c61bb030f 80 sc->mt = 0;
mzta 0:158c61bb030f 81 sc->iv = 0;
mzta 0:158c61bb030f 82 if (o->tt == MRB_TT_CLASS) {
mzta 0:158c61bb030f 83 c = (struct RClass*)o;
mzta 0:158c61bb030f 84 if (!c->super) {
mzta 0:158c61bb030f 85 sc->super = mrb->class_class;
mzta 0:158c61bb030f 86 }
mzta 0:158c61bb030f 87 else {
mzta 0:158c61bb030f 88 sc->super = c->super->c;
mzta 0:158c61bb030f 89 }
mzta 0:158c61bb030f 90 }
mzta 0:158c61bb030f 91 else if (o->tt == MRB_TT_SCLASS) {
mzta 0:158c61bb030f 92 c = (struct RClass*)o;
mzta 0:158c61bb030f 93 while (c->super->tt == MRB_TT_ICLASS)
mzta 0:158c61bb030f 94 c = c->super;
mzta 0:158c61bb030f 95 make_metaclass(mrb, c->super);
mzta 0:158c61bb030f 96 sc->super = c->super->c;
mzta 0:158c61bb030f 97 }
mzta 0:158c61bb030f 98 else {
mzta 0:158c61bb030f 99 sc->super = o->c;
mzta 0:158c61bb030f 100 }
mzta 0:158c61bb030f 101 o->c = sc;
mzta 0:158c61bb030f 102 mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mzta 0:158c61bb030f 103 mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
mzta 0:158c61bb030f 104 mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
mzta 0:158c61bb030f 105 }
mzta 0:158c61bb030f 106
mzta 0:158c61bb030f 107 static struct RClass *
mzta 0:158c61bb030f 108 class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
mzta 0:158c61bb030f 109 {
mzta 0:158c61bb030f 110 mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
mzta 0:158c61bb030f 111
mzta 0:158c61bb030f 112 mrb_check_type(mrb, c, MRB_TT_CLASS);
mzta 0:158c61bb030f 113 return mrb_class_ptr(c);
mzta 0:158c61bb030f 114 }
mzta 0:158c61bb030f 115
mzta 0:158c61bb030f 116 static struct RClass *
mzta 0:158c61bb030f 117 module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
mzta 0:158c61bb030f 118 {
mzta 0:158c61bb030f 119 mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
mzta 0:158c61bb030f 120
mzta 0:158c61bb030f 121 mrb_check_type(mrb, c, MRB_TT_MODULE);
mzta 0:158c61bb030f 122 return mrb_class_ptr(c);
mzta 0:158c61bb030f 123 }
mzta 0:158c61bb030f 124
mzta 0:158c61bb030f 125 MRB_API struct RClass*
mzta 0:158c61bb030f 126 mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
mzta 0:158c61bb030f 127 {
mzta 0:158c61bb030f 128 mrb_value outer;
mzta 0:158c61bb030f 129
mzta 0:158c61bb030f 130 outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
mzta 0:158c61bb030f 131 if (mrb_nil_p(outer)) return NULL;
mzta 0:158c61bb030f 132 return mrb_class_ptr(outer);
mzta 0:158c61bb030f 133 }
mzta 0:158c61bb030f 134
mzta 0:158c61bb030f 135 static struct RClass*
mzta 0:158c61bb030f 136 define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
mzta 0:158c61bb030f 137 {
mzta 0:158c61bb030f 138 struct RClass *m;
mzta 0:158c61bb030f 139
mzta 0:158c61bb030f 140 if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
mzta 0:158c61bb030f 141 return module_from_sym(mrb, outer, name);
mzta 0:158c61bb030f 142 }
mzta 0:158c61bb030f 143 m = mrb_module_new(mrb);
mzta 0:158c61bb030f 144 setup_class(mrb, outer, m, name);
mzta 0:158c61bb030f 145
mzta 0:158c61bb030f 146 return m;
mzta 0:158c61bb030f 147 }
mzta 0:158c61bb030f 148
mzta 0:158c61bb030f 149 MRB_API struct RClass*
mzta 0:158c61bb030f 150 mrb_define_module_id(mrb_state *mrb, mrb_sym name)
mzta 0:158c61bb030f 151 {
mzta 0:158c61bb030f 152 return define_module(mrb, name, mrb->object_class);
mzta 0:158c61bb030f 153 }
mzta 0:158c61bb030f 154
mzta 0:158c61bb030f 155 MRB_API struct RClass*
mzta 0:158c61bb030f 156 mrb_define_module(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 157 {
mzta 0:158c61bb030f 158 return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
mzta 0:158c61bb030f 159 }
mzta 0:158c61bb030f 160
mzta 0:158c61bb030f 161 MRB_API struct RClass*
mzta 0:158c61bb030f 162 mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
mzta 0:158c61bb030f 163 {
mzta 0:158c61bb030f 164 return define_module(mrb, id, mrb_class_ptr(outer));
mzta 0:158c61bb030f 165 }
mzta 0:158c61bb030f 166
mzta 0:158c61bb030f 167 MRB_API struct RClass*
mzta 0:158c61bb030f 168 mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
mzta 0:158c61bb030f 169 {
mzta 0:158c61bb030f 170 mrb_sym id = mrb_intern_cstr(mrb, name);
mzta 0:158c61bb030f 171 struct RClass * c = define_module(mrb, id, outer);
mzta 0:158c61bb030f 172
mzta 0:158c61bb030f 173 setup_class(mrb, outer, c, id);
mzta 0:158c61bb030f 174 return c;
mzta 0:158c61bb030f 175 }
mzta 0:158c61bb030f 176
mzta 0:158c61bb030f 177 static struct RClass*
mzta 0:158c61bb030f 178 define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
mzta 0:158c61bb030f 179 {
mzta 0:158c61bb030f 180 struct RClass * c;
mzta 0:158c61bb030f 181
mzta 0:158c61bb030f 182 if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
mzta 0:158c61bb030f 183 c = class_from_sym(mrb, outer, name);
mzta 0:158c61bb030f 184 if (super && mrb_class_real(c->super) != super) {
mzta 0:158c61bb030f 185 mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
mzta 0:158c61bb030f 186 mrb_sym2str(mrb, name),
mzta 0:158c61bb030f 187 mrb_obj_value(c->super), mrb_obj_value(super));
mzta 0:158c61bb030f 188 }
mzta 0:158c61bb030f 189 return c;
mzta 0:158c61bb030f 190 }
mzta 0:158c61bb030f 191
mzta 0:158c61bb030f 192 c = mrb_class_new(mrb, super);
mzta 0:158c61bb030f 193 setup_class(mrb, outer, c, name);
mzta 0:158c61bb030f 194
mzta 0:158c61bb030f 195 return c;
mzta 0:158c61bb030f 196 }
mzta 0:158c61bb030f 197
mzta 0:158c61bb030f 198 MRB_API struct RClass*
mzta 0:158c61bb030f 199 mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
mzta 0:158c61bb030f 200 {
mzta 0:158c61bb030f 201 if (!super) {
mzta 0:158c61bb030f 202 mrb_warn(mrb, "no super class for `%S', Object assumed", mrb_sym2str(mrb, name));
mzta 0:158c61bb030f 203 }
mzta 0:158c61bb030f 204 return define_class(mrb, name, super, mrb->object_class);
mzta 0:158c61bb030f 205 }
mzta 0:158c61bb030f 206
mzta 0:158c61bb030f 207 MRB_API struct RClass*
mzta 0:158c61bb030f 208 mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
mzta 0:158c61bb030f 209 {
mzta 0:158c61bb030f 210 return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
mzta 0:158c61bb030f 211 }
mzta 0:158c61bb030f 212
mzta 0:158c61bb030f 213 static void
mzta 0:158c61bb030f 214 mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
mzta 0:158c61bb030f 215 {
mzta 0:158c61bb030f 216 if (!super)
mzta 0:158c61bb030f 217 super = mrb->object_class;
mzta 0:158c61bb030f 218 mrb_funcall(mrb, mrb_obj_value(super), "inherited", 1, mrb_obj_value(klass));
mzta 0:158c61bb030f 219 }
mzta 0:158c61bb030f 220
mzta 0:158c61bb030f 221 MRB_API struct RClass*
mzta 0:158c61bb030f 222 mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
mzta 0:158c61bb030f 223 {
mzta 0:158c61bb030f 224 struct RClass *s;
mzta 0:158c61bb030f 225 struct RClass *c;
mzta 0:158c61bb030f 226
mzta 0:158c61bb030f 227 if (!mrb_nil_p(super)) {
mzta 0:158c61bb030f 228 if (mrb_type(super) != MRB_TT_CLASS) {
mzta 0:158c61bb030f 229 mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
mzta 0:158c61bb030f 230 }
mzta 0:158c61bb030f 231 s = mrb_class_ptr(super);
mzta 0:158c61bb030f 232 }
mzta 0:158c61bb030f 233 else {
mzta 0:158c61bb030f 234 s = 0;
mzta 0:158c61bb030f 235 }
mzta 0:158c61bb030f 236 switch (mrb_type(outer)) {
mzta 0:158c61bb030f 237 case MRB_TT_CLASS:
mzta 0:158c61bb030f 238 case MRB_TT_SCLASS:
mzta 0:158c61bb030f 239 case MRB_TT_MODULE:
mzta 0:158c61bb030f 240 break;
mzta 0:158c61bb030f 241 default:
mzta 0:158c61bb030f 242 mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer);
mzta 0:158c61bb030f 243 break;
mzta 0:158c61bb030f 244 }
mzta 0:158c61bb030f 245 c = define_class(mrb, id, s, mrb_class_ptr(outer));
mzta 0:158c61bb030f 246 mrb_class_inherited(mrb, mrb_class_real(c->super), c);
mzta 0:158c61bb030f 247
mzta 0:158c61bb030f 248 return c;
mzta 0:158c61bb030f 249 }
mzta 0:158c61bb030f 250
mzta 0:158c61bb030f 251 MRB_API mrb_bool
mzta 0:158c61bb030f 252 mrb_class_defined(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 253 {
mzta 0:158c61bb030f 254 mrb_value sym = mrb_check_intern_cstr(mrb, name);
mzta 0:158c61bb030f 255 if (mrb_nil_p(sym)) {
mzta 0:158c61bb030f 256 return FALSE;
mzta 0:158c61bb030f 257 }
mzta 0:158c61bb030f 258 return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
mzta 0:158c61bb030f 259 }
mzta 0:158c61bb030f 260
mzta 0:158c61bb030f 261 MRB_API struct RClass *
mzta 0:158c61bb030f 262 mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
mzta 0:158c61bb030f 263 {
mzta 0:158c61bb030f 264 return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
mzta 0:158c61bb030f 265 }
mzta 0:158c61bb030f 266
mzta 0:158c61bb030f 267 MRB_API struct RClass *
mzta 0:158c61bb030f 268 mrb_class_get(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 269 {
mzta 0:158c61bb030f 270 return mrb_class_get_under(mrb, mrb->object_class, name);
mzta 0:158c61bb030f 271 }
mzta 0:158c61bb030f 272
mzta 0:158c61bb030f 273 MRB_API struct RClass *
mzta 0:158c61bb030f 274 mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
mzta 0:158c61bb030f 275 {
mzta 0:158c61bb030f 276 return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
mzta 0:158c61bb030f 277 }
mzta 0:158c61bb030f 278
mzta 0:158c61bb030f 279 MRB_API struct RClass *
mzta 0:158c61bb030f 280 mrb_module_get(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 281 {
mzta 0:158c61bb030f 282 return mrb_module_get_under(mrb, mrb->object_class, name);
mzta 0:158c61bb030f 283 }
mzta 0:158c61bb030f 284
mzta 0:158c61bb030f 285 /*!
mzta 0:158c61bb030f 286 * Defines a class under the namespace of \a outer.
mzta 0:158c61bb030f 287 * \param outer a class which contains the new class.
mzta 0:158c61bb030f 288 * \param id name of the new class
mzta 0:158c61bb030f 289 * \param super a class from which the new class will derive.
mzta 0:158c61bb030f 290 * NULL means \c Object class.
mzta 0:158c61bb030f 291 * \return the created class
mzta 0:158c61bb030f 292 * \throw TypeError if the constant name \a name is already taken but
mzta 0:158c61bb030f 293 * the constant is not a \c Class.
mzta 0:158c61bb030f 294 * \throw NameError if the class is already defined but the class can not
mzta 0:158c61bb030f 295 * be reopened because its superclass is not \a super.
mzta 0:158c61bb030f 296 * \post top-level constant named \a name refers the returned class.
mzta 0:158c61bb030f 297 *
mzta 0:158c61bb030f 298 * \note if a class named \a name is already defined and its superclass is
mzta 0:158c61bb030f 299 * \a super, the function just returns the defined class.
mzta 0:158c61bb030f 300 */
mzta 0:158c61bb030f 301 MRB_API struct RClass *
mzta 0:158c61bb030f 302 mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
mzta 0:158c61bb030f 303 {
mzta 0:158c61bb030f 304 mrb_sym id = mrb_intern_cstr(mrb, name);
mzta 0:158c61bb030f 305 struct RClass * c;
mzta 0:158c61bb030f 306
mzta 0:158c61bb030f 307 #if 0
mzta 0:158c61bb030f 308 if (!super) {
mzta 0:158c61bb030f 309 mrb_warn(mrb, "no super class for `%S::%S', Object assumed",
mzta 0:158c61bb030f 310 mrb_obj_value(outer), mrb_sym2str(mrb, id));
mzta 0:158c61bb030f 311 }
mzta 0:158c61bb030f 312 #endif
mzta 0:158c61bb030f 313 c = define_class(mrb, id, super, outer);
mzta 0:158c61bb030f 314 setup_class(mrb, outer, c, id);
mzta 0:158c61bb030f 315 return c;
mzta 0:158c61bb030f 316 }
mzta 0:158c61bb030f 317
mzta 0:158c61bb030f 318 MRB_API void
mzta 0:158c61bb030f 319 mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
mzta 0:158c61bb030f 320 {
mzta 0:158c61bb030f 321 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 322 khiter_t k;
mzta 0:158c61bb030f 323
mzta 0:158c61bb030f 324 if (!h) h = c->mt = kh_init(mt, mrb);
mzta 0:158c61bb030f 325 k = kh_put(mt, mrb, h, mid);
mzta 0:158c61bb030f 326 kh_value(h, k) = p;
mzta 0:158c61bb030f 327 if (p) {
mzta 0:158c61bb030f 328 mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
mzta 0:158c61bb030f 329 }
mzta 0:158c61bb030f 330 }
mzta 0:158c61bb030f 331
mzta 0:158c61bb030f 332 MRB_API void
mzta 0:158c61bb030f 333 mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
mzta 0:158c61bb030f 334 {
mzta 0:158c61bb030f 335 struct RProc *p;
mzta 0:158c61bb030f 336 int ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 337
mzta 0:158c61bb030f 338 p = mrb_proc_new_cfunc(mrb, func);
mzta 0:158c61bb030f 339 p->target_class = c;
mzta 0:158c61bb030f 340 mrb_define_method_raw(mrb, c, mid, p);
mzta 0:158c61bb030f 341 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 342 }
mzta 0:158c61bb030f 343
mzta 0:158c61bb030f 344 MRB_API void
mzta 0:158c61bb030f 345 mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
mzta 0:158c61bb030f 346 {
mzta 0:158c61bb030f 347 mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
mzta 0:158c61bb030f 348 }
mzta 0:158c61bb030f 349
mzta 0:158c61bb030f 350 MRB_API void
mzta 0:158c61bb030f 351 mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value body)
mzta 0:158c61bb030f 352 {
mzta 0:158c61bb030f 353 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 354 khiter_t k;
mzta 0:158c61bb030f 355 struct RProc *p;
mzta 0:158c61bb030f 356
mzta 0:158c61bb030f 357 if (!h) h = c->mt = kh_init(mt, mrb);
mzta 0:158c61bb030f 358 k = kh_put(mt, mrb, h, name);
mzta 0:158c61bb030f 359 p = mrb_proc_ptr(body);
mzta 0:158c61bb030f 360 kh_value(h, k) = p;
mzta 0:158c61bb030f 361 if (p) {
mzta 0:158c61bb030f 362 mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
mzta 0:158c61bb030f 363 }
mzta 0:158c61bb030f 364 }
mzta 0:158c61bb030f 365
mzta 0:158c61bb030f 366 /* a function to raise NotImplementedError with current method name */
mzta 0:158c61bb030f 367 MRB_API void
mzta 0:158c61bb030f 368 mrb_notimplement(mrb_state *mrb)
mzta 0:158c61bb030f 369 {
mzta 0:158c61bb030f 370 const char *str;
mzta 0:158c61bb030f 371 mrb_int len;
mzta 0:158c61bb030f 372 mrb_callinfo *ci = mrb->c->ci;
mzta 0:158c61bb030f 373
mzta 0:158c61bb030f 374 if (ci->mid) {
mzta 0:158c61bb030f 375 str = mrb_sym2name_len(mrb, ci->mid, &len);
mzta 0:158c61bb030f 376 mrb_raisef(mrb, E_NOTIMP_ERROR,
mzta 0:158c61bb030f 377 "%S() function is unimplemented on this machine",
mzta 0:158c61bb030f 378 mrb_str_new_static(mrb, str, (size_t)len));
mzta 0:158c61bb030f 379 }
mzta 0:158c61bb030f 380 }
mzta 0:158c61bb030f 381
mzta 0:158c61bb030f 382 /* a function to be replacement of unimplemented method */
mzta 0:158c61bb030f 383 MRB_API mrb_value
mzta 0:158c61bb030f 384 mrb_notimplement_m(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 385 {
mzta 0:158c61bb030f 386 mrb_notimplement(mrb);
mzta 0:158c61bb030f 387 /* not reached */
mzta 0:158c61bb030f 388 return mrb_nil_value();
mzta 0:158c61bb030f 389 }
mzta 0:158c61bb030f 390
mzta 0:158c61bb030f 391 static mrb_value
mzta 0:158c61bb030f 392 check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
mzta 0:158c61bb030f 393 {
mzta 0:158c61bb030f 394 mrb_value tmp;
mzta 0:158c61bb030f 395
mzta 0:158c61bb030f 396 tmp = mrb_check_convert_type(mrb, val, t, c, m);
mzta 0:158c61bb030f 397 if (mrb_nil_p(tmp)) {
mzta 0:158c61bb030f 398 mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
mzta 0:158c61bb030f 399 }
mzta 0:158c61bb030f 400 return tmp;
mzta 0:158c61bb030f 401 }
mzta 0:158c61bb030f 402
mzta 0:158c61bb030f 403 static mrb_value
mzta 0:158c61bb030f 404 to_str(mrb_state *mrb, mrb_value val)
mzta 0:158c61bb030f 405 {
mzta 0:158c61bb030f 406 return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
mzta 0:158c61bb030f 407 }
mzta 0:158c61bb030f 408
mzta 0:158c61bb030f 409 static mrb_value
mzta 0:158c61bb030f 410 to_ary(mrb_state *mrb, mrb_value val)
mzta 0:158c61bb030f 411 {
mzta 0:158c61bb030f 412 return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
mzta 0:158c61bb030f 413 }
mzta 0:158c61bb030f 414
mzta 0:158c61bb030f 415 static mrb_value
mzta 0:158c61bb030f 416 to_hash(mrb_state *mrb, mrb_value val)
mzta 0:158c61bb030f 417 {
mzta 0:158c61bb030f 418 return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
mzta 0:158c61bb030f 419 }
mzta 0:158c61bb030f 420
mzta 0:158c61bb030f 421 static mrb_sym
mzta 0:158c61bb030f 422 to_sym(mrb_state *mrb, mrb_value ss)
mzta 0:158c61bb030f 423 {
mzta 0:158c61bb030f 424 if (mrb_type(ss) == MRB_TT_SYMBOL) {
mzta 0:158c61bb030f 425 return mrb_symbol(ss);
mzta 0:158c61bb030f 426 }
mzta 0:158c61bb030f 427 else if (mrb_string_p(ss)) {
mzta 0:158c61bb030f 428 return mrb_intern_str(mrb, to_str(mrb, ss));
mzta 0:158c61bb030f 429 }
mzta 0:158c61bb030f 430 else {
mzta 0:158c61bb030f 431 mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
mzta 0:158c61bb030f 432 mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
mzta 0:158c61bb030f 433 }
mzta 0:158c61bb030f 434 }
mzta 0:158c61bb030f 435
mzta 0:158c61bb030f 436 /*
mzta 0:158c61bb030f 437 retrieve arguments from mrb_state.
mzta 0:158c61bb030f 438
mzta 0:158c61bb030f 439 mrb_get_args(mrb, format, ...)
mzta 0:158c61bb030f 440
mzta 0:158c61bb030f 441 returns number of arguments parsed.
mzta 0:158c61bb030f 442
mzta 0:158c61bb030f 443 format specifiers:
mzta 0:158c61bb030f 444
mzta 0:158c61bb030f 445 string mruby type C type note
mzta 0:158c61bb030f 446 ----------------------------------------------------------------------------------------------
mzta 0:158c61bb030f 447 o: Object [mrb_value]
mzta 0:158c61bb030f 448 C: class/module [mrb_value]
mzta 0:158c61bb030f 449 S: String [mrb_value]
mzta 0:158c61bb030f 450 A: Array [mrb_value]
mzta 0:158c61bb030f 451 H: Hash [mrb_value]
mzta 0:158c61bb030f 452 s: String [char*,mrb_int] Receive two arguments.
mzta 0:158c61bb030f 453 z: String [char*] NUL terminated string.
mzta 0:158c61bb030f 454 a: Array [mrb_value*,mrb_int] Receive two arguments.
mzta 0:158c61bb030f 455 f: Float [mrb_float]
mzta 0:158c61bb030f 456 i: Integer [mrb_int]
mzta 0:158c61bb030f 457 b: Boolean [mrb_bool]
mzta 0:158c61bb030f 458 n: Symbol [mrb_sym]
mzta 0:158c61bb030f 459 d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
mzta 0:158c61bb030f 460 &: Block [mrb_value]
mzta 0:158c61bb030f 461 *: rest argument [mrb_value*,mrb_int] Receive the rest of the arguments as an array.
mzta 0:158c61bb030f 462 |: optional Next argument of '|' and later are optional.
mzta 0:158c61bb030f 463 ?: optional given [mrb_bool] true if preceding argument (optional) is given.
mzta 0:158c61bb030f 464 */
mzta 0:158c61bb030f 465 MRB_API mrb_int
mzta 0:158c61bb030f 466 mrb_get_args(mrb_state *mrb, const char *format, ...)
mzta 0:158c61bb030f 467 {
mzta 0:158c61bb030f 468 char c;
mzta 0:158c61bb030f 469 int i = 0;
mzta 0:158c61bb030f 470 mrb_value *sp = mrb->c->stack + 1;
mzta 0:158c61bb030f 471 va_list ap;
mzta 0:158c61bb030f 472 int argc = mrb->c->ci->argc;
mzta 0:158c61bb030f 473 mrb_bool opt = FALSE;
mzta 0:158c61bb030f 474 mrb_bool given = TRUE;
mzta 0:158c61bb030f 475
mzta 0:158c61bb030f 476 va_start(ap, format);
mzta 0:158c61bb030f 477 if (argc < 0) {
mzta 0:158c61bb030f 478 struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
mzta 0:158c61bb030f 479
mzta 0:158c61bb030f 480 argc = a->len;
mzta 0:158c61bb030f 481 sp = a->ptr;
mzta 0:158c61bb030f 482 }
mzta 0:158c61bb030f 483 while ((c = *format++)) {
mzta 0:158c61bb030f 484 switch (c) {
mzta 0:158c61bb030f 485 case '|': case '*': case '&': case '?':
mzta 0:158c61bb030f 486 break;
mzta 0:158c61bb030f 487 default:
mzta 0:158c61bb030f 488 if (argc <= i) {
mzta 0:158c61bb030f 489 if (opt) {
mzta 0:158c61bb030f 490 given = FALSE;
mzta 0:158c61bb030f 491 }
mzta 0:158c61bb030f 492 else {
mzta 0:158c61bb030f 493 mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
mzta 0:158c61bb030f 494 }
mzta 0:158c61bb030f 495 }
mzta 0:158c61bb030f 496 break;
mzta 0:158c61bb030f 497 }
mzta 0:158c61bb030f 498
mzta 0:158c61bb030f 499 switch (c) {
mzta 0:158c61bb030f 500 case 'o':
mzta 0:158c61bb030f 501 {
mzta 0:158c61bb030f 502 mrb_value *p;
mzta 0:158c61bb030f 503
mzta 0:158c61bb030f 504 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 505 if (i < argc) {
mzta 0:158c61bb030f 506 *p = *sp++;
mzta 0:158c61bb030f 507 i++;
mzta 0:158c61bb030f 508 }
mzta 0:158c61bb030f 509 }
mzta 0:158c61bb030f 510 break;
mzta 0:158c61bb030f 511 case 'C':
mzta 0:158c61bb030f 512 {
mzta 0:158c61bb030f 513 mrb_value *p;
mzta 0:158c61bb030f 514
mzta 0:158c61bb030f 515 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 516 if (i < argc) {
mzta 0:158c61bb030f 517 mrb_value ss;
mzta 0:158c61bb030f 518
mzta 0:158c61bb030f 519 ss = *sp++;
mzta 0:158c61bb030f 520 switch (mrb_type(ss)) {
mzta 0:158c61bb030f 521 case MRB_TT_CLASS:
mzta 0:158c61bb030f 522 case MRB_TT_MODULE:
mzta 0:158c61bb030f 523 case MRB_TT_SCLASS:
mzta 0:158c61bb030f 524 break;
mzta 0:158c61bb030f 525 default:
mzta 0:158c61bb030f 526 mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
mzta 0:158c61bb030f 527 break;
mzta 0:158c61bb030f 528 }
mzta 0:158c61bb030f 529 *p = ss;
mzta 0:158c61bb030f 530 i++;
mzta 0:158c61bb030f 531 }
mzta 0:158c61bb030f 532 }
mzta 0:158c61bb030f 533 break;
mzta 0:158c61bb030f 534 case 'S':
mzta 0:158c61bb030f 535 {
mzta 0:158c61bb030f 536 mrb_value *p;
mzta 0:158c61bb030f 537
mzta 0:158c61bb030f 538 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 539 if (i < argc) {
mzta 0:158c61bb030f 540 *p = to_str(mrb, *sp++);
mzta 0:158c61bb030f 541 i++;
mzta 0:158c61bb030f 542 }
mzta 0:158c61bb030f 543 }
mzta 0:158c61bb030f 544 break;
mzta 0:158c61bb030f 545 case 'A':
mzta 0:158c61bb030f 546 {
mzta 0:158c61bb030f 547 mrb_value *p;
mzta 0:158c61bb030f 548
mzta 0:158c61bb030f 549 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 550 if (i < argc) {
mzta 0:158c61bb030f 551 *p = to_ary(mrb, *sp++);
mzta 0:158c61bb030f 552 i++;
mzta 0:158c61bb030f 553 }
mzta 0:158c61bb030f 554 }
mzta 0:158c61bb030f 555 break;
mzta 0:158c61bb030f 556 case 'H':
mzta 0:158c61bb030f 557 {
mzta 0:158c61bb030f 558 mrb_value *p;
mzta 0:158c61bb030f 559
mzta 0:158c61bb030f 560 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 561 if (i < argc) {
mzta 0:158c61bb030f 562 *p = to_hash(mrb, *sp++);
mzta 0:158c61bb030f 563 i++;
mzta 0:158c61bb030f 564 }
mzta 0:158c61bb030f 565 }
mzta 0:158c61bb030f 566 break;
mzta 0:158c61bb030f 567 case 's':
mzta 0:158c61bb030f 568 {
mzta 0:158c61bb030f 569 mrb_value ss;
mzta 0:158c61bb030f 570 char **ps = 0;
mzta 0:158c61bb030f 571 mrb_int *pl = 0;
mzta 0:158c61bb030f 572
mzta 0:158c61bb030f 573 ps = va_arg(ap, char**);
mzta 0:158c61bb030f 574 pl = va_arg(ap, mrb_int*);
mzta 0:158c61bb030f 575 if (i < argc) {
mzta 0:158c61bb030f 576 ss = to_str(mrb, *sp++);
mzta 0:158c61bb030f 577 *ps = RSTRING_PTR(ss);
mzta 0:158c61bb030f 578 *pl = RSTRING_LEN(ss);
mzta 0:158c61bb030f 579 i++;
mzta 0:158c61bb030f 580 }
mzta 0:158c61bb030f 581 }
mzta 0:158c61bb030f 582 break;
mzta 0:158c61bb030f 583 case 'z':
mzta 0:158c61bb030f 584 {
mzta 0:158c61bb030f 585 mrb_value ss;
mzta 0:158c61bb030f 586 const char **ps;
mzta 0:158c61bb030f 587
mzta 0:158c61bb030f 588 ps = va_arg(ap, const char**);
mzta 0:158c61bb030f 589 if (i < argc) {
mzta 0:158c61bb030f 590 ss = to_str(mrb, *sp++);
mzta 0:158c61bb030f 591 *ps = mrb_string_value_cstr(mrb, &ss);
mzta 0:158c61bb030f 592 i++;
mzta 0:158c61bb030f 593 }
mzta 0:158c61bb030f 594 }
mzta 0:158c61bb030f 595 break;
mzta 0:158c61bb030f 596 case 'a':
mzta 0:158c61bb030f 597 {
mzta 0:158c61bb030f 598 mrb_value aa;
mzta 0:158c61bb030f 599 struct RArray *a;
mzta 0:158c61bb030f 600 mrb_value **pb;
mzta 0:158c61bb030f 601 mrb_int *pl;
mzta 0:158c61bb030f 602
mzta 0:158c61bb030f 603 pb = va_arg(ap, mrb_value**);
mzta 0:158c61bb030f 604 pl = va_arg(ap, mrb_int*);
mzta 0:158c61bb030f 605 if (i < argc) {
mzta 0:158c61bb030f 606 aa = to_ary(mrb, *sp++);
mzta 0:158c61bb030f 607 a = mrb_ary_ptr(aa);
mzta 0:158c61bb030f 608 *pb = a->ptr;
mzta 0:158c61bb030f 609 *pl = a->len;
mzta 0:158c61bb030f 610 i++;
mzta 0:158c61bb030f 611 }
mzta 0:158c61bb030f 612 }
mzta 0:158c61bb030f 613 break;
mzta 0:158c61bb030f 614 case 'f':
mzta 0:158c61bb030f 615 {
mzta 0:158c61bb030f 616 mrb_float *p;
mzta 0:158c61bb030f 617
mzta 0:158c61bb030f 618 p = va_arg(ap, mrb_float*);
mzta 0:158c61bb030f 619 if (i < argc) {
mzta 0:158c61bb030f 620 *p = mrb_to_flo(mrb, *sp);
mzta 0:158c61bb030f 621 sp++;
mzta 0:158c61bb030f 622 i++;
mzta 0:158c61bb030f 623 }
mzta 0:158c61bb030f 624 }
mzta 0:158c61bb030f 625 break;
mzta 0:158c61bb030f 626 case 'i':
mzta 0:158c61bb030f 627 {
mzta 0:158c61bb030f 628 mrb_int *p;
mzta 0:158c61bb030f 629
mzta 0:158c61bb030f 630 p = va_arg(ap, mrb_int*);
mzta 0:158c61bb030f 631 if (i < argc) {
mzta 0:158c61bb030f 632 switch (mrb_type(*sp)) {
mzta 0:158c61bb030f 633 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 634 *p = mrb_fixnum(*sp);
mzta 0:158c61bb030f 635 break;
mzta 0:158c61bb030f 636 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 637 {
mzta 0:158c61bb030f 638 mrb_float f = mrb_float(*sp);
mzta 0:158c61bb030f 639
mzta 0:158c61bb030f 640 if (!FIXABLE(f)) {
mzta 0:158c61bb030f 641 mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
mzta 0:158c61bb030f 642 }
mzta 0:158c61bb030f 643 *p = (mrb_int)f;
mzta 0:158c61bb030f 644 }
mzta 0:158c61bb030f 645 break;
mzta 0:158c61bb030f 646 case MRB_TT_STRING:
mzta 0:158c61bb030f 647 mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
mzta 0:158c61bb030f 648 break;
mzta 0:158c61bb030f 649 default:
mzta 0:158c61bb030f 650 *p = mrb_fixnum(mrb_Integer(mrb, *sp));
mzta 0:158c61bb030f 651 break;
mzta 0:158c61bb030f 652 }
mzta 0:158c61bb030f 653 sp++;
mzta 0:158c61bb030f 654 i++;
mzta 0:158c61bb030f 655 }
mzta 0:158c61bb030f 656 }
mzta 0:158c61bb030f 657 break;
mzta 0:158c61bb030f 658 case 'b':
mzta 0:158c61bb030f 659 {
mzta 0:158c61bb030f 660 mrb_bool *boolp = va_arg(ap, mrb_bool*);
mzta 0:158c61bb030f 661
mzta 0:158c61bb030f 662 if (i < argc) {
mzta 0:158c61bb030f 663 mrb_value b = *sp++;
mzta 0:158c61bb030f 664 *boolp = mrb_test(b);
mzta 0:158c61bb030f 665 i++;
mzta 0:158c61bb030f 666 }
mzta 0:158c61bb030f 667 }
mzta 0:158c61bb030f 668 break;
mzta 0:158c61bb030f 669 case 'n':
mzta 0:158c61bb030f 670 {
mzta 0:158c61bb030f 671 mrb_sym *symp;
mzta 0:158c61bb030f 672
mzta 0:158c61bb030f 673 symp = va_arg(ap, mrb_sym*);
mzta 0:158c61bb030f 674 if (i < argc) {
mzta 0:158c61bb030f 675 mrb_value ss;
mzta 0:158c61bb030f 676
mzta 0:158c61bb030f 677 ss = *sp++;
mzta 0:158c61bb030f 678 *symp = to_sym(mrb, ss);
mzta 0:158c61bb030f 679 i++;
mzta 0:158c61bb030f 680 }
mzta 0:158c61bb030f 681 }
mzta 0:158c61bb030f 682 break;
mzta 0:158c61bb030f 683 case 'd':
mzta 0:158c61bb030f 684 {
mzta 0:158c61bb030f 685 void** datap;
mzta 0:158c61bb030f 686 struct mrb_data_type const* type;
mzta 0:158c61bb030f 687
mzta 0:158c61bb030f 688 datap = va_arg(ap, void**);
mzta 0:158c61bb030f 689 type = va_arg(ap, struct mrb_data_type const*);
mzta 0:158c61bb030f 690 if (i < argc) {
mzta 0:158c61bb030f 691 *datap = mrb_data_get_ptr(mrb, *sp++, type);
mzta 0:158c61bb030f 692 ++i;
mzta 0:158c61bb030f 693 }
mzta 0:158c61bb030f 694 }
mzta 0:158c61bb030f 695 break;
mzta 0:158c61bb030f 696
mzta 0:158c61bb030f 697 case '&':
mzta 0:158c61bb030f 698 {
mzta 0:158c61bb030f 699 mrb_value *p, *bp;
mzta 0:158c61bb030f 700
mzta 0:158c61bb030f 701 p = va_arg(ap, mrb_value*);
mzta 0:158c61bb030f 702 if (mrb->c->ci->argc < 0) {
mzta 0:158c61bb030f 703 bp = mrb->c->stack + 2;
mzta 0:158c61bb030f 704 }
mzta 0:158c61bb030f 705 else {
mzta 0:158c61bb030f 706 bp = mrb->c->stack + mrb->c->ci->argc + 1;
mzta 0:158c61bb030f 707 }
mzta 0:158c61bb030f 708 *p = *bp;
mzta 0:158c61bb030f 709 }
mzta 0:158c61bb030f 710 break;
mzta 0:158c61bb030f 711 case '|':
mzta 0:158c61bb030f 712 opt = TRUE;
mzta 0:158c61bb030f 713 break;
mzta 0:158c61bb030f 714 case '?':
mzta 0:158c61bb030f 715 {
mzta 0:158c61bb030f 716 mrb_bool *p;
mzta 0:158c61bb030f 717
mzta 0:158c61bb030f 718 p = va_arg(ap, mrb_bool*);
mzta 0:158c61bb030f 719 *p = given;
mzta 0:158c61bb030f 720 }
mzta 0:158c61bb030f 721 break;
mzta 0:158c61bb030f 722
mzta 0:158c61bb030f 723 case '*':
mzta 0:158c61bb030f 724 {
mzta 0:158c61bb030f 725 mrb_value **var;
mzta 0:158c61bb030f 726 mrb_int *pl;
mzta 0:158c61bb030f 727
mzta 0:158c61bb030f 728 var = va_arg(ap, mrb_value**);
mzta 0:158c61bb030f 729 pl = va_arg(ap, mrb_int*);
mzta 0:158c61bb030f 730 if (argc > i) {
mzta 0:158c61bb030f 731 *pl = argc-i;
mzta 0:158c61bb030f 732 if (*pl > 0) {
mzta 0:158c61bb030f 733 *var = sp;
mzta 0:158c61bb030f 734 }
mzta 0:158c61bb030f 735 i = argc;
mzta 0:158c61bb030f 736 sp += *pl;
mzta 0:158c61bb030f 737 }
mzta 0:158c61bb030f 738 else {
mzta 0:158c61bb030f 739 *pl = 0;
mzta 0:158c61bb030f 740 *var = NULL;
mzta 0:158c61bb030f 741 }
mzta 0:158c61bb030f 742 }
mzta 0:158c61bb030f 743 break;
mzta 0:158c61bb030f 744 default:
mzta 0:158c61bb030f 745 mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
mzta 0:158c61bb030f 746 break;
mzta 0:158c61bb030f 747 }
mzta 0:158c61bb030f 748 }
mzta 0:158c61bb030f 749 if (!c && argc > i) {
mzta 0:158c61bb030f 750 mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
mzta 0:158c61bb030f 751 }
mzta 0:158c61bb030f 752 va_end(ap);
mzta 0:158c61bb030f 753 return i;
mzta 0:158c61bb030f 754 }
mzta 0:158c61bb030f 755
mzta 0:158c61bb030f 756 static struct RClass*
mzta 0:158c61bb030f 757 boot_defclass(mrb_state *mrb, struct RClass *super)
mzta 0:158c61bb030f 758 {
mzta 0:158c61bb030f 759 struct RClass *c;
mzta 0:158c61bb030f 760
mzta 0:158c61bb030f 761 c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
mzta 0:158c61bb030f 762 if (super) {
mzta 0:158c61bb030f 763 c->super = super;
mzta 0:158c61bb030f 764 mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
mzta 0:158c61bb030f 765 }
mzta 0:158c61bb030f 766 else {
mzta 0:158c61bb030f 767 c->super = mrb->object_class;
mzta 0:158c61bb030f 768 }
mzta 0:158c61bb030f 769 c->mt = kh_init(mt, mrb);
mzta 0:158c61bb030f 770 return c;
mzta 0:158c61bb030f 771 }
mzta 0:158c61bb030f 772
mzta 0:158c61bb030f 773 MRB_API void
mzta 0:158c61bb030f 774 mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
mzta 0:158c61bb030f 775 {
mzta 0:158c61bb030f 776 struct RClass *ins_pos;
mzta 0:158c61bb030f 777
mzta 0:158c61bb030f 778 ins_pos = c;
mzta 0:158c61bb030f 779 while (m) {
mzta 0:158c61bb030f 780 struct RClass *p = c, *ic;
mzta 0:158c61bb030f 781 int superclass_seen = 0;
mzta 0:158c61bb030f 782
mzta 0:158c61bb030f 783 if (c->mt && c->mt == m->mt) {
mzta 0:158c61bb030f 784 mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
mzta 0:158c61bb030f 785 }
mzta 0:158c61bb030f 786 while (p) {
mzta 0:158c61bb030f 787 if (c != p && p->tt == MRB_TT_CLASS) {
mzta 0:158c61bb030f 788 superclass_seen = 1;
mzta 0:158c61bb030f 789 }
mzta 0:158c61bb030f 790 else if (p->mt == m->mt) {
mzta 0:158c61bb030f 791 if (p->tt == MRB_TT_ICLASS && !superclass_seen) {
mzta 0:158c61bb030f 792 ins_pos = p;
mzta 0:158c61bb030f 793 }
mzta 0:158c61bb030f 794 goto skip;
mzta 0:158c61bb030f 795 }
mzta 0:158c61bb030f 796 p = p->super;
mzta 0:158c61bb030f 797 }
mzta 0:158c61bb030f 798 ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
mzta 0:158c61bb030f 799 if (m->tt == MRB_TT_ICLASS) {
mzta 0:158c61bb030f 800 ic->c = m->c;
mzta 0:158c61bb030f 801 }
mzta 0:158c61bb030f 802 else {
mzta 0:158c61bb030f 803 ic->c = m;
mzta 0:158c61bb030f 804 }
mzta 0:158c61bb030f 805 ic->mt = m->mt;
mzta 0:158c61bb030f 806 ic->iv = m->iv;
mzta 0:158c61bb030f 807 ic->super = ins_pos->super;
mzta 0:158c61bb030f 808 ins_pos->super = ic;
mzta 0:158c61bb030f 809 mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
mzta 0:158c61bb030f 810 ins_pos = ic;
mzta 0:158c61bb030f 811 skip:
mzta 0:158c61bb030f 812 m = m->super;
mzta 0:158c61bb030f 813 }
mzta 0:158c61bb030f 814 }
mzta 0:158c61bb030f 815
mzta 0:158c61bb030f 816 static mrb_value
mzta 0:158c61bb030f 817 mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 818 {
mzta 0:158c61bb030f 819 mrb_value klass;
mzta 0:158c61bb030f 820
mzta 0:158c61bb030f 821 mrb_check_type(mrb, mod, MRB_TT_MODULE);
mzta 0:158c61bb030f 822 mrb_get_args(mrb, "C", &klass);
mzta 0:158c61bb030f 823 mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
mzta 0:158c61bb030f 824 return mod;
mzta 0:158c61bb030f 825 }
mzta 0:158c61bb030f 826
mzta 0:158c61bb030f 827 static mrb_value
mzta 0:158c61bb030f 828 mrb_mod_include(mrb_state *mrb, mrb_value klass)
mzta 0:158c61bb030f 829 {
mzta 0:158c61bb030f 830 mrb_value *argv;
mzta 0:158c61bb030f 831 mrb_int argc, i;
mzta 0:158c61bb030f 832
mzta 0:158c61bb030f 833 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 834 for (i=0; i<argc; i++) {
mzta 0:158c61bb030f 835 mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
mzta 0:158c61bb030f 836 }
mzta 0:158c61bb030f 837 while (argc--) {
mzta 0:158c61bb030f 838 mrb_funcall(mrb, argv[argc], "append_features", 1, klass);
mzta 0:158c61bb030f 839 mrb_funcall(mrb, argv[argc], "included", 1, klass);
mzta 0:158c61bb030f 840 }
mzta 0:158c61bb030f 841
mzta 0:158c61bb030f 842 return klass;
mzta 0:158c61bb030f 843 }
mzta 0:158c61bb030f 844
mzta 0:158c61bb030f 845 /* 15.2.2.4.28 */
mzta 0:158c61bb030f 846 /*
mzta 0:158c61bb030f 847 * call-seq:
mzta 0:158c61bb030f 848 * mod.include?(module) -> true or false
mzta 0:158c61bb030f 849 *
mzta 0:158c61bb030f 850 * Returns <code>true</code> if <i>module</i> is included in
mzta 0:158c61bb030f 851 * <i>mod</i> or one of <i>mod</i>'s ancestors.
mzta 0:158c61bb030f 852 *
mzta 0:158c61bb030f 853 * module A
mzta 0:158c61bb030f 854 * end
mzta 0:158c61bb030f 855 * class B
mzta 0:158c61bb030f 856 * include A
mzta 0:158c61bb030f 857 * end
mzta 0:158c61bb030f 858 * class C < B
mzta 0:158c61bb030f 859 * end
mzta 0:158c61bb030f 860 * B.include?(A) #=> true
mzta 0:158c61bb030f 861 * C.include?(A) #=> true
mzta 0:158c61bb030f 862 * A.include?(A) #=> false
mzta 0:158c61bb030f 863 */
mzta 0:158c61bb030f 864 static mrb_value
mzta 0:158c61bb030f 865 mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 866 {
mzta 0:158c61bb030f 867 mrb_value mod2;
mzta 0:158c61bb030f 868 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 869
mzta 0:158c61bb030f 870 mrb_get_args(mrb, "C", &mod2);
mzta 0:158c61bb030f 871 mrb_check_type(mrb, mod2, MRB_TT_MODULE);
mzta 0:158c61bb030f 872
mzta 0:158c61bb030f 873 while (c) {
mzta 0:158c61bb030f 874 if (c->tt == MRB_TT_ICLASS) {
mzta 0:158c61bb030f 875 if (c->c == mrb_class_ptr(mod2)) return mrb_true_value();
mzta 0:158c61bb030f 876 }
mzta 0:158c61bb030f 877 c = c->super;
mzta 0:158c61bb030f 878 }
mzta 0:158c61bb030f 879 return mrb_false_value();
mzta 0:158c61bb030f 880 }
mzta 0:158c61bb030f 881
mzta 0:158c61bb030f 882 static mrb_value
mzta 0:158c61bb030f 883 mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 884 {
mzta 0:158c61bb030f 885 mrb_value result;
mzta 0:158c61bb030f 886 struct RClass *c = mrb_class_ptr(self);
mzta 0:158c61bb030f 887
mzta 0:158c61bb030f 888 result = mrb_ary_new(mrb);
mzta 0:158c61bb030f 889 mrb_ary_push(mrb, result, mrb_obj_value(c));
mzta 0:158c61bb030f 890 c = c->super;
mzta 0:158c61bb030f 891 while (c) {
mzta 0:158c61bb030f 892 if (c->tt == MRB_TT_ICLASS) {
mzta 0:158c61bb030f 893 mrb_ary_push(mrb, result, mrb_obj_value(c->c));
mzta 0:158c61bb030f 894 }
mzta 0:158c61bb030f 895 else if (c->tt != MRB_TT_SCLASS) {
mzta 0:158c61bb030f 896 mrb_ary_push(mrb, result, mrb_obj_value(c));
mzta 0:158c61bb030f 897 }
mzta 0:158c61bb030f 898 c = c->super;
mzta 0:158c61bb030f 899 }
mzta 0:158c61bb030f 900
mzta 0:158c61bb030f 901 return result;
mzta 0:158c61bb030f 902 }
mzta 0:158c61bb030f 903
mzta 0:158c61bb030f 904 static mrb_value
mzta 0:158c61bb030f 905 mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 906 {
mzta 0:158c61bb030f 907 mrb_value obj;
mzta 0:158c61bb030f 908
mzta 0:158c61bb030f 909 mrb_check_type(mrb, mod, MRB_TT_MODULE);
mzta 0:158c61bb030f 910 mrb_get_args(mrb, "o", &obj);
mzta 0:158c61bb030f 911 mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
mzta 0:158c61bb030f 912 return mod;
mzta 0:158c61bb030f 913 }
mzta 0:158c61bb030f 914
mzta 0:158c61bb030f 915 static mrb_value
mzta 0:158c61bb030f 916 mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 917 {
mzta 0:158c61bb030f 918 mrb_value result;
mzta 0:158c61bb030f 919 struct RClass *c = mrb_class_ptr(self);
mzta 0:158c61bb030f 920
mzta 0:158c61bb030f 921 result = mrb_ary_new(mrb);
mzta 0:158c61bb030f 922 while (c) {
mzta 0:158c61bb030f 923 if (c->tt == MRB_TT_ICLASS) {
mzta 0:158c61bb030f 924 mrb_ary_push(mrb, result, mrb_obj_value(c->c));
mzta 0:158c61bb030f 925 }
mzta 0:158c61bb030f 926 c = c->super;
mzta 0:158c61bb030f 927 }
mzta 0:158c61bb030f 928
mzta 0:158c61bb030f 929 return result;
mzta 0:158c61bb030f 930 }
mzta 0:158c61bb030f 931
mzta 0:158c61bb030f 932 static mrb_value
mzta 0:158c61bb030f 933 mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 934 {
mzta 0:158c61bb030f 935 mrb_value b;
mzta 0:158c61bb030f 936
mzta 0:158c61bb030f 937 mrb_get_args(mrb, "&", &b);
mzta 0:158c61bb030f 938 if (!mrb_nil_p(b)) {
mzta 0:158c61bb030f 939 mrb_yield_with_class(mrb, b, 1, &mod, mod, mrb_class_ptr(mod));
mzta 0:158c61bb030f 940 }
mzta 0:158c61bb030f 941 return mod;
mzta 0:158c61bb030f 942 }
mzta 0:158c61bb030f 943
mzta 0:158c61bb030f 944 mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
mzta 0:158c61bb030f 945
mzta 0:158c61bb030f 946 /* 15.2.2.4.33 */
mzta 0:158c61bb030f 947 /*
mzta 0:158c61bb030f 948 * call-seq:
mzta 0:158c61bb030f 949 * mod.instance_methods(include_super=true) -> array
mzta 0:158c61bb030f 950 *
mzta 0:158c61bb030f 951 * Returns an array containing the names of the public and protected instance
mzta 0:158c61bb030f 952 * methods in the receiver. For a module, these are the public and protected methods;
mzta 0:158c61bb030f 953 * for a class, they are the instance (not singleton) methods. With no
mzta 0:158c61bb030f 954 * argument, or with an argument that is <code>false</code>, the
mzta 0:158c61bb030f 955 * instance methods in <i>mod</i> are returned, otherwise the methods
mzta 0:158c61bb030f 956 * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
mzta 0:158c61bb030f 957 *
mzta 0:158c61bb030f 958 * module A
mzta 0:158c61bb030f 959 * def method1() end
mzta 0:158c61bb030f 960 * end
mzta 0:158c61bb030f 961 * class B
mzta 0:158c61bb030f 962 * def method2() end
mzta 0:158c61bb030f 963 * end
mzta 0:158c61bb030f 964 * class C < B
mzta 0:158c61bb030f 965 * def method3() end
mzta 0:158c61bb030f 966 * end
mzta 0:158c61bb030f 967 *
mzta 0:158c61bb030f 968 * A.instance_methods #=> [:method1]
mzta 0:158c61bb030f 969 * B.instance_methods(false) #=> [:method2]
mzta 0:158c61bb030f 970 * C.instance_methods(false) #=> [:method3]
mzta 0:158c61bb030f 971 * C.instance_methods(true).length #=> 43
mzta 0:158c61bb030f 972 */
mzta 0:158c61bb030f 973
mzta 0:158c61bb030f 974 static mrb_value
mzta 0:158c61bb030f 975 mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 976 {
mzta 0:158c61bb030f 977 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 978 mrb_bool recur = TRUE;
mzta 0:158c61bb030f 979 mrb_get_args(mrb, "|b", &recur);
mzta 0:158c61bb030f 980 return mrb_class_instance_method_list(mrb, recur, c, 0);
mzta 0:158c61bb030f 981 }
mzta 0:158c61bb030f 982
mzta 0:158c61bb030f 983 /* implementation of module_eval/class_eval */
mzta 0:158c61bb030f 984 mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
mzta 0:158c61bb030f 985
mzta 0:158c61bb030f 986 static mrb_value
mzta 0:158c61bb030f 987 mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 988 {
mzta 0:158c61bb030f 989 return mod;
mzta 0:158c61bb030f 990 }
mzta 0:158c61bb030f 991
mzta 0:158c61bb030f 992 MRB_API mrb_value
mzta 0:158c61bb030f 993 mrb_singleton_class(mrb_state *mrb, mrb_value v)
mzta 0:158c61bb030f 994 {
mzta 0:158c61bb030f 995 struct RBasic *obj;
mzta 0:158c61bb030f 996
mzta 0:158c61bb030f 997 switch (mrb_type(v)) {
mzta 0:158c61bb030f 998 case MRB_TT_FALSE:
mzta 0:158c61bb030f 999 if (mrb_nil_p(v))
mzta 0:158c61bb030f 1000 return mrb_obj_value(mrb->nil_class);
mzta 0:158c61bb030f 1001 return mrb_obj_value(mrb->false_class);
mzta 0:158c61bb030f 1002 case MRB_TT_TRUE:
mzta 0:158c61bb030f 1003 return mrb_obj_value(mrb->true_class);
mzta 0:158c61bb030f 1004 case MRB_TT_CPTR:
mzta 0:158c61bb030f 1005 return mrb_obj_value(mrb->object_class);
mzta 0:158c61bb030f 1006 case MRB_TT_SYMBOL:
mzta 0:158c61bb030f 1007 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 1008 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 1009 mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
mzta 0:158c61bb030f 1010 return mrb_nil_value(); /* not reached */
mzta 0:158c61bb030f 1011 default:
mzta 0:158c61bb030f 1012 break;
mzta 0:158c61bb030f 1013 }
mzta 0:158c61bb030f 1014 obj = mrb_basic_ptr(v);
mzta 0:158c61bb030f 1015 prepare_singleton_class(mrb, obj);
mzta 0:158c61bb030f 1016 if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) {
mzta 0:158c61bb030f 1017 mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"),
mzta 0:158c61bb030f 1018 mrb_obj_value(mrb->c->ci->target_class));
mzta 0:158c61bb030f 1019 }
mzta 0:158c61bb030f 1020 return mrb_obj_value(obj->c);
mzta 0:158c61bb030f 1021 }
mzta 0:158c61bb030f 1022
mzta 0:158c61bb030f 1023 MRB_API void
mzta 0:158c61bb030f 1024 mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
mzta 0:158c61bb030f 1025 {
mzta 0:158c61bb030f 1026 prepare_singleton_class(mrb, (struct RBasic*)o);
mzta 0:158c61bb030f 1027 mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec);
mzta 0:158c61bb030f 1028 }
mzta 0:158c61bb030f 1029
mzta 0:158c61bb030f 1030 MRB_API void
mzta 0:158c61bb030f 1031 mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
mzta 0:158c61bb030f 1032 {
mzta 0:158c61bb030f 1033 mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
mzta 0:158c61bb030f 1034 }
mzta 0:158c61bb030f 1035
mzta 0:158c61bb030f 1036 MRB_API void
mzta 0:158c61bb030f 1037 mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
mzta 0:158c61bb030f 1038 {
mzta 0:158c61bb030f 1039 mrb_define_class_method(mrb, c, name, func, aspec);
mzta 0:158c61bb030f 1040 mrb_define_method(mrb, c, name, func, aspec);
mzta 0:158c61bb030f 1041 }
mzta 0:158c61bb030f 1042
mzta 0:158c61bb030f 1043 MRB_API struct RProc*
mzta 0:158c61bb030f 1044 mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
mzta 0:158c61bb030f 1045 {
mzta 0:158c61bb030f 1046 khiter_t k;
mzta 0:158c61bb030f 1047 struct RProc *m;
mzta 0:158c61bb030f 1048 struct RClass *c = *cp;
mzta 0:158c61bb030f 1049
mzta 0:158c61bb030f 1050 while (c) {
mzta 0:158c61bb030f 1051 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 1052
mzta 0:158c61bb030f 1053 if (h) {
mzta 0:158c61bb030f 1054 k = kh_get(mt, mrb, h, mid);
mzta 0:158c61bb030f 1055 if (k != kh_end(h)) {
mzta 0:158c61bb030f 1056 m = kh_value(h, k);
mzta 0:158c61bb030f 1057 if (!m) break;
mzta 0:158c61bb030f 1058 *cp = c;
mzta 0:158c61bb030f 1059 return m;
mzta 0:158c61bb030f 1060 }
mzta 0:158c61bb030f 1061 }
mzta 0:158c61bb030f 1062 c = c->super;
mzta 0:158c61bb030f 1063 }
mzta 0:158c61bb030f 1064 return NULL; /* no method */
mzta 0:158c61bb030f 1065 }
mzta 0:158c61bb030f 1066
mzta 0:158c61bb030f 1067 MRB_API struct RProc*
mzta 0:158c61bb030f 1068 mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
mzta 0:158c61bb030f 1069 {
mzta 0:158c61bb030f 1070 struct RProc *m;
mzta 0:158c61bb030f 1071
mzta 0:158c61bb030f 1072 m = mrb_method_search_vm(mrb, &c, mid);
mzta 0:158c61bb030f 1073 if (!m) {
mzta 0:158c61bb030f 1074 mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
mzta 0:158c61bb030f 1075 if (RSTRING_LEN(inspect) > 64) {
mzta 0:158c61bb030f 1076 inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
mzta 0:158c61bb030f 1077 }
mzta 0:158c61bb030f 1078 mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
mzta 0:158c61bb030f 1079 mrb_sym2str(mrb, mid), inspect);
mzta 0:158c61bb030f 1080 }
mzta 0:158c61bb030f 1081 return m;
mzta 0:158c61bb030f 1082 }
mzta 0:158c61bb030f 1083
mzta 0:158c61bb030f 1084 static mrb_value
mzta 0:158c61bb030f 1085 attr_reader(mrb_state *mrb, mrb_value obj)
mzta 0:158c61bb030f 1086 {
mzta 0:158c61bb030f 1087 mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
mzta 0:158c61bb030f 1088 return mrb_iv_get(mrb, obj, to_sym(mrb, name));
mzta 0:158c61bb030f 1089 }
mzta 0:158c61bb030f 1090
mzta 0:158c61bb030f 1091 static mrb_value
mzta 0:158c61bb030f 1092 mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1093 {
mzta 0:158c61bb030f 1094 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 1095 mrb_value *argv;
mzta 0:158c61bb030f 1096 mrb_int argc, i;
mzta 0:158c61bb030f 1097 int ai;
mzta 0:158c61bb030f 1098
mzta 0:158c61bb030f 1099 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 1100 ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 1101 for (i=0; i<argc; i++) {
mzta 0:158c61bb030f 1102 mrb_value name, str;
mzta 0:158c61bb030f 1103 mrb_sym method, sym;
mzta 0:158c61bb030f 1104
mzta 0:158c61bb030f 1105 method = to_sym(mrb, argv[i]);
mzta 0:158c61bb030f 1106 name = mrb_sym2str(mrb, method);
mzta 0:158c61bb030f 1107 str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
mzta 0:158c61bb030f 1108 mrb_str_cat_lit(mrb, str, "@");
mzta 0:158c61bb030f 1109 mrb_str_cat_str(mrb, str, name);
mzta 0:158c61bb030f 1110 sym = mrb_intern_str(mrb, str);
mzta 0:158c61bb030f 1111 mrb_iv_check(mrb, sym);
mzta 0:158c61bb030f 1112 name = mrb_symbol_value(sym);
mzta 0:158c61bb030f 1113 mrb_define_method_raw(mrb, c, method,
mzta 0:158c61bb030f 1114 mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
mzta 0:158c61bb030f 1115 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 1116 }
mzta 0:158c61bb030f 1117 return mrb_nil_value();
mzta 0:158c61bb030f 1118 }
mzta 0:158c61bb030f 1119
mzta 0:158c61bb030f 1120 static mrb_value
mzta 0:158c61bb030f 1121 attr_writer(mrb_state *mrb, mrb_value obj)
mzta 0:158c61bb030f 1122 {
mzta 0:158c61bb030f 1123 mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
mzta 0:158c61bb030f 1124 mrb_value val;
mzta 0:158c61bb030f 1125
mzta 0:158c61bb030f 1126 mrb_get_args(mrb, "o", &val);
mzta 0:158c61bb030f 1127 mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
mzta 0:158c61bb030f 1128 return val;
mzta 0:158c61bb030f 1129 }
mzta 0:158c61bb030f 1130
mzta 0:158c61bb030f 1131 static mrb_value
mzta 0:158c61bb030f 1132 mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1133 {
mzta 0:158c61bb030f 1134 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 1135 mrb_value *argv;
mzta 0:158c61bb030f 1136 mrb_int argc, i;
mzta 0:158c61bb030f 1137 int ai;
mzta 0:158c61bb030f 1138
mzta 0:158c61bb030f 1139 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 1140 ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 1141 for (i=0; i<argc; i++) {
mzta 0:158c61bb030f 1142 mrb_value name, str, attr;
mzta 0:158c61bb030f 1143 mrb_sym method, sym;
mzta 0:158c61bb030f 1144
mzta 0:158c61bb030f 1145 method = to_sym(mrb, argv[i]);
mzta 0:158c61bb030f 1146
mzta 0:158c61bb030f 1147 /* prepare iv name (@name) */
mzta 0:158c61bb030f 1148 name = mrb_sym2str(mrb, method);
mzta 0:158c61bb030f 1149 str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
mzta 0:158c61bb030f 1150 mrb_str_cat_lit(mrb, str, "@");
mzta 0:158c61bb030f 1151 mrb_str_cat_str(mrb, str, name);
mzta 0:158c61bb030f 1152 sym = mrb_intern_str(mrb, str);
mzta 0:158c61bb030f 1153 mrb_iv_check(mrb, sym);
mzta 0:158c61bb030f 1154 attr = mrb_symbol_value(sym);
mzta 0:158c61bb030f 1155
mzta 0:158c61bb030f 1156 /* prepare method name (name=) */
mzta 0:158c61bb030f 1157 str = mrb_str_buf_new(mrb, RSTRING_LEN(str));
mzta 0:158c61bb030f 1158 mrb_str_cat_str(mrb, str, name);
mzta 0:158c61bb030f 1159 mrb_str_cat_lit(mrb, str, "=");
mzta 0:158c61bb030f 1160 method = mrb_intern_str(mrb, str);
mzta 0:158c61bb030f 1161
mzta 0:158c61bb030f 1162 mrb_define_method_raw(mrb, c, method,
mzta 0:158c61bb030f 1163 mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
mzta 0:158c61bb030f 1164 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 1165 }
mzta 0:158c61bb030f 1166 return mrb_nil_value();
mzta 0:158c61bb030f 1167 }
mzta 0:158c61bb030f 1168
mzta 0:158c61bb030f 1169 static mrb_value
mzta 0:158c61bb030f 1170 mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
mzta 0:158c61bb030f 1171 {
mzta 0:158c61bb030f 1172 struct RClass *c = mrb_class_ptr(cv);
mzta 0:158c61bb030f 1173 struct RObject *o;
mzta 0:158c61bb030f 1174 enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
mzta 0:158c61bb030f 1175
mzta 0:158c61bb030f 1176 if (c->tt == MRB_TT_SCLASS)
mzta 0:158c61bb030f 1177 mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");
mzta 0:158c61bb030f 1178
mzta 0:158c61bb030f 1179 if (ttype == 0) ttype = MRB_TT_OBJECT;
mzta 0:158c61bb030f 1180 o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
mzta 0:158c61bb030f 1181 return mrb_obj_value(o);
mzta 0:158c61bb030f 1182 }
mzta 0:158c61bb030f 1183
mzta 0:158c61bb030f 1184 /*
mzta 0:158c61bb030f 1185 * call-seq:
mzta 0:158c61bb030f 1186 * class.new(args, ...) -> obj
mzta 0:158c61bb030f 1187 *
mzta 0:158c61bb030f 1188 * Calls <code>allocate</code> to create a new object of
mzta 0:158c61bb030f 1189 * <i>class</i>'s class, then invokes that object's
mzta 0:158c61bb030f 1190 * <code>initialize</code> method, passing it <i>args</i>.
mzta 0:158c61bb030f 1191 * This is the method that ends up getting called whenever
mzta 0:158c61bb030f 1192 * an object is constructed using .new.
mzta 0:158c61bb030f 1193 *
mzta 0:158c61bb030f 1194 */
mzta 0:158c61bb030f 1195
mzta 0:158c61bb030f 1196 MRB_API mrb_value
mzta 0:158c61bb030f 1197 mrb_instance_new(mrb_state *mrb, mrb_value cv)
mzta 0:158c61bb030f 1198 {
mzta 0:158c61bb030f 1199 mrb_value obj, blk;
mzta 0:158c61bb030f 1200 mrb_value *argv;
mzta 0:158c61bb030f 1201 mrb_int argc;
mzta 0:158c61bb030f 1202
mzta 0:158c61bb030f 1203 mrb_get_args(mrb, "*&", &argv, &argc, &blk);
mzta 0:158c61bb030f 1204 obj = mrb_instance_alloc(mrb, cv);
mzta 0:158c61bb030f 1205 mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk);
mzta 0:158c61bb030f 1206
mzta 0:158c61bb030f 1207 return obj;
mzta 0:158c61bb030f 1208 }
mzta 0:158c61bb030f 1209
mzta 0:158c61bb030f 1210 MRB_API mrb_value
mzta 0:158c61bb030f 1211 mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv)
mzta 0:158c61bb030f 1212 {
mzta 0:158c61bb030f 1213 mrb_value obj;
mzta 0:158c61bb030f 1214
mzta 0:158c61bb030f 1215 obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
mzta 0:158c61bb030f 1216 mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv);
mzta 0:158c61bb030f 1217
mzta 0:158c61bb030f 1218 return obj;
mzta 0:158c61bb030f 1219 }
mzta 0:158c61bb030f 1220
mzta 0:158c61bb030f 1221 static mrb_value
mzta 0:158c61bb030f 1222 mrb_class_initialize(mrb_state *mrb, mrb_value c)
mzta 0:158c61bb030f 1223 {
mzta 0:158c61bb030f 1224 mrb_value a, b;
mzta 0:158c61bb030f 1225
mzta 0:158c61bb030f 1226 mrb_get_args(mrb, "|C&", &a, &b);
mzta 0:158c61bb030f 1227 if (!mrb_nil_p(b)) {
mzta 0:158c61bb030f 1228 mrb_yield_with_class(mrb, b, 1, &c, c, mrb_class_ptr(c));
mzta 0:158c61bb030f 1229 }
mzta 0:158c61bb030f 1230 return c;
mzta 0:158c61bb030f 1231 }
mzta 0:158c61bb030f 1232
mzta 0:158c61bb030f 1233 static mrb_value
mzta 0:158c61bb030f 1234 mrb_class_new_class(mrb_state *mrb, mrb_value cv)
mzta 0:158c61bb030f 1235 {
mzta 0:158c61bb030f 1236 mrb_int n;
mzta 0:158c61bb030f 1237 mrb_value super, blk;
mzta 0:158c61bb030f 1238 mrb_value new_class;
mzta 0:158c61bb030f 1239
mzta 0:158c61bb030f 1240 n = mrb_get_args(mrb, "|C&", &super, &blk);
mzta 0:158c61bb030f 1241 if (n == 0) {
mzta 0:158c61bb030f 1242 super = mrb_obj_value(mrb->object_class);
mzta 0:158c61bb030f 1243 }
mzta 0:158c61bb030f 1244 new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
mzta 0:158c61bb030f 1245 mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "initialize"), n, &super, blk);
mzta 0:158c61bb030f 1246 mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
mzta 0:158c61bb030f 1247 return new_class;
mzta 0:158c61bb030f 1248 }
mzta 0:158c61bb030f 1249
mzta 0:158c61bb030f 1250 static mrb_value
mzta 0:158c61bb030f 1251 mrb_class_superclass(mrb_state *mrb, mrb_value klass)
mzta 0:158c61bb030f 1252 {
mzta 0:158c61bb030f 1253 struct RClass *c;
mzta 0:158c61bb030f 1254
mzta 0:158c61bb030f 1255 c = mrb_class_ptr(klass);
mzta 0:158c61bb030f 1256 c = c->super;
mzta 0:158c61bb030f 1257 while (c && c->tt == MRB_TT_ICLASS) {
mzta 0:158c61bb030f 1258 c = c->super;
mzta 0:158c61bb030f 1259 }
mzta 0:158c61bb030f 1260 if (!c) return mrb_nil_value();
mzta 0:158c61bb030f 1261 return mrb_obj_value(c);
mzta 0:158c61bb030f 1262 }
mzta 0:158c61bb030f 1263
mzta 0:158c61bb030f 1264 static mrb_value
mzta 0:158c61bb030f 1265 mrb_bob_init(mrb_state *mrb, mrb_value cv)
mzta 0:158c61bb030f 1266 {
mzta 0:158c61bb030f 1267 return mrb_nil_value();
mzta 0:158c61bb030f 1268 }
mzta 0:158c61bb030f 1269
mzta 0:158c61bb030f 1270 static mrb_value
mzta 0:158c61bb030f 1271 mrb_bob_not(mrb_state *mrb, mrb_value cv)
mzta 0:158c61bb030f 1272 {
mzta 0:158c61bb030f 1273 return mrb_bool_value(!mrb_test(cv));
mzta 0:158c61bb030f 1274 }
mzta 0:158c61bb030f 1275
mzta 0:158c61bb030f 1276 /* 15.3.1.3.30 */
mzta 0:158c61bb030f 1277 /*
mzta 0:158c61bb030f 1278 * call-seq:
mzta 0:158c61bb030f 1279 * obj.method_missing(symbol [, *args] ) -> result
mzta 0:158c61bb030f 1280 *
mzta 0:158c61bb030f 1281 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
mzta 0:158c61bb030f 1282 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
mzta 0:158c61bb030f 1283 * are any arguments that were passed to it. By default, the interpreter
mzta 0:158c61bb030f 1284 * raises an error when this method is called. However, it is possible
mzta 0:158c61bb030f 1285 * to override the method to provide more dynamic behavior.
mzta 0:158c61bb030f 1286 * If it is decided that a particular method should not be handled, then
mzta 0:158c61bb030f 1287 * <i>super</i> should be called, so that ancestors can pick up the
mzta 0:158c61bb030f 1288 * missing method.
mzta 0:158c61bb030f 1289 * The example below creates
mzta 0:158c61bb030f 1290 * a class <code>Roman</code>, which responds to methods with names
mzta 0:158c61bb030f 1291 * consisting of roman numerals, returning the corresponding integer
mzta 0:158c61bb030f 1292 * values.
mzta 0:158c61bb030f 1293 *
mzta 0:158c61bb030f 1294 * class Roman
mzta 0:158c61bb030f 1295 * def romanToInt(str)
mzta 0:158c61bb030f 1296 * # ...
mzta 0:158c61bb030f 1297 * end
mzta 0:158c61bb030f 1298 * def method_missing(methId)
mzta 0:158c61bb030f 1299 * str = methId.id2name
mzta 0:158c61bb030f 1300 * romanToInt(str)
mzta 0:158c61bb030f 1301 * end
mzta 0:158c61bb030f 1302 * end
mzta 0:158c61bb030f 1303 *
mzta 0:158c61bb030f 1304 * r = Roman.new
mzta 0:158c61bb030f 1305 * r.iv #=> 4
mzta 0:158c61bb030f 1306 * r.xxiii #=> 23
mzta 0:158c61bb030f 1307 * r.mm #=> 2000
mzta 0:158c61bb030f 1308 */
mzta 0:158c61bb030f 1309 static mrb_value
mzta 0:158c61bb030f 1310 mrb_bob_missing(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1311 {
mzta 0:158c61bb030f 1312 mrb_sym name;
mzta 0:158c61bb030f 1313 mrb_value *a;
mzta 0:158c61bb030f 1314 mrb_int alen;
mzta 0:158c61bb030f 1315 mrb_sym inspect;
mzta 0:158c61bb030f 1316 mrb_value repr;
mzta 0:158c61bb030f 1317
mzta 0:158c61bb030f 1318 mrb_get_args(mrb, "n*", &name, &a, &alen);
mzta 0:158c61bb030f 1319
mzta 0:158c61bb030f 1320 inspect = mrb_intern_lit(mrb, "inspect");
mzta 0:158c61bb030f 1321 if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
mzta 0:158c61bb030f 1322 /* method missing in inspect; avoid recursion */
mzta 0:158c61bb030f 1323 repr = mrb_any_to_s(mrb, mod);
mzta 0:158c61bb030f 1324 }
mzta 0:158c61bb030f 1325 else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
mzta 0:158c61bb030f 1326 repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
mzta 0:158c61bb030f 1327 if (RSTRING_LEN(repr) > 64) {
mzta 0:158c61bb030f 1328 repr = mrb_any_to_s(mrb, mod);
mzta 0:158c61bb030f 1329 }
mzta 0:158c61bb030f 1330 }
mzta 0:158c61bb030f 1331 else {
mzta 0:158c61bb030f 1332 repr = mrb_any_to_s(mrb, mod);
mzta 0:158c61bb030f 1333 }
mzta 0:158c61bb030f 1334
mzta 0:158c61bb030f 1335 mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
mzta 0:158c61bb030f 1336 /* not reached */
mzta 0:158c61bb030f 1337 return mrb_nil_value();
mzta 0:158c61bb030f 1338 }
mzta 0:158c61bb030f 1339
mzta 0:158c61bb030f 1340 MRB_API mrb_bool
mzta 0:158c61bb030f 1341 mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
mzta 0:158c61bb030f 1342 {
mzta 0:158c61bb030f 1343 khiter_t k;
mzta 0:158c61bb030f 1344
mzta 0:158c61bb030f 1345 while (c) {
mzta 0:158c61bb030f 1346 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 1347
mzta 0:158c61bb030f 1348 if (h) {
mzta 0:158c61bb030f 1349 k = kh_get(mt, mrb, h, mid);
mzta 0:158c61bb030f 1350 if (k != kh_end(h)) {
mzta 0:158c61bb030f 1351 if (kh_value(h, k)) {
mzta 0:158c61bb030f 1352 return TRUE; /* method exists */
mzta 0:158c61bb030f 1353 }
mzta 0:158c61bb030f 1354 else {
mzta 0:158c61bb030f 1355 return FALSE; /* undefined method */
mzta 0:158c61bb030f 1356 }
mzta 0:158c61bb030f 1357 }
mzta 0:158c61bb030f 1358 }
mzta 0:158c61bb030f 1359 c = c->super;
mzta 0:158c61bb030f 1360 }
mzta 0:158c61bb030f 1361 return FALSE; /* no method */
mzta 0:158c61bb030f 1362 }
mzta 0:158c61bb030f 1363
mzta 0:158c61bb030f 1364 MRB_API mrb_bool
mzta 0:158c61bb030f 1365 mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
mzta 0:158c61bb030f 1366 {
mzta 0:158c61bb030f 1367 return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid);
mzta 0:158c61bb030f 1368 }
mzta 0:158c61bb030f 1369
mzta 0:158c61bb030f 1370 MRB_API mrb_value
mzta 0:158c61bb030f 1371 mrb_class_path(mrb_state *mrb, struct RClass *c)
mzta 0:158c61bb030f 1372 {
mzta 0:158c61bb030f 1373 mrb_value path;
mzta 0:158c61bb030f 1374 const char *name;
mzta 0:158c61bb030f 1375 mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__");
mzta 0:158c61bb030f 1376
mzta 0:158c61bb030f 1377 path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
mzta 0:158c61bb030f 1378 if (mrb_nil_p(path)) {
mzta 0:158c61bb030f 1379 struct RClass *outer = mrb_class_outer_module(mrb, c);
mzta 0:158c61bb030f 1380 mrb_sym sym = mrb_class_sym(mrb, c, outer);
mzta 0:158c61bb030f 1381 mrb_int len;
mzta 0:158c61bb030f 1382
mzta 0:158c61bb030f 1383 if (sym == 0) {
mzta 0:158c61bb030f 1384 return mrb_nil_value();
mzta 0:158c61bb030f 1385 }
mzta 0:158c61bb030f 1386 else if (outer && outer != mrb->object_class) {
mzta 0:158c61bb030f 1387 mrb_value base = mrb_class_path(mrb, outer);
mzta 0:158c61bb030f 1388 path = mrb_str_buf_new(mrb, 0);
mzta 0:158c61bb030f 1389 if (mrb_nil_p(base)) {
mzta 0:158c61bb030f 1390 mrb_str_cat_lit(mrb, path, "#<Class:");
mzta 0:158c61bb030f 1391 mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, outer));
mzta 0:158c61bb030f 1392 mrb_str_cat_lit(mrb, path, ">");
mzta 0:158c61bb030f 1393 }
mzta 0:158c61bb030f 1394 else {
mzta 0:158c61bb030f 1395 mrb_str_concat(mrb, path, base);
mzta 0:158c61bb030f 1396 }
mzta 0:158c61bb030f 1397 mrb_str_cat_lit(mrb, path, "::");
mzta 0:158c61bb030f 1398 name = mrb_sym2name_len(mrb, sym, &len);
mzta 0:158c61bb030f 1399 mrb_str_cat(mrb, path, name, len);
mzta 0:158c61bb030f 1400 }
mzta 0:158c61bb030f 1401 else {
mzta 0:158c61bb030f 1402 name = mrb_sym2name_len(mrb, sym, &len);
mzta 0:158c61bb030f 1403 path = mrb_str_new(mrb, name, len);
mzta 0:158c61bb030f 1404 }
mzta 0:158c61bb030f 1405 mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
mzta 0:158c61bb030f 1406 }
mzta 0:158c61bb030f 1407 return path;
mzta 0:158c61bb030f 1408 }
mzta 0:158c61bb030f 1409
mzta 0:158c61bb030f 1410 MRB_API struct RClass *
mzta 0:158c61bb030f 1411 mrb_class_real(struct RClass* cl)
mzta 0:158c61bb030f 1412 {
mzta 0:158c61bb030f 1413 if (cl == 0)
mzta 0:158c61bb030f 1414 return NULL;
mzta 0:158c61bb030f 1415 while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
mzta 0:158c61bb030f 1416 cl = cl->super;
mzta 0:158c61bb030f 1417 }
mzta 0:158c61bb030f 1418 return cl;
mzta 0:158c61bb030f 1419 }
mzta 0:158c61bb030f 1420
mzta 0:158c61bb030f 1421 MRB_API const char*
mzta 0:158c61bb030f 1422 mrb_class_name(mrb_state *mrb, struct RClass* c)
mzta 0:158c61bb030f 1423 {
mzta 0:158c61bb030f 1424 mrb_value path = mrb_class_path(mrb, c);
mzta 0:158c61bb030f 1425 if (mrb_nil_p(path)) {
mzta 0:158c61bb030f 1426 path = mrb_str_new_lit(mrb, "#<Class:");
mzta 0:158c61bb030f 1427 mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
mzta 0:158c61bb030f 1428 mrb_str_cat_lit(mrb, path, ">");
mzta 0:158c61bb030f 1429 }
mzta 0:158c61bb030f 1430 return RSTRING_PTR(path);
mzta 0:158c61bb030f 1431 }
mzta 0:158c61bb030f 1432
mzta 0:158c61bb030f 1433 MRB_API const char*
mzta 0:158c61bb030f 1434 mrb_obj_classname(mrb_state *mrb, mrb_value obj)
mzta 0:158c61bb030f 1435 {
mzta 0:158c61bb030f 1436 return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
mzta 0:158c61bb030f 1437 }
mzta 0:158c61bb030f 1438
mzta 0:158c61bb030f 1439 /*!
mzta 0:158c61bb030f 1440 * Ensures a class can be derived from super.
mzta 0:158c61bb030f 1441 *
mzta 0:158c61bb030f 1442 * \param super a reference to an object.
mzta 0:158c61bb030f 1443 * \exception TypeError if \a super is not a Class or \a super is a singleton class.
mzta 0:158c61bb030f 1444 */
mzta 0:158c61bb030f 1445 static void
mzta 0:158c61bb030f 1446 mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
mzta 0:158c61bb030f 1447 {
mzta 0:158c61bb030f 1448 if (super->tt != MRB_TT_CLASS) {
mzta 0:158c61bb030f 1449 mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
mzta 0:158c61bb030f 1450 }
mzta 0:158c61bb030f 1451 if (super->tt == MRB_TT_SCLASS) {
mzta 0:158c61bb030f 1452 mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
mzta 0:158c61bb030f 1453 }
mzta 0:158c61bb030f 1454 if (super == mrb->class_class) {
mzta 0:158c61bb030f 1455 mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of Class");
mzta 0:158c61bb030f 1456 }
mzta 0:158c61bb030f 1457 }
mzta 0:158c61bb030f 1458
mzta 0:158c61bb030f 1459 /*!
mzta 0:158c61bb030f 1460 * Creates a new class.
mzta 0:158c61bb030f 1461 * \param super a class from which the new class derives.
mzta 0:158c61bb030f 1462 * \exception TypeError \a super is not inheritable.
mzta 0:158c61bb030f 1463 * \exception TypeError \a super is the Class class.
mzta 0:158c61bb030f 1464 */
mzta 0:158c61bb030f 1465 MRB_API struct RClass*
mzta 0:158c61bb030f 1466 mrb_class_new(mrb_state *mrb, struct RClass *super)
mzta 0:158c61bb030f 1467 {
mzta 0:158c61bb030f 1468 struct RClass *c;
mzta 0:158c61bb030f 1469
mzta 0:158c61bb030f 1470 if (super) {
mzta 0:158c61bb030f 1471 mrb_check_inheritable(mrb, super);
mzta 0:158c61bb030f 1472 }
mzta 0:158c61bb030f 1473 c = boot_defclass(mrb, super);
mzta 0:158c61bb030f 1474 if (super) {
mzta 0:158c61bb030f 1475 MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
mzta 0:158c61bb030f 1476 }
mzta 0:158c61bb030f 1477 make_metaclass(mrb, c);
mzta 0:158c61bb030f 1478
mzta 0:158c61bb030f 1479 return c;
mzta 0:158c61bb030f 1480 }
mzta 0:158c61bb030f 1481
mzta 0:158c61bb030f 1482 /*!
mzta 0:158c61bb030f 1483 * Creates a new module.
mzta 0:158c61bb030f 1484 */
mzta 0:158c61bb030f 1485 MRB_API struct RClass*
mzta 0:158c61bb030f 1486 mrb_module_new(mrb_state *mrb)
mzta 0:158c61bb030f 1487 {
mzta 0:158c61bb030f 1488 struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
mzta 0:158c61bb030f 1489 m->mt = kh_init(mt, mrb);
mzta 0:158c61bb030f 1490
mzta 0:158c61bb030f 1491 return m;
mzta 0:158c61bb030f 1492 }
mzta 0:158c61bb030f 1493
mzta 0:158c61bb030f 1494 /*
mzta 0:158c61bb030f 1495 * call-seq:
mzta 0:158c61bb030f 1496 * obj.class => class
mzta 0:158c61bb030f 1497 *
mzta 0:158c61bb030f 1498 * Returns the class of <i>obj</i>, now preferred over
mzta 0:158c61bb030f 1499 * <code>Object#type</code>, as an object's type in Ruby is only
mzta 0:158c61bb030f 1500 * loosely tied to that object's class. This method must always be
mzta 0:158c61bb030f 1501 * called with an explicit receiver, as <code>class</code> is also a
mzta 0:158c61bb030f 1502 * reserved word in Ruby.
mzta 0:158c61bb030f 1503 *
mzta 0:158c61bb030f 1504 * 1.class #=> Fixnum
mzta 0:158c61bb030f 1505 * self.class #=> Object
mzta 0:158c61bb030f 1506 */
mzta 0:158c61bb030f 1507
mzta 0:158c61bb030f 1508 MRB_API struct RClass*
mzta 0:158c61bb030f 1509 mrb_obj_class(mrb_state *mrb, mrb_value obj)
mzta 0:158c61bb030f 1510 {
mzta 0:158c61bb030f 1511 return mrb_class_real(mrb_class(mrb, obj));
mzta 0:158c61bb030f 1512 }
mzta 0:158c61bb030f 1513
mzta 0:158c61bb030f 1514 MRB_API void
mzta 0:158c61bb030f 1515 mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
mzta 0:158c61bb030f 1516 {
mzta 0:158c61bb030f 1517 struct RProc *m = mrb_method_search(mrb, c, b);
mzta 0:158c61bb030f 1518
mzta 0:158c61bb030f 1519 mrb_define_method_vm(mrb, c, a, mrb_obj_value(m));
mzta 0:158c61bb030f 1520 }
mzta 0:158c61bb030f 1521
mzta 0:158c61bb030f 1522 /*!
mzta 0:158c61bb030f 1523 * Defines an alias of a method.
mzta 0:158c61bb030f 1524 * \param klass the class which the original method belongs to
mzta 0:158c61bb030f 1525 * \param name1 a new name for the method
mzta 0:158c61bb030f 1526 * \param name2 the original name of the method
mzta 0:158c61bb030f 1527 */
mzta 0:158c61bb030f 1528 MRB_API void
mzta 0:158c61bb030f 1529 mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
mzta 0:158c61bb030f 1530 {
mzta 0:158c61bb030f 1531 mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2));
mzta 0:158c61bb030f 1532 }
mzta 0:158c61bb030f 1533
mzta 0:158c61bb030f 1534 /*
mzta 0:158c61bb030f 1535 * call-seq:
mzta 0:158c61bb030f 1536 * mod.to_s -> string
mzta 0:158c61bb030f 1537 *
mzta 0:158c61bb030f 1538 * Return a string representing this module or class. For basic
mzta 0:158c61bb030f 1539 * classes and modules, this is the name. For singletons, we
mzta 0:158c61bb030f 1540 * show information on the thing we're attached to as well.
mzta 0:158c61bb030f 1541 */
mzta 0:158c61bb030f 1542
mzta 0:158c61bb030f 1543 static mrb_value
mzta 0:158c61bb030f 1544 mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
mzta 0:158c61bb030f 1545 {
mzta 0:158c61bb030f 1546 mrb_value str;
mzta 0:158c61bb030f 1547
mzta 0:158c61bb030f 1548 if (mrb_type(klass) == MRB_TT_SCLASS) {
mzta 0:158c61bb030f 1549 mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
mzta 0:158c61bb030f 1550
mzta 0:158c61bb030f 1551 str = mrb_str_new_lit(mrb, "#<Class:");
mzta 0:158c61bb030f 1552
mzta 0:158c61bb030f 1553 switch (mrb_type(v)) {
mzta 0:158c61bb030f 1554 case MRB_TT_CLASS:
mzta 0:158c61bb030f 1555 case MRB_TT_MODULE:
mzta 0:158c61bb030f 1556 case MRB_TT_SCLASS:
mzta 0:158c61bb030f 1557 mrb_str_append(mrb, str, mrb_inspect(mrb, v));
mzta 0:158c61bb030f 1558 break;
mzta 0:158c61bb030f 1559 default:
mzta 0:158c61bb030f 1560 mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
mzta 0:158c61bb030f 1561 break;
mzta 0:158c61bb030f 1562 }
mzta 0:158c61bb030f 1563 return mrb_str_cat_lit(mrb, str, ">");
mzta 0:158c61bb030f 1564 }
mzta 0:158c61bb030f 1565 else {
mzta 0:158c61bb030f 1566 struct RClass *c;
mzta 0:158c61bb030f 1567 mrb_value path;
mzta 0:158c61bb030f 1568
mzta 0:158c61bb030f 1569 str = mrb_str_buf_new(mrb, 32);
mzta 0:158c61bb030f 1570 c = mrb_class_ptr(klass);
mzta 0:158c61bb030f 1571 path = mrb_class_path(mrb, c);
mzta 0:158c61bb030f 1572
mzta 0:158c61bb030f 1573 if (mrb_nil_p(path)) {
mzta 0:158c61bb030f 1574 switch (mrb_type(klass)) {
mzta 0:158c61bb030f 1575 case MRB_TT_CLASS:
mzta 0:158c61bb030f 1576 mrb_str_cat_lit(mrb, str, "#<Class:");
mzta 0:158c61bb030f 1577 break;
mzta 0:158c61bb030f 1578
mzta 0:158c61bb030f 1579 case MRB_TT_MODULE:
mzta 0:158c61bb030f 1580 mrb_str_cat_lit(mrb, str, "#<Module:");
mzta 0:158c61bb030f 1581 break;
mzta 0:158c61bb030f 1582
mzta 0:158c61bb030f 1583 default:
mzta 0:158c61bb030f 1584 /* Shouldn't be happened? */
mzta 0:158c61bb030f 1585 mrb_str_cat_lit(mrb, str, "#<??????:");
mzta 0:158c61bb030f 1586 break;
mzta 0:158c61bb030f 1587 }
mzta 0:158c61bb030f 1588 mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
mzta 0:158c61bb030f 1589 return mrb_str_cat_lit(mrb, str, ">");
mzta 0:158c61bb030f 1590 }
mzta 0:158c61bb030f 1591 else {
mzta 0:158c61bb030f 1592 return path;
mzta 0:158c61bb030f 1593 }
mzta 0:158c61bb030f 1594 }
mzta 0:158c61bb030f 1595 }
mzta 0:158c61bb030f 1596
mzta 0:158c61bb030f 1597 static mrb_value
mzta 0:158c61bb030f 1598 mrb_mod_alias(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1599 {
mzta 0:158c61bb030f 1600 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 1601 mrb_sym new_name, old_name;
mzta 0:158c61bb030f 1602
mzta 0:158c61bb030f 1603 mrb_get_args(mrb, "nn", &new_name, &old_name);
mzta 0:158c61bb030f 1604 mrb_alias_method(mrb, c, new_name, old_name);
mzta 0:158c61bb030f 1605 return mrb_nil_value();
mzta 0:158c61bb030f 1606 }
mzta 0:158c61bb030f 1607
mzta 0:158c61bb030f 1608 static void
mzta 0:158c61bb030f 1609 undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
mzta 0:158c61bb030f 1610 {
mzta 0:158c61bb030f 1611 mrb_value m;
mzta 0:158c61bb030f 1612
mzta 0:158c61bb030f 1613 if (!mrb_obj_respond_to(mrb, c, a)) {
mzta 0:158c61bb030f 1614 mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
mzta 0:158c61bb030f 1615 }
mzta 0:158c61bb030f 1616 else {
mzta 0:158c61bb030f 1617 SET_PROC_VALUE(m, 0);
mzta 0:158c61bb030f 1618 mrb_define_method_vm(mrb, c, a, m);
mzta 0:158c61bb030f 1619 }
mzta 0:158c61bb030f 1620 }
mzta 0:158c61bb030f 1621
mzta 0:158c61bb030f 1622 MRB_API void
mzta 0:158c61bb030f 1623 mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
mzta 0:158c61bb030f 1624 {
mzta 0:158c61bb030f 1625 undef_method(mrb, c, mrb_intern_cstr(mrb, name));
mzta 0:158c61bb030f 1626 }
mzta 0:158c61bb030f 1627
mzta 0:158c61bb030f 1628 MRB_API void
mzta 0:158c61bb030f 1629 mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name)
mzta 0:158c61bb030f 1630 {
mzta 0:158c61bb030f 1631 mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
mzta 0:158c61bb030f 1632 }
mzta 0:158c61bb030f 1633
mzta 0:158c61bb030f 1634 static mrb_value
mzta 0:158c61bb030f 1635 mrb_mod_undef(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1636 {
mzta 0:158c61bb030f 1637 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 1638 mrb_int argc;
mzta 0:158c61bb030f 1639 mrb_value *argv;
mzta 0:158c61bb030f 1640
mzta 0:158c61bb030f 1641 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 1642 while (argc--) {
mzta 0:158c61bb030f 1643 undef_method(mrb, c, mrb_symbol(*argv));
mzta 0:158c61bb030f 1644 argv++;
mzta 0:158c61bb030f 1645 }
mzta 0:158c61bb030f 1646 return mrb_nil_value();
mzta 0:158c61bb030f 1647 }
mzta 0:158c61bb030f 1648
mzta 0:158c61bb030f 1649 static mrb_value
mzta 0:158c61bb030f 1650 mod_define_method(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 1651 {
mzta 0:158c61bb030f 1652 struct RClass *c = mrb_class_ptr(self);
mzta 0:158c61bb030f 1653 struct RProc *p;
mzta 0:158c61bb030f 1654 mrb_sym mid;
mzta 0:158c61bb030f 1655 mrb_value blk;
mzta 0:158c61bb030f 1656
mzta 0:158c61bb030f 1657 mrb_get_args(mrb, "n&", &mid, &blk);
mzta 0:158c61bb030f 1658 if (mrb_nil_p(blk)) {
mzta 0:158c61bb030f 1659 mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
mzta 0:158c61bb030f 1660 }
mzta 0:158c61bb030f 1661 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mzta 0:158c61bb030f 1662 mrb_proc_copy(p, mrb_proc_ptr(blk));
mzta 0:158c61bb030f 1663 p->flags |= MRB_PROC_STRICT;
mzta 0:158c61bb030f 1664 mrb_define_method_raw(mrb, c, mid, p);
mzta 0:158c61bb030f 1665 return mrb_symbol_value(mid);
mzta 0:158c61bb030f 1666 }
mzta 0:158c61bb030f 1667
mzta 0:158c61bb030f 1668 static void
mzta 0:158c61bb030f 1669 check_cv_name_str(mrb_state *mrb, mrb_value str)
mzta 0:158c61bb030f 1670 {
mzta 0:158c61bb030f 1671 const char *s = RSTRING_PTR(str);
mzta 0:158c61bb030f 1672 mrb_int len = RSTRING_LEN(str);
mzta 0:158c61bb030f 1673
mzta 0:158c61bb030f 1674 if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
mzta 0:158c61bb030f 1675 mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str);
mzta 0:158c61bb030f 1676 }
mzta 0:158c61bb030f 1677 }
mzta 0:158c61bb030f 1678
mzta 0:158c61bb030f 1679 static void
mzta 0:158c61bb030f 1680 check_cv_name_sym(mrb_state *mrb, mrb_sym id)
mzta 0:158c61bb030f 1681 {
mzta 0:158c61bb030f 1682 check_cv_name_str(mrb, mrb_sym2str(mrb, id));
mzta 0:158c61bb030f 1683 }
mzta 0:158c61bb030f 1684
mzta 0:158c61bb030f 1685 /* 15.2.2.4.16 */
mzta 0:158c61bb030f 1686 /*
mzta 0:158c61bb030f 1687 * call-seq:
mzta 0:158c61bb030f 1688 * obj.class_variable_defined?(symbol) -> true or false
mzta 0:158c61bb030f 1689 *
mzta 0:158c61bb030f 1690 * Returns <code>true</code> if the given class variable is defined
mzta 0:158c61bb030f 1691 * in <i>obj</i>.
mzta 0:158c61bb030f 1692 *
mzta 0:158c61bb030f 1693 * class Fred
mzta 0:158c61bb030f 1694 * @@foo = 99
mzta 0:158c61bb030f 1695 * end
mzta 0:158c61bb030f 1696 * Fred.class_variable_defined?(:@@foo) #=> true
mzta 0:158c61bb030f 1697 * Fred.class_variable_defined?(:@@bar) #=> false
mzta 0:158c61bb030f 1698 */
mzta 0:158c61bb030f 1699
mzta 0:158c61bb030f 1700 static mrb_value
mzta 0:158c61bb030f 1701 mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1702 {
mzta 0:158c61bb030f 1703 mrb_sym id;
mzta 0:158c61bb030f 1704
mzta 0:158c61bb030f 1705 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1706 check_cv_name_sym(mrb, id);
mzta 0:158c61bb030f 1707 return mrb_bool_value(mrb_cv_defined(mrb, mod, id));
mzta 0:158c61bb030f 1708 }
mzta 0:158c61bb030f 1709
mzta 0:158c61bb030f 1710 /* 15.2.2.4.17 */
mzta 0:158c61bb030f 1711 /*
mzta 0:158c61bb030f 1712 * call-seq:
mzta 0:158c61bb030f 1713 * mod.class_variable_get(symbol) -> obj
mzta 0:158c61bb030f 1714 *
mzta 0:158c61bb030f 1715 * Returns the value of the given class variable (or throws a
mzta 0:158c61bb030f 1716 * <code>NameError</code> exception). The <code>@@</code> part of the
mzta 0:158c61bb030f 1717 * variable name should be included for regular class variables
mzta 0:158c61bb030f 1718 *
mzta 0:158c61bb030f 1719 * class Fred
mzta 0:158c61bb030f 1720 * @@foo = 99
mzta 0:158c61bb030f 1721 * end
mzta 0:158c61bb030f 1722 * Fred.class_variable_get(:@@foo) #=> 99
mzta 0:158c61bb030f 1723 */
mzta 0:158c61bb030f 1724
mzta 0:158c61bb030f 1725 static mrb_value
mzta 0:158c61bb030f 1726 mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1727 {
mzta 0:158c61bb030f 1728 mrb_sym id;
mzta 0:158c61bb030f 1729
mzta 0:158c61bb030f 1730 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1731 check_cv_name_sym(mrb, id);
mzta 0:158c61bb030f 1732 return mrb_cv_get(mrb, mod, id);
mzta 0:158c61bb030f 1733 }
mzta 0:158c61bb030f 1734
mzta 0:158c61bb030f 1735 /* 15.2.2.4.18 */
mzta 0:158c61bb030f 1736 /*
mzta 0:158c61bb030f 1737 * call-seq:
mzta 0:158c61bb030f 1738 * obj.class_variable_set(symbol, obj) -> obj
mzta 0:158c61bb030f 1739 *
mzta 0:158c61bb030f 1740 * Sets the class variable names by <i>symbol</i> to
mzta 0:158c61bb030f 1741 * <i>object</i>.
mzta 0:158c61bb030f 1742 *
mzta 0:158c61bb030f 1743 * class Fred
mzta 0:158c61bb030f 1744 * @@foo = 99
mzta 0:158c61bb030f 1745 * def foo
mzta 0:158c61bb030f 1746 * @@foo
mzta 0:158c61bb030f 1747 * end
mzta 0:158c61bb030f 1748 * end
mzta 0:158c61bb030f 1749 * Fred.class_variable_set(:@@foo, 101) #=> 101
mzta 0:158c61bb030f 1750 * Fred.new.foo #=> 101
mzta 0:158c61bb030f 1751 */
mzta 0:158c61bb030f 1752
mzta 0:158c61bb030f 1753 static mrb_value
mzta 0:158c61bb030f 1754 mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1755 {
mzta 0:158c61bb030f 1756 mrb_value value;
mzta 0:158c61bb030f 1757 mrb_sym id;
mzta 0:158c61bb030f 1758
mzta 0:158c61bb030f 1759 mrb_get_args(mrb, "no", &id, &value);
mzta 0:158c61bb030f 1760 check_cv_name_sym(mrb, id);
mzta 0:158c61bb030f 1761 mrb_cv_set(mrb, mod, id, value);
mzta 0:158c61bb030f 1762 return value;
mzta 0:158c61bb030f 1763 }
mzta 0:158c61bb030f 1764
mzta 0:158c61bb030f 1765 /* 15.2.2.4.39 */
mzta 0:158c61bb030f 1766 /*
mzta 0:158c61bb030f 1767 * call-seq:
mzta 0:158c61bb030f 1768 * remove_class_variable(sym) -> obj
mzta 0:158c61bb030f 1769 *
mzta 0:158c61bb030f 1770 * Removes the definition of the <i>sym</i>, returning that
mzta 0:158c61bb030f 1771 * constant's value.
mzta 0:158c61bb030f 1772 *
mzta 0:158c61bb030f 1773 * class Dummy
mzta 0:158c61bb030f 1774 * @@var = 99
mzta 0:158c61bb030f 1775 * puts @@var
mzta 0:158c61bb030f 1776 * p class_variables
mzta 0:158c61bb030f 1777 * remove_class_variable(:@@var)
mzta 0:158c61bb030f 1778 * p class_variables
mzta 0:158c61bb030f 1779 * end
mzta 0:158c61bb030f 1780 *
mzta 0:158c61bb030f 1781 * <em>produces:</em>
mzta 0:158c61bb030f 1782 *
mzta 0:158c61bb030f 1783 * 99
mzta 0:158c61bb030f 1784 * [:@@var]
mzta 0:158c61bb030f 1785 * []
mzta 0:158c61bb030f 1786 */
mzta 0:158c61bb030f 1787
mzta 0:158c61bb030f 1788 static mrb_value
mzta 0:158c61bb030f 1789 mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1790 {
mzta 0:158c61bb030f 1791 mrb_value val;
mzta 0:158c61bb030f 1792 mrb_sym id;
mzta 0:158c61bb030f 1793
mzta 0:158c61bb030f 1794 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1795 check_cv_name_sym(mrb, id);
mzta 0:158c61bb030f 1796
mzta 0:158c61bb030f 1797 val = mrb_iv_remove(mrb, mod, id);
mzta 0:158c61bb030f 1798 if (!mrb_undef_p(val)) return val;
mzta 0:158c61bb030f 1799
mzta 0:158c61bb030f 1800 if (mrb_cv_defined(mrb, mod, id)) {
mzta 0:158c61bb030f 1801 mrb_name_error(mrb, id, "cannot remove %S for %S",
mzta 0:158c61bb030f 1802 mrb_sym2str(mrb, id), mod);
mzta 0:158c61bb030f 1803 }
mzta 0:158c61bb030f 1804
mzta 0:158c61bb030f 1805 mrb_name_error(mrb, id, "class variable %S not defined for %S",
mzta 0:158c61bb030f 1806 mrb_sym2str(mrb, id), mod);
mzta 0:158c61bb030f 1807
mzta 0:158c61bb030f 1808 /* not reached */
mzta 0:158c61bb030f 1809 return mrb_nil_value();
mzta 0:158c61bb030f 1810 }
mzta 0:158c61bb030f 1811
mzta 0:158c61bb030f 1812 /* 15.2.2.4.34 */
mzta 0:158c61bb030f 1813 /*
mzta 0:158c61bb030f 1814 * call-seq:
mzta 0:158c61bb030f 1815 * mod.method_defined?(symbol) -> true or false
mzta 0:158c61bb030f 1816 *
mzta 0:158c61bb030f 1817 * Returns +true+ if the named method is defined by
mzta 0:158c61bb030f 1818 * _mod_ (or its included modules and, if _mod_ is a class,
mzta 0:158c61bb030f 1819 * its ancestors). Public and protected methods are matched.
mzta 0:158c61bb030f 1820 *
mzta 0:158c61bb030f 1821 * module A
mzta 0:158c61bb030f 1822 * def method1() end
mzta 0:158c61bb030f 1823 * end
mzta 0:158c61bb030f 1824 * class B
mzta 0:158c61bb030f 1825 * def method2() end
mzta 0:158c61bb030f 1826 * end
mzta 0:158c61bb030f 1827 * class C < B
mzta 0:158c61bb030f 1828 * include A
mzta 0:158c61bb030f 1829 * def method3() end
mzta 0:158c61bb030f 1830 * end
mzta 0:158c61bb030f 1831 *
mzta 0:158c61bb030f 1832 * A.method_defined? :method1 #=> true
mzta 0:158c61bb030f 1833 * C.method_defined? "method1" #=> true
mzta 0:158c61bb030f 1834 * C.method_defined? "method2" #=> true
mzta 0:158c61bb030f 1835 * C.method_defined? "method3" #=> true
mzta 0:158c61bb030f 1836 * C.method_defined? "method4" #=> false
mzta 0:158c61bb030f 1837 */
mzta 0:158c61bb030f 1838
mzta 0:158c61bb030f 1839 static mrb_value
mzta 0:158c61bb030f 1840 mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1841 {
mzta 0:158c61bb030f 1842 mrb_sym id;
mzta 0:158c61bb030f 1843
mzta 0:158c61bb030f 1844 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1845 return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id));
mzta 0:158c61bb030f 1846 }
mzta 0:158c61bb030f 1847
mzta 0:158c61bb030f 1848 static void
mzta 0:158c61bb030f 1849 remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
mzta 0:158c61bb030f 1850 {
mzta 0:158c61bb030f 1851 struct RClass *c = mrb_class_ptr(mod);
mzta 0:158c61bb030f 1852 khash_t(mt) *h = c->mt;
mzta 0:158c61bb030f 1853 khiter_t k;
mzta 0:158c61bb030f 1854
mzta 0:158c61bb030f 1855 if (h) {
mzta 0:158c61bb030f 1856 k = kh_get(mt, mrb, h, mid);
mzta 0:158c61bb030f 1857 if (k != kh_end(h)) {
mzta 0:158c61bb030f 1858 kh_del(mt, mrb, h, k);
mzta 0:158c61bb030f 1859 return;
mzta 0:158c61bb030f 1860 }
mzta 0:158c61bb030f 1861 }
mzta 0:158c61bb030f 1862
mzta 0:158c61bb030f 1863 mrb_name_error(mrb, mid, "method `%S' not defined in %S",
mzta 0:158c61bb030f 1864 mrb_sym2str(mrb, mid), mod);
mzta 0:158c61bb030f 1865 }
mzta 0:158c61bb030f 1866
mzta 0:158c61bb030f 1867 /* 15.2.2.4.41 */
mzta 0:158c61bb030f 1868 /*
mzta 0:158c61bb030f 1869 * call-seq:
mzta 0:158c61bb030f 1870 * remove_method(symbol) -> self
mzta 0:158c61bb030f 1871 *
mzta 0:158c61bb030f 1872 * Removes the method identified by _symbol_ from the current
mzta 0:158c61bb030f 1873 * class. For an example, see <code>Module.undef_method</code>.
mzta 0:158c61bb030f 1874 */
mzta 0:158c61bb030f 1875
mzta 0:158c61bb030f 1876 static mrb_value
mzta 0:158c61bb030f 1877 mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1878 {
mzta 0:158c61bb030f 1879 mrb_int argc;
mzta 0:158c61bb030f 1880 mrb_value *argv;
mzta 0:158c61bb030f 1881
mzta 0:158c61bb030f 1882 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 1883 while (argc--) {
mzta 0:158c61bb030f 1884 remove_method(mrb, mod, mrb_symbol(*argv));
mzta 0:158c61bb030f 1885 argv++;
mzta 0:158c61bb030f 1886 }
mzta 0:158c61bb030f 1887 return mod;
mzta 0:158c61bb030f 1888 }
mzta 0:158c61bb030f 1889
mzta 0:158c61bb030f 1890
mzta 0:158c61bb030f 1891
mzta 0:158c61bb030f 1892 static void
mzta 0:158c61bb030f 1893 check_const_name_str(mrb_state *mrb, mrb_value str)
mzta 0:158c61bb030f 1894 {
mzta 0:158c61bb030f 1895 if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) {
mzta 0:158c61bb030f 1896 mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str);
mzta 0:158c61bb030f 1897 }
mzta 0:158c61bb030f 1898 }
mzta 0:158c61bb030f 1899
mzta 0:158c61bb030f 1900 static void
mzta 0:158c61bb030f 1901 check_const_name_sym(mrb_state *mrb, mrb_sym id)
mzta 0:158c61bb030f 1902 {
mzta 0:158c61bb030f 1903 check_const_name_str(mrb, mrb_sym2str(mrb, id));
mzta 0:158c61bb030f 1904 }
mzta 0:158c61bb030f 1905
mzta 0:158c61bb030f 1906 static mrb_value
mzta 0:158c61bb030f 1907 const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit)
mzta 0:158c61bb030f 1908 {
mzta 0:158c61bb030f 1909 if (inherit) {
mzta 0:158c61bb030f 1910 return mrb_bool_value(mrb_const_defined(mrb, mod, id));
mzta 0:158c61bb030f 1911 }
mzta 0:158c61bb030f 1912 return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
mzta 0:158c61bb030f 1913 }
mzta 0:158c61bb030f 1914
mzta 0:158c61bb030f 1915 static mrb_value
mzta 0:158c61bb030f 1916 mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1917 {
mzta 0:158c61bb030f 1918 mrb_sym id;
mzta 0:158c61bb030f 1919 mrb_bool inherit = TRUE;
mzta 0:158c61bb030f 1920
mzta 0:158c61bb030f 1921 mrb_get_args(mrb, "n|b", &id, &inherit);
mzta 0:158c61bb030f 1922 check_const_name_sym(mrb, id);
mzta 0:158c61bb030f 1923 return const_defined(mrb, mod, id, inherit);
mzta 0:158c61bb030f 1924 }
mzta 0:158c61bb030f 1925
mzta 0:158c61bb030f 1926 static mrb_value
mzta 0:158c61bb030f 1927 mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1928 {
mzta 0:158c61bb030f 1929 mrb_sym id;
mzta 0:158c61bb030f 1930
mzta 0:158c61bb030f 1931 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1932 check_const_name_sym(mrb, id);
mzta 0:158c61bb030f 1933 return mrb_const_get(mrb, mod, id);
mzta 0:158c61bb030f 1934 }
mzta 0:158c61bb030f 1935
mzta 0:158c61bb030f 1936 static mrb_value
mzta 0:158c61bb030f 1937 mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1938 {
mzta 0:158c61bb030f 1939 mrb_sym id;
mzta 0:158c61bb030f 1940 mrb_value value;
mzta 0:158c61bb030f 1941
mzta 0:158c61bb030f 1942 mrb_get_args(mrb, "no", &id, &value);
mzta 0:158c61bb030f 1943 check_const_name_sym(mrb, id);
mzta 0:158c61bb030f 1944 mrb_const_set(mrb, mod, id, value);
mzta 0:158c61bb030f 1945 return value;
mzta 0:158c61bb030f 1946 }
mzta 0:158c61bb030f 1947
mzta 0:158c61bb030f 1948 static mrb_value
mzta 0:158c61bb030f 1949 mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1950 {
mzta 0:158c61bb030f 1951 mrb_sym id;
mzta 0:158c61bb030f 1952 mrb_value val;
mzta 0:158c61bb030f 1953
mzta 0:158c61bb030f 1954 mrb_get_args(mrb, "n", &id);
mzta 0:158c61bb030f 1955 check_const_name_sym(mrb, id);
mzta 0:158c61bb030f 1956 val = mrb_iv_remove(mrb, mod, id);
mzta 0:158c61bb030f 1957 if (mrb_undef_p(val)) {
mzta 0:158c61bb030f 1958 mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
mzta 0:158c61bb030f 1959 }
mzta 0:158c61bb030f 1960 return val;
mzta 0:158c61bb030f 1961 }
mzta 0:158c61bb030f 1962
mzta 0:158c61bb030f 1963 static mrb_value
mzta 0:158c61bb030f 1964 mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1965 {
mzta 0:158c61bb030f 1966 mrb_sym sym;
mzta 0:158c61bb030f 1967
mzta 0:158c61bb030f 1968 mrb_get_args(mrb, "n", &sym);
mzta 0:158c61bb030f 1969
mzta 0:158c61bb030f 1970 if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
mzta 0:158c61bb030f 1971 mrb_name_error(mrb, sym, "uninitialized constant %S::%S",
mzta 0:158c61bb030f 1972 mod,
mzta 0:158c61bb030f 1973 mrb_sym2str(mrb, sym));
mzta 0:158c61bb030f 1974 }
mzta 0:158c61bb030f 1975 else {
mzta 0:158c61bb030f 1976 mrb_name_error(mrb, sym, "uninitialized constant %S",
mzta 0:158c61bb030f 1977 mrb_sym2str(mrb, sym));
mzta 0:158c61bb030f 1978 }
mzta 0:158c61bb030f 1979 /* not reached */
mzta 0:158c61bb030f 1980 return mrb_nil_value();
mzta 0:158c61bb030f 1981 }
mzta 0:158c61bb030f 1982
mzta 0:158c61bb030f 1983 static mrb_value
mzta 0:158c61bb030f 1984 mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1985 {
mzta 0:158c61bb030f 1986 mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
mzta 0:158c61bb030f 1987 return mrb_nil_value(); /* not reached */
mzta 0:158c61bb030f 1988 }
mzta 0:158c61bb030f 1989
mzta 0:158c61bb030f 1990 static mrb_value
mzta 0:158c61bb030f 1991 mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 1992 {
mzta 0:158c61bb030f 1993 mrb_value obj;
mzta 0:158c61bb030f 1994 mrb_bool eqq;
mzta 0:158c61bb030f 1995
mzta 0:158c61bb030f 1996 mrb_get_args(mrb, "o", &obj);
mzta 0:158c61bb030f 1997 eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
mzta 0:158c61bb030f 1998
mzta 0:158c61bb030f 1999 return mrb_bool_value(eqq);
mzta 0:158c61bb030f 2000 }
mzta 0:158c61bb030f 2001
mzta 0:158c61bb030f 2002 MRB_API mrb_value
mzta 0:158c61bb030f 2003 mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
mzta 0:158c61bb030f 2004 {
mzta 0:158c61bb030f 2005 mrb_value *argv;
mzta 0:158c61bb030f 2006 mrb_int argc, i;
mzta 0:158c61bb030f 2007 mrb_sym mid;
mzta 0:158c61bb030f 2008 struct RProc *method_rproc;
mzta 0:158c61bb030f 2009 struct RClass *rclass;
mzta 0:158c61bb030f 2010 int ai;
mzta 0:158c61bb030f 2011
mzta 0:158c61bb030f 2012 mrb_check_type(mrb, mod, MRB_TT_MODULE);
mzta 0:158c61bb030f 2013
mzta 0:158c61bb030f 2014 mrb_get_args(mrb, "*", &argv, &argc);
mzta 0:158c61bb030f 2015 if(argc == 0) {
mzta 0:158c61bb030f 2016 /* set MODFUNC SCOPE if implemented */
mzta 0:158c61bb030f 2017 return mod;
mzta 0:158c61bb030f 2018 }
mzta 0:158c61bb030f 2019
mzta 0:158c61bb030f 2020 /* set PRIVATE method visibility if implemented */
mzta 0:158c61bb030f 2021 /* mrb_mod_dummy_visibility(mrb, mod); */
mzta 0:158c61bb030f 2022
mzta 0:158c61bb030f 2023 for (i=0; i<argc; i++) {
mzta 0:158c61bb030f 2024 mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);
mzta 0:158c61bb030f 2025
mzta 0:158c61bb030f 2026 mid = mrb_symbol(argv[i]);
mzta 0:158c61bb030f 2027 rclass = mrb_class_ptr(mod);
mzta 0:158c61bb030f 2028 method_rproc = mrb_method_search(mrb, rclass, mid);
mzta 0:158c61bb030f 2029
mzta 0:158c61bb030f 2030 prepare_singleton_class(mrb, (struct RBasic*)rclass);
mzta 0:158c61bb030f 2031 ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 2032 mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
mzta 0:158c61bb030f 2033 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 2034 }
mzta 0:158c61bb030f 2035
mzta 0:158c61bb030f 2036 return mod;
mzta 0:158c61bb030f 2037 }
mzta 0:158c61bb030f 2038
mzta 0:158c61bb030f 2039 void
mzta 0:158c61bb030f 2040 mrb_init_class(mrb_state *mrb)
mzta 0:158c61bb030f 2041 {
mzta 0:158c61bb030f 2042 struct RClass *bob; /* BasicObject */
mzta 0:158c61bb030f 2043 struct RClass *obj; /* Object */
mzta 0:158c61bb030f 2044 struct RClass *mod; /* Module */
mzta 0:158c61bb030f 2045 struct RClass *cls; /* Class */
mzta 0:158c61bb030f 2046
mzta 0:158c61bb030f 2047 /* boot class hierarchy */
mzta 0:158c61bb030f 2048 bob = boot_defclass(mrb, 0);
mzta 0:158c61bb030f 2049 obj = boot_defclass(mrb, bob); mrb->object_class = obj;
mzta 0:158c61bb030f 2050 mod = boot_defclass(mrb, obj); mrb->module_class = mod;/* obj -> mod */
mzta 0:158c61bb030f 2051 cls = boot_defclass(mrb, mod); mrb->class_class = cls; /* obj -> cls */
mzta 0:158c61bb030f 2052 /* fix-up loose ends */
mzta 0:158c61bb030f 2053 bob->c = obj->c = mod->c = cls->c = cls;
mzta 0:158c61bb030f 2054 make_metaclass(mrb, bob);
mzta 0:158c61bb030f 2055 make_metaclass(mrb, obj);
mzta 0:158c61bb030f 2056 make_metaclass(mrb, mod);
mzta 0:158c61bb030f 2057 make_metaclass(mrb, cls);
mzta 0:158c61bb030f 2058
mzta 0:158c61bb030f 2059 /* name basic classes */
mzta 0:158c61bb030f 2060 mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
mzta 0:158c61bb030f 2061 mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
mzta 0:158c61bb030f 2062 mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
mzta 0:158c61bb030f 2063 mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
mzta 0:158c61bb030f 2064 mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
mzta 0:158c61bb030f 2065
mzta 0:158c61bb030f 2066 /* name each classes */
mzta 0:158c61bb030f 2067 name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
mzta 0:158c61bb030f 2068 name_class(mrb, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
mzta 0:158c61bb030f 2069 name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
mzta 0:158c61bb030f 2070 name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
mzta 0:158c61bb030f 2071
mzta 0:158c61bb030f 2072 mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */
mzta 0:158c61bb030f 2073 MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
mzta 0:158c61bb030f 2074
mzta 0:158c61bb030f 2075 MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
mzta 0:158c61bb030f 2076 mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE());
mzta 0:158c61bb030f 2077 mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE());
mzta 0:158c61bb030f 2078 mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */
mzta 0:158c61bb030f 2079
mzta 0:158c61bb030f 2080 mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1));
mzta 0:158c61bb030f 2081 mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */
mzta 0:158c61bb030f 2082 mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */
mzta 0:158c61bb030f 2083 mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
mzta 0:158c61bb030f 2084 mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 2085
mzta 0:158c61bb030f 2086 MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mzta 0:158c61bb030f 2087 mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */
mzta 0:158c61bb030f 2088 mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */
mzta 0:158c61bb030f 2089 mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
mzta 0:158c61bb030f 2090 mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mzta 0:158c61bb030f 2091 mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mzta 0:158c61bb030f 2092 mrb_define_method(mrb, mod, "include", mrb_mod_include, MRB_ARGS_ANY()); /* 15.2.2.4.27 */
mzta 0:158c61bb030f 2093 mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
mzta 0:158c61bb030f 2094 mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
mzta 0:158c61bb030f 2095 mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */
mzta 0:158c61bb030f 2096 mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
mzta 0:158c61bb030f 2097 mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */
mzta 0:158c61bb030f 2098 mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */
mzta 0:158c61bb030f 2099 mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */
mzta 0:158c61bb030f 2100 mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
mzta 0:158c61bb030f 2101 mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */
mzta 0:158c61bb030f 2102 mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY());
mzta 0:158c61bb030f 2103 mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */
mzta 0:158c61bb030f 2104 mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */
mzta 0:158c61bb030f 2105 mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */
mzta 0:158c61bb030f 2106 mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
mzta 0:158c61bb030f 2107 mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
mzta 0:158c61bb030f 2108 mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */
mzta 0:158c61bb030f 2109 mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */
mzta 0:158c61bb030f 2110 mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE());
mzta 0:158c61bb030f 2111 mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE());
mzta 0:158c61bb030f 2112 mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */
mzta 0:158c61bb030f 2113 mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */
mzta 0:158c61bb030f 2114 mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
mzta 0:158c61bb030f 2115 mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */
mzta 0:158c61bb030f 2116 mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */
mzta 0:158c61bb030f 2117 mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
mzta 0:158c61bb030f 2118 mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
mzta 0:158c61bb030f 2119 mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
mzta 0:158c61bb030f 2120 mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 2121 mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 2122 mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */
mzta 0:158c61bb030f 2123 mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 2124 mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */
mzta 0:158c61bb030f 2125
mzta 0:158c61bb030f 2126 mrb_undef_method(mrb, cls, "append_features");
mzta 0:158c61bb030f 2127 mrb_undef_method(mrb, cls, "extend_object");
mzta 0:158c61bb030f 2128 }
mzta 0:158c61bb030f 2129