Merge pull request #6288 from dearblue/closing
[mruby.git] / src / kernel.c
blob2fd990242e98af201ce971f5a66d719482b771de
1 /*
2 ** kernel.c - Kernel module
3 **
4 ** See Copyright Notice in mruby.h
5 */
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 #include <mruby/internal.h>
17 #include <mruby/presym.h>
19 MRB_API mrb_bool
20 mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func)
22 struct RClass *c = mrb_class(mrb, obj);
23 mrb_method_t m = mrb_method_search_vm(mrb, &c, mid);
24 const struct RProc *p;
26 if (MRB_METHOD_UNDEF_P(m)) return FALSE;
27 if (MRB_METHOD_FUNC_P(m))
28 return MRB_METHOD_FUNC(m) == func;
29 p = MRB_METHOD_PROC(m);
30 if (MRB_PROC_CFUNC_P(p) && (MRB_PROC_CFUNC(p) == func))
31 return TRUE;
32 return FALSE;
35 static mrb_bool
36 mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
38 return mrb_func_basic_p(mrb, obj, MRB_SYM(to_s), mrb_any_to_s);
41 /* 15.3.1.3.17 */
43 * call-seq:
44 * obj.inspect -> string
46 * Returns a string containing a human-readable representation of
47 * <i>obj</i>. If not overridden and no instance variables, uses the
48 * <code>to_s</code> method to generate the string.
49 * <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
50 * generate the string.
52 * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
53 * Time.new.inspect #=> "2008-03-08 19:43:39 +0900"
55 MRB_API mrb_value
56 mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
58 if (mrb_object_p(obj) && mrb_obj_basic_to_s_p(mrb, obj)) {
59 return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
61 return mrb_any_to_s(mrb, obj);
64 /* 15.3.1.3.2 */
66 * call-seq:
67 * obj === other -> true or false
69 * Case Equality---For class <code>Object</code>, effectively the same
70 * as calling <code>#==</code>, but typically overridden by descendants
71 * to provide meaningful semantics in <code>case</code> statements.
73 static mrb_value
74 mrb_eqq_m(mrb_state *mrb, mrb_value self)
76 mrb_value arg = mrb_get_arg1(mrb);
78 return mrb_bool_value(mrb_equal(mrb, self, arg));
81 static mrb_value
82 mrb_cmp_m(mrb_state *mrb, mrb_value self)
84 mrb_value arg = mrb_get_arg1(mrb);
86 /* recursion check */
87 for (mrb_callinfo *ci=&mrb->c->ci[-1]; ci>=mrb->c->cibase; ci--) {
88 if (ci->mid == MRB_OPSYM(cmp) &&
89 mrb_obj_eq(mrb, self, ci->stack[0]) &&
90 mrb_obj_eq(mrb, arg, ci->stack[1])) {
91 /* recursive <=> calling returns `nil` */
92 return mrb_nil_value();
96 if (mrb_equal(mrb, self, arg))
97 return mrb_fixnum_value(0);
98 return mrb_nil_value();
101 static mrb_bool
102 inspect_recursive_p(mrb_state *mrb, mrb_value obj, int n)
104 for (mrb_callinfo *ci=&mrb->c->ci[-1-n]; ci>=mrb->c->cibase; ci--) {
105 if (ci->mid == MRB_SYM(inspect) &&
106 mrb_obj_eq(mrb, obj, ci->stack[0])) {
107 return TRUE;
110 return FALSE;
113 mrb_bool
114 mrb_inspect_recursive_p(mrb_state *mrb, mrb_value obj)
116 return inspect_recursive_p(mrb, obj, 0);
119 static mrb_value
120 mrb_obj_inspect_recursive_p(mrb_state *mrb, mrb_value obj)
122 return mrb_bool_value(inspect_recursive_p(mrb, obj, 1));
125 /* 15.3.1.3.3 */
126 /* 15.3.1.3.33 */
128 * Document-method: __id__
129 * Document-method: object_id
131 * call-seq:
132 * obj.__id__ -> int
133 * obj.object_id -> int
135 * Returns an integer identifier for <i>obj</i>. The same number will
136 * be returned on all calls to <code>id</code> for a given object, and
137 * no two active objects will share an id.
138 * <code>Object#object_id</code> is a different concept from the
139 * <code>:name</code> notation, which returns the symbol id of
140 * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
142 mrb_value
143 mrb_obj_id_m(mrb_state *mrb, mrb_value self)
145 return mrb_fixnum_value(mrb_obj_id(self));
148 static int
149 env_bidx(struct REnv *e)
151 int bidx;
153 /* use saved block arg position */
154 bidx = MRB_ENV_BIDX(e);
155 /* bidx may be useless (e.g. define_method) */
156 if (bidx >= MRB_ENV_LEN(e)) return -1;
157 return bidx;
160 /* 15.3.1.2.2 */
161 /* 15.3.1.2.5 */
162 /* 15.3.1.3.6 */
163 /* 15.3.1.3.25 */
165 * call-seq:
166 * block_given? -> true or false
167 * iterator? -> true or false
169 * Returns <code>true</code> if <code>yield</code> would execute a
170 * block in the current context. The <code>iterator?</code> form
171 * is mildly deprecated.
173 * def try
174 * if block_given?
175 * yield
176 * else
177 * "no block"
178 * end
179 * end
180 * try #=> "no block"
181 * try { "hello" } #=> "hello"
182 * try do "hello" end #=> "hello"
184 static mrb_value
185 mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
187 mrb_callinfo *ci = &mrb->c->ci[-1];
188 mrb_callinfo *cibase = mrb->c->cibase;
189 mrb_value *bp;
190 int bidx;
191 struct REnv *e = NULL;
192 const struct RProc *p;
194 if (ci <= cibase) {
195 /* toplevel does not have block */
196 return mrb_false_value();
198 p = ci->proc;
199 /* search method/class/module proc */
200 while (p) {
201 if (MRB_PROC_SCOPE_P(p)) break;
202 e = MRB_PROC_ENV(p);
203 p = p->upper;
205 if (p == NULL) return mrb_false_value();
206 if (e) {
207 bidx = env_bidx(e);
208 if (bidx < 0) return mrb_false_value();
209 bp = &e->stack[bidx];
210 goto block_given;
212 /* search ci corresponding to proc */
213 while (cibase < ci) {
214 if (ci->proc == p) break;
215 ci--;
217 if (ci == cibase) {
218 /* proc is closure */
219 if (!MRB_PROC_ENV_P(p)) return mrb_false_value();
220 e = MRB_PROC_ENV(p);
221 bidx = env_bidx(e);
222 if (bidx < 0) return mrb_false_value();
223 bp = &e->stack[bidx];
225 else if ((e = mrb_vm_ci_env(ci)) != NULL) {
226 /* top-level does not have block slot (always false) */
227 if (e->stack == mrb->c->stbase) return mrb_false_value();
228 bidx = env_bidx(e);
229 /* bidx may be useless (e.g. define_method) */
230 if (bidx < 0) return mrb_false_value();
231 bp = &e->stack[bidx];
233 else {
234 uint8_t n = ci->n == 15 ? 1 : ci->n;
235 uint8_t k = ci->nk == 15 ? 1 : ci->nk*2;
236 bidx = n + k + 1; /* self + args + kargs => bidx */
237 bp = &ci->stack[bidx];
239 block_given:
240 if (mrb_nil_p(*bp))
241 return mrb_false_value();
242 return mrb_true_value();
245 /* 15.3.1.3.7 */
247 * call-seq:
248 * obj.class -> class
250 * Returns the class of <i>obj</i>. This method must always be
251 * called with an explicit receiver, as <code>class</code> is also a
252 * reserved word in Ruby.
254 * 1.class #=> Integer
255 * self.class #=> Object
257 static mrb_value
258 mrb_obj_class_m(mrb_state *mrb, mrb_value self)
260 return mrb_obj_value(mrb_obj_class(mrb, self));
263 MRB_API mrb_value
264 mrb_obj_freeze(mrb_state *mrb, mrb_value self)
266 if (!mrb_immediate_p(self)) {
267 struct RBasic *b = mrb_basic_ptr(self);
268 if (!mrb_frozen_p(b)) {
269 MRB_SET_FROZEN_FLAG(b);
270 if (b->c->tt == MRB_TT_SCLASS) MRB_SET_FROZEN_FLAG(b->c);
273 return self;
276 static mrb_value
277 mrb_obj_frozen(mrb_state *mrb, mrb_value self)
279 return mrb_bool_value(mrb_immediate_p(self) || mrb_frozen_p(mrb_basic_ptr(self)));
282 /* 15.3.1.3.15 */
284 * call-seq:
285 * obj.hash -> int
287 * Generates a <code>Integer</code> hash value for this object. This
288 * function must have the property that <code>a.eql?(b)</code> implies
289 * <code>a.hash == b.hash</code>. The hash value is used by class
290 * <code>Hash</code>. Any hash value that exceeds the capacity of a
291 * <code>Integer</code> will be truncated before being used.
293 static mrb_value
294 mrb_obj_hash(mrb_state *mrb, mrb_value self)
296 #ifdef MRB_USE_BIGINT
297 if (mrb_bigint_p(self)) {
298 return mrb_bint_hash(mrb, self);
300 #endif
301 return mrb_int_value(mrb, mrb_obj_id(self));
304 /* 15.3.1.3.16 */
305 mrb_value
306 mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
308 mrb_value orig = mrb_get_arg1(mrb);
310 if (mrb_obj_equal(mrb, self, orig)) return self;
311 if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
312 mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
314 return self;
317 MRB_API mrb_bool
318 mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, const struct RClass* c)
320 if (mrb_obj_class(mrb, obj) == c) return TRUE;
321 return FALSE;
324 /* 15.3.1.3.19 */
326 * call-seq:
327 * obj.instance_of?(class) -> true or false
329 * Returns <code>true</code> if <i>obj</i> is an instance of the given
330 * class. See also <code>Object#kind_of?</code>.
332 static mrb_value
333 obj_is_instance_of(mrb_state *mrb, mrb_value self)
335 struct RClass *c;
337 mrb_get_args(mrb, "c", &c);
339 return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, c));
342 /* 15.3.1.3.24 */
343 /* 15.3.1.3.26 */
345 * call-seq:
346 * obj.is_a?(class) -> true or false
347 * obj.kind_of?(class) -> true or false
349 * Returns <code>true</code> if <i>class</i> is the class of
350 * <i>obj</i>, or if <i>class</i> is one of the superclasses of
351 * <i>obj</i> or modules included in <i>obj</i>.
353 * module M; end
354 * class A
355 * include M
356 * end
357 * class B < A; end
358 * class C < B; end
359 * b = B.new
360 * b.instance_of? A #=> false
361 * b.instance_of? B #=> true
362 * b.instance_of? C #=> false
363 * b.instance_of? M #=> false
364 * b.kind_of? A #=> true
365 * b.kind_of? B #=> true
366 * b.kind_of? C #=> false
367 * b.kind_of? M #=> true
369 static mrb_value
370 mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
372 struct RClass *c;
374 mrb_get_args(mrb, "c", &c);
376 return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c));
379 /* 15.3.1.3.32 */
381 * call_seq:
382 * nil.nil? -> true
383 * <anything_else>.nil? -> false
385 * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
387 static mrb_value
388 mrb_false(mrb_state *mrb, mrb_value self)
390 return mrb_false_value();
393 /* 15.3.1.2.12 */
394 /* 15.3.1.3.40 */
396 * call-seq:
397 * raise
398 * raise(string)
399 * raise(exception [, string])
401 * With no arguments, raises a <code>RuntimeError</code>
402 * With a single +String+ argument, raises a
403 * +RuntimeError+ with the string as a message. Otherwise,
404 * the first parameter should be the name of an +Exception+
405 * class (or an object that returns an +Exception+ object when sent
406 * an +exception+ message). The optional second parameter sets the
407 * message associated with the exception, and the third parameter is an
408 * array of callback information. Exceptions are caught by the
409 * +rescue+ clause of <code>begin...end</code> blocks.
411 * raise "Failed to create socket"
412 * raise ArgumentError, "No parameters", caller
414 mrb_value
415 mrb_f_raise(mrb_state *mrb, mrb_value self)
417 mrb_value exc, mesg;
418 mrb_int argc;
420 argc = mrb_get_args(mrb, "|oo", &exc, &mesg);
421 mrb->c->ci->mid = 0;
422 switch (argc) {
423 case 0:
424 mrb_raise(mrb, E_RUNTIME_ERROR, "");
425 break;
426 case 1:
427 if (mrb_string_p(exc)) {
428 mesg = exc;
429 exc = mrb_obj_value(E_RUNTIME_ERROR);
431 else {
432 mesg = mrb_nil_value();
434 /* fall through */
435 default:
436 exc = mrb_make_exception(mrb, exc, mesg);
437 mrb_exc_raise(mrb, exc);
438 break;
440 return mrb_nil_value(); /* not reached */
443 /* 15.3.1.3.41 */
445 * call-seq:
446 * obj.remove_instance_variable(symbol) -> obj
448 * Removes the named instance variable from <i>obj</i>, returning that
449 * variable's value.
451 * class Dummy
452 * attr_reader :var
453 * def initialize
454 * @var = 99
455 * end
456 * def remove
457 * remove_instance_variable(:@var)
458 * end
459 * end
460 * d = Dummy.new
461 * d.var #=> 99
462 * d.remove #=> 99
463 * d.var #=> nil
465 static mrb_value
466 mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
468 mrb_sym sym;
469 mrb_value val;
471 mrb_get_args(mrb, "n", &sym);
472 mrb_iv_name_sym_check(mrb, sym);
473 val = mrb_iv_remove(mrb, self, sym);
474 if (mrb_undef_p(val)) {
475 mrb_name_error(mrb, sym, "instance variable %n not defined", sym);
477 return val;
480 /* 15.3.1.3.43 */
482 * call-seq:
483 * obj.respond_to?(symbol, include_private=false) -> true or false
485 * Returns +true+ if _obj_ responds to the given
486 * method. Private methods are included in the search only if the
487 * optional second parameter evaluates to +true+.
489 * If the method is not implemented,
490 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
491 * false is returned.
493 * If the method is not defined, <code>respond_to_missing?</code>
494 * method is called and the result is returned.
496 static mrb_value
497 obj_respond_to(mrb_state *mrb, mrb_value self)
499 mrb_sym id;
500 mrb_bool priv = FALSE, respond_to_p;
502 mrb_get_args(mrb, "n|b", &id, &priv);
503 respond_to_p = mrb_respond_to(mrb, self, id);
504 if (!respond_to_p) {
505 mrb_sym rtm_id = MRB_SYM_Q(respond_to_missing);
506 if (!mrb_func_basic_p(mrb, self, rtm_id, mrb_false)) {
507 mrb_value v;
508 v = mrb_funcall_id(mrb, self, rtm_id, 2, mrb_symbol_value(id), mrb_bool_value(priv));
509 return mrb_bool_value(mrb_bool(v));
512 return mrb_bool_value(respond_to_p);
515 static mrb_value
516 mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
518 mrb_value v = mrb_get_arg1(mrb);
519 mrb_int i, len;
520 mrb_sym eqq = MRB_OPSYM(eqq);
521 mrb_value ary;
523 mrb->c->ci->mid = 0;
524 if (mrb_array_p(self)) {
525 ary = self;
527 else if (mrb_nil_p(self)) {
528 return mrb_false_value();
530 else if (!mrb_respond_to(mrb, self, MRB_SYM(to_a))) {
531 mrb_value c = mrb_funcall_argv(mrb, self, eqq, 1, &v);
532 if (mrb_test(c)) return mrb_true_value();
533 return mrb_false_value();
535 else {
536 ary = mrb_funcall_argv(mrb, self, MRB_SYM(to_a), 0, NULL);
537 if (mrb_nil_p(ary)) {
538 return mrb_funcall_argv(mrb, self, eqq, 1, &v);
540 mrb_ensure_array_type(mrb, ary);
542 len = RARRAY_LEN(ary);
543 for (i=0; i<len; i++) {
544 mrb_value c = mrb_funcall_argv(mrb, RARRAY_PTR(ary)[i], eqq, 1, &v);
545 if (mrb_test(c)) return mrb_true_value();
547 return mrb_false_value();
550 void
551 mrb_init_kernel(mrb_state *mrb)
553 struct RClass *krn;
555 mrb->kernel_module = krn = mrb_define_module_id(mrb, MRB_SYM(Kernel)); /* 15.3.1 */
556 mrb_define_class_method_id(mrb, krn, MRB_SYM_Q(block_given), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */
557 mrb_define_class_method_id(mrb, krn, MRB_SYM_Q(iterator), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */
558 mrb_define_class_method_id(mrb, krn, MRB_SYM(raise), mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */
560 mrb_define_method_id(mrb, krn, MRB_OPSYM(eqq), mrb_eqq_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */
561 mrb_define_method_id(mrb, krn, MRB_OPSYM(cmp), mrb_cmp_m, MRB_ARGS_REQ(1));
562 mrb_define_method_id(mrb, krn, MRB_SYM_Q(block_given), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */
563 mrb_define_method_id(mrb, krn, MRB_SYM(class), mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */
564 mrb_define_method_id(mrb, krn, MRB_SYM(clone), mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */
565 mrb_define_method_id(mrb, krn, MRB_SYM(dup), mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */
566 mrb_define_method_id(mrb, krn, MRB_SYM_Q(eql), mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */
567 mrb_define_method_id(mrb, krn, MRB_SYM(freeze), mrb_obj_freeze, MRB_ARGS_NONE());
568 mrb_define_method_id(mrb, krn, MRB_SYM_Q(frozen), mrb_obj_frozen, MRB_ARGS_NONE());
569 mrb_define_method_id(mrb, krn, MRB_SYM(hash), mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */
570 mrb_define_method_id(mrb, krn, MRB_SYM(initialize_copy), mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */
571 mrb_define_method_id(mrb, krn, MRB_SYM(inspect), mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */
572 mrb_define_method_id(mrb, krn, MRB_SYM_Q(instance_of), obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */
574 mrb_define_method_id(mrb, krn, MRB_SYM_Q(is_a), mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */
575 mrb_define_method_id(mrb, krn, MRB_SYM_Q(iterator), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */
576 mrb_define_method_id(mrb, krn, MRB_SYM_Q(kind_of), mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */
577 mrb_define_method_id(mrb, krn, MRB_SYM_Q(nil), mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */
578 mrb_define_method_id(mrb, krn, MRB_SYM(object_id), mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */
579 mrb_define_method_id(mrb, krn, MRB_SYM(raise), mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */
580 mrb_define_method_id(mrb, krn, MRB_SYM(remove_instance_variable), mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */
581 mrb_define_method_id(mrb, krn, MRB_SYM_Q(respond_to), obj_respond_to, MRB_ARGS_ARG(1,1)); /* 15.3.1.3.43 */
582 mrb_define_method_id(mrb, krn, MRB_SYM(to_s), mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
583 mrb_define_method_id(mrb, krn, MRB_SYM(__case_eqq), mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
584 mrb_define_method_id(mrb, krn, MRB_SYM(__to_int), mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */
585 mrb_define_method_id(mrb, krn, MRB_SYM_Q(respond_to_missing), mrb_false, MRB_ARGS_ARG(1,1));
586 mrb_define_method_id(mrb, krn, MRB_SYM_Q(__inspect_recursive), mrb_obj_inspect_recursive_p, MRB_ARGS_NONE());
588 mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);