source: EcnlProtoTool/trunk/mruby-1.2.0/src/kernel.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 34.5 KB
Line 
1/*
2** kernel.c - Kernel module
3**
4** See Copyright Notice in mruby.h
5*/
6
7#include "mruby.h"
8#include "mruby/array.h"
9#include "mruby/class.h"
10#include "mruby/proc.h"
11#include "mruby/string.h"
12#include "mruby/variable.h"
13#include "mruby/error.h"
14
15typedef enum {
16 NOEX_PUBLIC = 0x00,
17 NOEX_NOSUPER = 0x01,
18 NOEX_PRIVATE = 0x02,
19 NOEX_PROTECTED = 0x04,
20 NOEX_MASK = 0x06,
21 NOEX_BASIC = 0x08,
22 NOEX_UNDEF = NOEX_NOSUPER,
23 NOEX_MODFUNC = 0x12,
24 NOEX_SUPER = 0x20,
25 NOEX_VCALL = 0x40,
26 NOEX_RESPONDS = 0x80
27} mrb_method_flag_t;
28
29static mrb_bool
30mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
31{
32 struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s"));
33 if (MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
34 return TRUE;
35 return FALSE;
36}
37
38/* 15.3.1.3.17 */
39/*
40 * call-seq:
41 * obj.inspect -> string
42 *
43 * Returns a string containing a human-readable representation of
44 * <i>obj</i>. If not overridden and no instance variables, uses the
45 * <code>to_s</code> method to generate the string.
46 * <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
47 * generate the string.
48 *
49 * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
50 * Time.new.inspect #=> "2008-03-08 19:43:39 +0900"
51 */
52MRB_API mrb_value
53mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
54{
55 if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
56 return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
57 }
58 return mrb_any_to_s(mrb, obj);
59}
60
61/* 15.3.1.3.1 */
62/* 15.3.1.3.10 */
63/* 15.3.1.3.11 */
64/*
65 * call-seq:
66 * obj == other -> true or false
67 * obj.equal?(other) -> true or false
68 * obj.eql?(other) -> true or false
69 *
70 * Equality---At the <code>Object</code> level, <code>==</code> returns
71 * <code>true</code> only if <i>obj</i> and <i>other</i> are the
72 * same object. Typically, this method is overridden in descendant
73 * classes to provide class-specific meaning.
74 *
75 * Unlike <code>==</code>, the <code>equal?</code> method should never be
76 * overridden by subclasses: it is used to determine object identity
77 * (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
78 * object as <code>b</code>).
79 *
80 * The <code>eql?</code> method returns <code>true</code> if
81 * <i>obj</i> and <i>anObject</i> have the same value. Used by
82 * <code>Hash</code> to test members for equality. For objects of
83 * class <code>Object</code>, <code>eql?</code> is synonymous with
84 * <code>==</code>. Subclasses normally continue this tradition, but
85 * there are exceptions. <code>Numeric</code> types, for example,
86 * perform type conversion across <code>==</code>, but not across
87 * <code>eql?</code>, so:
88 *
89 * 1 == 1.0 #=> true
90 * 1.eql? 1.0 #=> false
91 */
92static mrb_value
93mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
94{
95 mrb_value arg;
96
97 mrb_get_args(mrb, "o", &arg);
98 return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
99}
100
101static mrb_value
102mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
103{
104 mrb_value arg;
105
106 mrb_get_args(mrb, "o", &arg);
107 return mrb_bool_value(!mrb_equal(mrb, self, arg));
108}
109
110/* 15.3.1.3.2 */
111/*
112 * call-seq:
113 * obj === other -> true or false
114 *
115 * Case Equality---For class <code>Object</code>, effectively the same
116 * as calling <code>#==</code>, but typically overridden by descendants
117 * to provide meaningful semantics in <code>case</code> statements.
118 */
119static mrb_value
120mrb_equal_m(mrb_state *mrb, mrb_value self)
121{
122 mrb_value arg;
123
124 mrb_get_args(mrb, "o", &arg);
125 return mrb_bool_value(mrb_equal(mrb, self, arg));
126}
127
128/* 15.3.1.3.3 */
129/* 15.3.1.3.33 */
130/*
131 * Document-method: __id__
132 * Document-method: object_id
133 *
134 * call-seq:
135 * obj.__id__ -> fixnum
136 * obj.object_id -> fixnum
137 *
138 * Returns an integer identifier for <i>obj</i>. The same number will
139 * be returned on all calls to <code>id</code> for a given object, and
140 * no two active objects will share an id.
141 * <code>Object#object_id</code> is a different concept from the
142 * <code>:name</code> notation, which returns the symbol id of
143 * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
144 */
145static mrb_value
146mrb_obj_id_m(mrb_state *mrb, mrb_value self)
147{
148 return mrb_fixnum_value(mrb_obj_id(self));
149}
150
151/* 15.3.1.2.2 */
152/* 15.3.1.2.5 */
153/* 15.3.1.3.6 */
154/* 15.3.1.3.25 */
155/*
156 * call-seq:
157 * block_given? -> true or false
158 * iterator? -> true or false
159 *
160 * Returns <code>true</code> if <code>yield</code> would execute a
161 * block in the current context. The <code>iterator?</code> form
162 * is mildly deprecated.
163 *
164 * def try
165 * if block_given?
166 * yield
167 * else
168 * "no block"
169 * end
170 * end
171 * try #=> "no block"
172 * try { "hello" } #=> "hello"
173 * try do "hello" end #=> "hello"
174 */
175static mrb_value
176mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
177{
178 mrb_callinfo *ci = mrb->c->ci;
179 mrb_value *bp;
180 mrb_bool given_p;
181
182 bp = ci->stackent + 1;
183 ci--;
184 if (ci <= mrb->c->cibase) {
185 given_p = FALSE;
186 }
187 else {
188 /* block_given? called within block; check upper scope */
189 if (ci->proc->env) {
190 struct REnv *e = ci->proc->env;
191 mrb_value *sp;
192
193 while (e->c) {
194 e = (struct REnv*)e->c;
195 }
196 sp = e->stack;
197 if (sp) {
198 /* top-level does not have block slot (alway false) */
199 if (sp == mrb->c->stbase)
200 return mrb_false_value();
201 ci = mrb->c->cibase + e->cioff;
202 bp = ci[1].stackent + 1;
203 }
204 }
205 if (ci->argc > 0) {
206 bp += ci->argc;
207 }
208 given_p = !mrb_nil_p(*bp);
209 }
210
211 return mrb_bool_value(given_p);
212}
213
214/* 15.3.1.3.7 */
215/*
216 * call-seq:
217 * obj.class -> class
218 *
219 * Returns the class of <i>obj</i>. This method must always be
220 * called with an explicit receiver, as <code>class</code> is also a
221 * reserved word in Ruby.
222 *
223 * 1.class #=> Fixnum
224 * self.class #=> Object
225 */
226static mrb_value
227mrb_obj_class_m(mrb_state *mrb, mrb_value self)
228{
229 return mrb_obj_value(mrb_obj_class(mrb, self));
230}
231
232static struct RClass*
233mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
234{
235 struct RClass *klass = mrb_basic_ptr(obj)->c;
236
237 if (klass->tt != MRB_TT_SCLASS)
238 return klass;
239 else {
240 /* copy singleton(unnamed) class */
241 struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
242
243 if ((mrb_type(obj) == MRB_TT_CLASS) || (mrb_type(obj) == MRB_TT_SCLASS)) {
244 clone->c = clone;
245 }
246 else {
247 clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
248 }
249 clone->super = klass->super;
250 if (klass->iv) {
251 mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
252 mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj);
253 }
254 if (klass->mt) {
255 clone->mt = kh_copy(mt, mrb, klass->mt);
256 }
257 else {
258 clone->mt = kh_init(mt, mrb);
259 }
260 clone->tt = MRB_TT_SCLASS;
261 return clone;
262 }
263}
264
265static void
266copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
267{
268 struct RClass *dc = mrb_class_ptr(dst);
269 struct RClass *sc = mrb_class_ptr(src);
270 /* if the origin is not the same as the class, then the origin and
271 the current class need to be copied */
272 if (sc->flags & MRB_FLAG_IS_PREPENDED) {
273 struct RClass *c0 = sc->super;
274 struct RClass *c1 = dc;
275
276 /* copy prepended iclasses */
277 while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) {
278 c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
279 c1 = c1->super;
280 c0 = c0->super;
281 }
282 c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
283 c1->super->flags |= MRB_FLAG_IS_ORIGIN;
284 }
285 dc->mt = kh_copy(mt, mrb, sc->mt);
286 dc->super = sc->super;
287}
288
289static void
290init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
291{
292 switch (mrb_type(obj)) {
293 case MRB_TT_CLASS:
294 case MRB_TT_MODULE:
295 copy_class(mrb, dest, obj);
296 /* fall through */
297 case MRB_TT_OBJECT:
298 case MRB_TT_SCLASS:
299 case MRB_TT_HASH:
300 case MRB_TT_DATA:
301 case MRB_TT_EXCEPTION:
302 mrb_iv_copy(mrb, dest, obj);
303 break;
304
305 default:
306 break;
307 }
308 mrb_funcall(mrb, dest, "initialize_copy", 1, obj);
309}
310
311/* 15.3.1.3.8 */
312/*
313 * call-seq:
314 * obj.clone -> an_object
315 *
316 * Produces a shallow copy of <i>obj</i>---the instance variables of
317 * <i>obj</i> are copied, but not the objects they reference. Copies
318 * the frozen state of <i>obj</i>. See also the discussion
319 * under <code>Object#dup</code>.
320 *
321 * class Klass
322 * attr_accessor :str
323 * end
324 * s1 = Klass.new #=> #<Klass:0x401b3a38>
325 * s1.str = "Hello" #=> "Hello"
326 * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
327 * s2.str[1,4] = "i" #=> "i"
328 * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
329 * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
330 *
331 * This method may have class-specific behavior. If so, that
332 * behavior will be documented under the #+initialize_copy+ method of
333 * the class.
334 *
335 * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone.
336 */
337MRB_API mrb_value
338mrb_obj_clone(mrb_state *mrb, mrb_value self)
339{
340 struct RObject *p;
341 mrb_value clone;
342
343 if (mrb_immediate_p(self)) {
344 mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
345 }
346 if (mrb_type(self) == MRB_TT_SCLASS) {
347 mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
348 }
349 p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
350 p->c = mrb_singleton_class_clone(mrb, self);
351 clone = mrb_obj_value(p);
352 init_copy(mrb, clone, self);
353
354 return clone;
355}
356
357/* 15.3.1.3.9 */
358/*
359 * call-seq:
360 * obj.dup -> an_object
361 *
362 * Produces a shallow copy of <i>obj</i>---the instance variables of
363 * <i>obj</i> are copied, but not the objects they reference.
364 * <code>dup</code> copies the frozen state of <i>obj</i>. See also
365 * the discussion under <code>Object#clone</code>. In general,
366 * <code>clone</code> and <code>dup</code> may have different semantics
367 * in descendant classes. While <code>clone</code> is used to duplicate
368 * an object, including its internal state, <code>dup</code> typically
369 * uses the class of the descendant object to create the new instance.
370 *
371 * This method may have class-specific behavior. If so, that
372 * behavior will be documented under the #+initialize_copy+ method of
373 * the class.
374 */
375
376MRB_API mrb_value
377mrb_obj_dup(mrb_state *mrb, mrb_value obj)
378{
379 struct RBasic *p;
380 mrb_value dup;
381
382 if (mrb_immediate_p(obj)) {
383 mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
384 }
385 if (mrb_type(obj) == MRB_TT_SCLASS) {
386 mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
387 }
388 p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
389 dup = mrb_obj_value(p);
390 init_copy(mrb, dup, obj);
391
392 return dup;
393}
394
395static mrb_value
396mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj)
397{
398 mrb_int i;
399
400 if (argc == 0) {
401 mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
402 }
403 for (i = 0; i < argc; i++) {
404 mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
405 }
406 while (argc--) {
407 mrb_funcall(mrb, argv[argc], "extend_object", 1, obj);
408 mrb_funcall(mrb, argv[argc], "extended", 1, obj);
409 }
410 return obj;
411}
412
413/* 15.3.1.3.13 */
414/*
415 * call-seq:
416 * obj.extend(module, ...) -> obj
417 *
418 * Adds to _obj_ the instance methods from each module given as a
419 * parameter.
420 *
421 * module Mod
422 * def hello
423 * "Hello from Mod.\n"
424 * end
425 * end
426 *
427 * class Klass
428 * def hello
429 * "Hello from Klass.\n"
430 * end
431 * end
432 *
433 * k = Klass.new
434 * k.hello #=> "Hello from Klass.\n"
435 * k.extend(Mod) #=> #<Klass:0x401b3bc8>
436 * k.hello #=> "Hello from Mod.\n"
437 */
438static mrb_value
439mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
440{
441 mrb_value *argv;
442 mrb_int argc;
443
444 mrb_get_args(mrb, "*", &argv, &argc);
445 return mrb_obj_extend(mrb, argc, argv, self);
446}
447
448/* 15.3.1.3.15 */
449/*
450 * call-seq:
451 * obj.hash -> fixnum
452 *
453 * Generates a <code>Fixnum</code> hash value for this object. This
454 * function must have the property that <code>a.eql?(b)</code> implies
455 * <code>a.hash == b.hash</code>. The hash value is used by class
456 * <code>Hash</code>. Any hash value that exceeds the capacity of a
457 * <code>Fixnum</code> will be truncated before being used.
458 */
459MRB_API mrb_value
460mrb_obj_hash(mrb_state *mrb, mrb_value self)
461{
462 return mrb_fixnum_value(mrb_obj_id(self));
463}
464
465/* 15.3.1.3.16 */
466static mrb_value
467mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
468{
469 mrb_value orig;
470
471 mrb_get_args(mrb, "o", &orig);
472 if (mrb_obj_equal(mrb, self, orig)) return self;
473 if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
474 mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
475 }
476 return self;
477}
478
479
480/* implementation of instance_eval */
481mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value);
482
483MRB_API mrb_bool
484mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c)
485{
486 if (mrb_obj_class(mrb, obj) == c) return TRUE;
487 return FALSE;
488}
489
490/* 15.3.1.3.19 */
491/*
492 * call-seq:
493 * obj.instance_of?(class) -> true or false
494 *
495 * Returns <code>true</code> if <i>obj</i> is an instance of the given
496 * class. See also <code>Object#kind_of?</code>.
497 */
498static mrb_value
499obj_is_instance_of(mrb_state *mrb, mrb_value self)
500{
501 mrb_value arg;
502
503 mrb_get_args(mrb, "C", &arg);
504
505 return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg)));
506}
507
508/* 15.3.1.3.20 */
509/*
510 * call-seq:
511 * obj.instance_variable_defined?(symbol) -> true or false
512 *
513 * Returns <code>true</code> if the given instance variable is
514 * defined in <i>obj</i>.
515 *
516 * class Fred
517 * def initialize(p1, p2)
518 * @a, @b = p1, p2
519 * end
520 * end
521 * fred = Fred.new('cat', 99)
522 * fred.instance_variable_defined?(:@a) #=> true
523 * fred.instance_variable_defined?("@b") #=> true
524 * fred.instance_variable_defined?("@c") #=> false
525 */
526static mrb_value
527mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
528{
529 mrb_sym sym;
530
531 mrb_get_args(mrb, "n", &sym);
532 mrb_iv_check(mrb, sym);
533 return mrb_bool_value(mrb_iv_defined(mrb, self, sym));
534}
535
536/* 15.3.1.3.21 */
537/*
538 * call-seq:
539 * obj.instance_variable_get(symbol) -> obj
540 *
541 * Returns the value of the given instance variable, or nil if the
542 * instance variable is not set. The <code>@</code> part of the
543 * variable name should be included for regular instance
544 * variables. Throws a <code>NameError</code> exception if the
545 * supplied symbol is not valid as an instance variable name.
546 *
547 * class Fred
548 * def initialize(p1, p2)
549 * @a, @b = p1, p2
550 * end
551 * end
552 * fred = Fred.new('cat', 99)
553 * fred.instance_variable_get(:@a) #=> "cat"
554 * fred.instance_variable_get("@b") #=> 99
555 */
556static mrb_value
557mrb_obj_ivar_get(mrb_state *mrb, mrb_value self)
558{
559 mrb_sym iv_name;
560
561 mrb_get_args(mrb, "n", &iv_name);
562 mrb_iv_check(mrb, iv_name);
563 return mrb_iv_get(mrb, self, iv_name);
564}
565
566/* 15.3.1.3.22 */
567/*
568 * call-seq:
569 * obj.instance_variable_set(symbol, obj) -> obj
570 *
571 * Sets the instance variable names by <i>symbol</i> to
572 * <i>object</i>, thereby frustrating the efforts of the class's
573 * author to attempt to provide proper encapsulation. The variable
574 * did not have to exist prior to this call.
575 *
576 * class Fred
577 * def initialize(p1, p2)
578 * @a, @b = p1, p2
579 * end
580 * end
581 * fred = Fred.new('cat', 99)
582 * fred.instance_variable_set(:@a, 'dog') #=> "dog"
583 * fred.instance_variable_set(:@c, 'cat') #=> "cat"
584 * fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
585 */
586static mrb_value
587mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
588{
589 mrb_sym iv_name;
590 mrb_value val;
591
592 mrb_get_args(mrb, "no", &iv_name, &val);
593 mrb_iv_check(mrb, iv_name);
594 mrb_iv_set(mrb, self, iv_name, val);
595 return val;
596}
597
598/* 15.3.1.3.24 */
599/* 15.3.1.3.26 */
600/*
601 * call-seq:
602 * obj.is_a?(class) -> true or false
603 * obj.kind_of?(class) -> true or false
604 *
605 * Returns <code>true</code> if <i>class</i> is the class of
606 * <i>obj</i>, or if <i>class</i> is one of the superclasses of
607 * <i>obj</i> or modules included in <i>obj</i>.
608 *
609 * module M; end
610 * class A
611 * include M
612 * end
613 * class B < A; end
614 * class C < B; end
615 * b = B.new
616 * b.instance_of? A #=> false
617 * b.instance_of? B #=> true
618 * b.instance_of? C #=> false
619 * b.instance_of? M #=> false
620 * b.kind_of? A #=> true
621 * b.kind_of? B #=> true
622 * b.kind_of? C #=> false
623 * b.kind_of? M #=> true
624 */
625static mrb_value
626mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
627{
628 mrb_value arg;
629
630 mrb_get_args(mrb, "C", &arg);
631
632 return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg)));
633}
634
635KHASH_DECLARE(st, mrb_sym, char, FALSE)
636KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
637
638static void
639method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
640{
641 khint_t i;
642
643 khash_t(mt) *h = klass->mt;
644 if (!h) return;
645 for (i=0;i<kh_end(h);i++) {
646 if (kh_exist(h, i) && kh_value(h, i)) {
647 kh_put(st, mrb, set, kh_key(h, i));
648 }
649 }
650}
651
652mrb_value
653mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
654{
655 khint_t i;
656 mrb_value ary;
657 mrb_bool prepended = FALSE;
658 struct RClass* oldklass;
659 khash_t(st)* set = kh_init(st, mrb);
660
661 if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) {
662 MRB_CLASS_ORIGIN(klass);
663 prepended = TRUE;
664 }
665
666 oldklass = 0;
667 while (klass && (klass != oldklass)) {
668 method_entry_loop(mrb, klass, set);
669 if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
670 (klass->tt == MRB_TT_SCLASS)) {
671 }
672 else {
673 if (!recur) break;
674 }
675 oldklass = klass;
676 klass = klass->super;
677 }
678
679 ary = mrb_ary_new(mrb);
680 for (i=0;i<kh_end(set);i++) {
681 if (kh_exist(set, i)) {
682 mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
683 }
684 }
685 kh_destroy(st, mrb, set);
686
687 return ary;
688}
689
690static mrb_value
691mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
692{
693 khint_t i;
694 mrb_value ary;
695 struct RClass* klass;
696 khash_t(st)* set = kh_init(st, mrb);
697
698 klass = mrb_class(mrb, obj);
699
700 if (klass && (klass->tt == MRB_TT_SCLASS)) {
701 method_entry_loop(mrb, klass, set);
702 klass = klass->super;
703 }
704 if (recur) {
705 while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
706 method_entry_loop(mrb, klass, set);
707 klass = klass->super;
708 }
709 }
710
711 ary = mrb_ary_new(mrb);
712 for (i=0;i<kh_end(set);i++) {
713 if (kh_exist(set, i)) {
714 mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
715 }
716 }
717 kh_destroy(st, mrb, set);
718
719 return ary;
720}
721
722static mrb_value
723mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, mrb_method_flag_t flag)
724{
725 if (recur)
726 return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0);
727 return mrb_obj_singleton_methods(mrb, recur, obj);
728}
729/* 15.3.1.3.31 */
730/*
731 * call-seq:
732 * obj.methods -> array
733 *
734 * Returns a list of the names of methods publicly accessible in
735 * <i>obj</i>. This will include all the methods accessible in
736 * <i>obj</i>'s ancestors.
737 *
738 * class Klass
739 * def kMethod()
740 * end
741 * end
742 * k = Klass.new
743 * k.methods[0..9] #=> [:kMethod, :respond_to?, :nil?, :is_a?,
744 * # :class, :instance_variable_set,
745 * # :methods, :extend, :__send__, :instance_eval]
746 * k.methods.length #=> 42
747 */
748static mrb_value
749mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
750{
751 mrb_bool recur = TRUE;
752 mrb_get_args(mrb, "|b", &recur);
753 return mrb_obj_methods(mrb, recur, self, (mrb_method_flag_t)0); /* everything but private */
754}
755
756/* 15.3.1.3.32 */
757/*
758 * call_seq:
759 * nil.nil? -> true
760 * <anything_else>.nil? -> false
761 *
762 * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
763 */
764static mrb_value
765mrb_false(mrb_state *mrb, mrb_value self)
766{
767 return mrb_false_value();
768}
769
770/* 15.3.1.3.36 */
771/*
772 * call-seq:
773 * obj.private_methods(all=true) -> array
774 *
775 * Returns the list of private methods accessible to <i>obj</i>. If
776 * the <i>all</i> parameter is set to <code>false</code>, only those methods
777 * in the receiver will be listed.
778 */
779static mrb_value
780mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
781{
782 mrb_bool recur = TRUE;
783 mrb_get_args(mrb, "|b", &recur);
784 return mrb_obj_methods(mrb, recur, self, NOEX_PRIVATE); /* private attribute not define */
785}
786
787/* 15.3.1.3.37 */
788/*
789 * call-seq:
790 * obj.protected_methods(all=true) -> array
791 *
792 * Returns the list of protected methods accessible to <i>obj</i>. If
793 * the <i>all</i> parameter is set to <code>false</code>, only those methods
794 * in the receiver will be listed.
795 */
796static mrb_value
797mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
798{
799 mrb_bool recur = TRUE;
800 mrb_get_args(mrb, "|b", &recur);
801 return mrb_obj_methods(mrb, recur, self, NOEX_PROTECTED); /* protected attribute not define */
802}
803
804/* 15.3.1.3.38 */
805/*
806 * call-seq:
807 * obj.public_methods(all=true) -> array
808 *
809 * Returns the list of public methods accessible to <i>obj</i>. If
810 * the <i>all</i> parameter is set to <code>false</code>, only those methods
811 * in the receiver will be listed.
812 */
813static mrb_value
814mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
815{
816 mrb_bool recur = TRUE;
817 mrb_get_args(mrb, "|b", &recur);
818 return mrb_obj_methods(mrb, recur, self, NOEX_PUBLIC); /* public attribute not define */
819}
820
821/* 15.3.1.2.12 */
822/* 15.3.1.3.40 */
823/*
824 * call-seq:
825 * raise
826 * raise(string)
827 * raise(exception [, string])
828 *
829 * With no arguments, raises a <code>RuntimeError</code>
830 * With a single +String+ argument, raises a
831 * +RuntimeError+ with the string as a message. Otherwise,
832 * the first parameter should be the name of an +Exception+
833 * class (or an object that returns an +Exception+ object when sent
834 * an +exception+ message). The optional second parameter sets the
835 * message associated with the exception, and the third parameter is an
836 * array of callback information. Exceptions are caught by the
837 * +rescue+ clause of <code>begin...end</code> blocks.
838 *
839 * raise "Failed to create socket"
840 * raise ArgumentError, "No parameters", caller
841 */
842MRB_API mrb_value
843mrb_f_raise(mrb_state *mrb, mrb_value self)
844{
845 mrb_value a[2], exc;
846 int argc;
847
848
849 argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]);
850 switch (argc) {
851 case 0:
852 mrb_raise(mrb, E_RUNTIME_ERROR, "");
853 break;
854 case 1:
855 a[1] = mrb_check_string_type(mrb, a[0]);
856 if (!mrb_nil_p(a[1])) {
857 argc = 2;
858 a[0] = mrb_obj_value(E_RUNTIME_ERROR);
859 }
860 /* fall through */
861 default:
862 exc = mrb_make_exception(mrb, argc, a);
863 mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, mrb->c->ci->pc));
864 mrb_exc_raise(mrb, exc);
865 break;
866 }
867 return mrb_nil_value(); /* not reached */
868}
869
870/* 15.3.1.3.41 */
871/*
872 * call-seq:
873 * obj.remove_instance_variable(symbol) -> obj
874 *
875 * Removes the named instance variable from <i>obj</i>, returning that
876 * variable's value.
877 *
878 * class Dummy
879 * attr_reader :var
880 * def initialize
881 * @var = 99
882 * end
883 * def remove
884 * remove_instance_variable(:@var)
885 * end
886 * end
887 * d = Dummy.new
888 * d.var #=> 99
889 * d.remove #=> 99
890 * d.var #=> nil
891 */
892static mrb_value
893mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
894{
895 mrb_sym sym;
896 mrb_value val;
897
898 mrb_get_args(mrb, "n", &sym);
899 mrb_iv_check(mrb, sym);
900 val = mrb_iv_remove(mrb, self, sym);
901 if (mrb_undef_p(val)) {
902 mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym));
903 }
904 return val;
905}
906
907static inline mrb_bool
908basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
909{
910 return mrb_respond_to(mrb, obj, id);
911}
912/* 15.3.1.3.43 */
913/*
914 * call-seq:
915 * obj.respond_to?(symbol, include_private=false) -> true or false
916 *
917 * Returns +true+ if _obj_ responds to the given
918 * method. Private methods are included in the search only if the
919 * optional second parameter evaluates to +true+.
920 *
921 * If the method is not implemented,
922 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
923 * false is returned.
924 *
925 * If the method is not defined, <code>respond_to_missing?</code>
926 * method is called and the result is returned.
927 */
928static mrb_value
929obj_respond_to(mrb_state *mrb, mrb_value self)
930{
931 mrb_value mid;
932 mrb_sym id, rtm_id;
933 mrb_bool priv = FALSE, respond_to_p = TRUE;
934
935 mrb_get_args(mrb, "o|b", &mid, &priv);
936
937 if (mrb_symbol_p(mid)) {
938 id = mrb_symbol(mid);
939 }
940 else {
941 mrb_value tmp;
942 if (!mrb_string_p(mid)) {
943 tmp = mrb_check_string_type(mrb, mid);
944 if (mrb_nil_p(tmp)) {
945 tmp = mrb_inspect(mrb, mid);
946 mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
947 }
948 }
949 tmp = mrb_check_intern_str(mrb, mid);
950 if (mrb_nil_p(tmp)) {
951 respond_to_p = FALSE;
952 }
953 else {
954 id = mrb_symbol(tmp);
955 }
956 }
957
958 if (respond_to_p) {
959 respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
960 }
961
962 if (!respond_to_p) {
963 rtm_id = mrb_intern_lit(mrb, "respond_to_missing?");
964 if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) {
965 mrb_value args[2];
966 args[0] = mid;
967 args[1] = mrb_bool_value(priv);
968 return mrb_funcall_argv(mrb, self, rtm_id, 2, args);
969 }
970 }
971 return mrb_bool_value(respond_to_p);
972}
973
974/* 15.3.1.3.45 */
975/*
976 * call-seq:
977 * obj.singleton_methods(all=true) -> array
978 *
979 * Returns an array of the names of singleton methods for <i>obj</i>.
980 * If the optional <i>all</i> parameter is true, the list will include
981 * methods in modules included in <i>obj</i>.
982 * Only public and protected singleton methods are returned.
983 *
984 * module Other
985 * def three() end
986 * end
987 *
988 * class Single
989 * def Single.four() end
990 * end
991 *
992 * a = Single.new
993 *
994 * def a.one()
995 * end
996 *
997 * class << a
998 * include Other
999 * def two()
1000 * end
1001 * end
1002 *
1003 * Single.singleton_methods #=> [:four]
1004 * a.singleton_methods(false) #=> [:two, :one]
1005 * a.singleton_methods #=> [:two, :one, :three]
1006 */
1007static mrb_value
1008mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
1009{
1010 mrb_bool recur = TRUE;
1011 mrb_get_args(mrb, "|b", &recur);
1012 return mrb_obj_singleton_methods(mrb, recur, self);
1013}
1014
1015static mrb_value
1016mod_define_singleton_method(mrb_state *mrb, mrb_value self)
1017{
1018 struct RProc *p;
1019 mrb_sym mid;
1020 mrb_value blk = mrb_nil_value();
1021
1022 mrb_get_args(mrb, "n&", &mid, &blk);
1023 if (mrb_nil_p(blk)) {
1024 mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
1025 }
1026 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
1027 mrb_proc_copy(p, mrb_proc_ptr(blk));
1028 p->flags |= MRB_PROC_STRICT;
1029 mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p);
1030 return mrb_symbol_value(mid);
1031}
1032
1033static mrb_value
1034mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
1035{
1036 mrb_value v;
1037 mrb_int i, len;
1038 mrb_sym eqq = mrb_intern_lit(mrb, "===");
1039 mrb_value ary = mrb_ary_splat(mrb, self);
1040
1041 mrb_get_args(mrb, "o", &v);
1042 len = RARRAY_LEN(ary);
1043 for (i=0; i<len; i++) {
1044 mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v);
1045 if (mrb_test(c)) return mrb_true_value();
1046 }
1047 return mrb_false_value();
1048}
1049
1050static mrb_value
1051mrb_local_variables(mrb_state *mrb, mrb_value self)
1052{
1053 mrb_value ret;
1054 struct RProc *proc;
1055 struct mrb_irep *irep;
1056 size_t i;
1057
1058 proc = mrb->c->ci[-1].proc;
1059
1060 if (MRB_PROC_CFUNC_P(proc)) {
1061 return mrb_ary_new(mrb);
1062 }
1063
1064 irep = proc->body.irep;
1065 if (!irep->lv) {
1066 return mrb_ary_new(mrb);
1067 }
1068 ret = mrb_ary_new_capa(mrb, irep->nlocals - 1);
1069 for (i = 0; i + 1 < irep->nlocals; ++i) {
1070 if (irep->lv[i].name) {
1071 mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name));
1072 }
1073 }
1074 if (proc->env) {
1075 struct REnv *e = proc->env;
1076
1077 while (e) {
1078 if (!MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) {
1079 irep = mrb->c->cibase[e->cioff].proc->body.irep;
1080 if (irep->lv) {
1081 for (i = 0; i + 1 < irep->nlocals; ++i) {
1082 if (irep->lv[i].name) {
1083 mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name));
1084 }
1085 }
1086 }
1087 }
1088 e = (struct REnv*)e->c;
1089 }
1090 }
1091
1092 return ret;
1093}
1094
1095void
1096mrb_init_kernel(mrb_state *mrb)
1097{
1098 struct RClass *krn;
1099
1100 mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */
1101 mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */
1102 mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.2.4 */
1103 mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */
1104 mrb_define_class_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.2.7 */
1105; /* 15.3.1.2.11 */
1106 mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */
1107
1108 mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE());
1109
1110 mrb_define_method(mrb, krn, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */
1111 mrb_define_method(mrb, krn, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1));
1112 mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */
1113 mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */
1114 mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */
1115 mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */
1116 mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */
1117 mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */
1118 mrb_define_method(mrb, krn, "dup", mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */
1119 mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */
1120 mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */
1121 mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */
1122 mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */
1123 mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */
1124 mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */
1125 mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */
1126 mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */
1127 mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */
1128 mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, MRB_ARGS_REQ(1)); /* 15.3.1.3.20 */
1129 mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, MRB_ARGS_REQ(1)); /* 15.3.1.3.21 */
1130 mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, MRB_ARGS_REQ(2)); /* 15.3.1.3.22 */
1131 mrb_define_method(mrb, krn, "instance_variables", mrb_obj_instance_variables, MRB_ARGS_NONE()); /* 15.3.1.3.23 */
1132 mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */
1133 mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */
1134 mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */
1135 mrb_define_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.3.28 */
1136 mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.31 */
1137 mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */
1138 mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */
1139 mrb_define_method(mrb, krn, "private_methods", mrb_obj_private_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.36 */
1140 mrb_define_method(mrb, krn, "protected_methods", mrb_obj_protected_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.37 */
1141 mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.38 */
1142 mrb_define_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */
1143 mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */
1144 mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */
1145 mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */
1146 mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
1147 mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY());
1148 mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
1149 mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
1150
1151 mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
1152 mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
1153}
Note: See TracBrowser for help on using the repository browser.