source: EcnlProtoTool/trunk/mruby-1.3.0/src/kernel.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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