Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 1276 lines (1105 sloc) 25.968 kB
511dc44 initial import
Laurent Sansonetti authored
1 /**********************************************************************
2
3 eval.c -
4
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
5 $Author: nobu $
511dc44 initial import
Laurent Sansonetti authored
6 created at: Thu Jun 10 14:22:17 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12 **********************************************************************/
13
14 #include "eval_intern.h"
15
16 VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
17 VALUE rb_binding_new(void);
18 NORETURN(void rb_raise_jump(VALUE));
511dc44 initial import
Laurent Sansonetti authored
19
20 VALUE rb_f_block_given_p(void);
21
22 ID rb_frame_callee(void);
23 VALUE rb_eLocalJumpError;
24 VALUE rb_eSysStackError;
25 VALUE sysstack_error;
26
27 static VALUE exception_error;
28
29 #include "eval_error.c"
30 #include "eval_safe.c"
31 #include "eval_jump.c"
32
33 /* initialize ruby */
34
35 #if defined(__APPLE__)
36 #define environ (*_NSGetEnviron())
37 #elif !defined(_WIN32) && !defined(__MACOS__) || defined(_WIN32_WCE)
38 extern char **environ;
39 #endif
40 char **rb_origenviron;
41
42 void rb_clear_trace_func(void);
43 void rb_thread_stop_timer_thread(void);
44
45 void rb_call_inits(void);
46 #if WITH_OBJC
47 # define Init_stack(x)
48 # define Init_heap(x)
49 #else
50 void Init_stack(VALUE *);
51 void Init_heap(void);
52 #endif
53 void Init_ext(void);
54 void Init_PreGC(void);
55 void Init_BareVM(void);
56
ec1f435 wip
Laurent Sansonetti authored
57 #if WITH_OBJC
58 bool ruby_dlog_enabled = false;
59 #endif
60
511dc44 initial import
Laurent Sansonetti authored
61 void
62 ruby_init(void)
63 {
64 static int initialized = 0;
65 int state;
66
67 if (initialized)
68 return;
69 initialized = 1;
70
71 #ifdef __MACOS__
72 rb_origenviron = 0;
73 #else
74 rb_origenviron = environ;
75 #endif
76
ec1f435 wip
Laurent Sansonetti authored
77 #if WITH_OBJC
78 char *s = getenv("MACRUBY_DEBUG");
79 ruby_dlog_enabled = !(s == NULL || *s == '0');
80 #endif
81
511dc44 initial import
Laurent Sansonetti authored
82 Init_stack((void *)&state);
83 Init_PreGC();
84 Init_BareVM();
85 Init_heap();
86
87 PUSH_TAG();
88 if ((state = EXEC_TAG()) == 0) {
89 rb_call_inits();
90
91 #ifdef __MACOS__
92 _macruby_init();
93 #elif defined(__VMS)
94 _vmsruby_init();
95 #endif
96
97 ruby_prog_init();
98 ALLOW_INTS;
99 }
100 POP_TAG();
101
102 if (state) {
103 error_print();
104 exit(EXIT_FAILURE);
105 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
106 GET_VM()->running = 1;
511dc44 initial import
Laurent Sansonetti authored
107 }
108
109 extern void rb_clear_trace_func(void);
110
111 void *
112 ruby_options(int argc, char **argv)
113 {
114 int state;
115 void *tree = 0;
116
117 Init_stack((void *)&state);
118 PUSH_TAG();
119 if ((state = EXEC_TAG()) == 0) {
120 SAVE_ROOT_JMPBUF(GET_THREAD(), tree = ruby_process_options(argc, argv));
121 }
122 else {
123 rb_clear_trace_func();
124 state = error_handle(state);
125 tree = (void *)INT2FIX(state);
126 }
127 POP_TAG();
128 return tree;
129 }
130
131 static void
132 ruby_finalize_0(void)
133 {
134 rb_clear_trace_func();
135 PUSH_TAG();
136 if (EXEC_TAG() == 0) {
137 rb_trap_exit();
138 }
139 POP_TAG();
140 rb_exec_end_proc();
141 }
142
143 static void
144 ruby_finalize_1(void)
145 {
146 ruby_sig_finalize();
147 GET_THREAD()->errinfo = Qnil;
148 rb_gc_call_finalizer_at_exit();
149 }
150
151 void
152 ruby_finalize(void)
153 {
154 ruby_finalize_0();
155 ruby_finalize_1();
156 }
157
158 void rb_thread_stop_timer_thread(void);
159
160 int
161 ruby_cleanup(int ex)
162 {
163 int state;
164 volatile VALUE errs[2];
165 rb_thread_t *th = GET_THREAD();
166 int nerr;
167
168 errs[1] = th->errinfo;
169 th->safe_level = 0;
170 Init_stack((void *)&state);
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
171
172 PUSH_TAG();
173 if ((state = EXEC_TAG()) == 0) {
174 SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
175 }
176 POP_TAG();
177
511dc44 initial import
Laurent Sansonetti authored
178 errs[0] = th->errinfo;
179 PUSH_TAG();
180 if ((state = EXEC_TAG()) == 0) {
181 SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
182 }
183 else if (ex == 0) {
184 ex = state;
185 }
186 th->errinfo = errs[1];
187 ex = error_handle(ex);
188 ruby_finalize_1();
189 POP_TAG();
190 rb_thread_stop_timer_thread();
191
192 for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) {
193 VALUE err = errs[nerr];
194
195 if (!RTEST(err)) continue;
196
197 /* th->errinfo contains a NODE while break'ing */
198 if (TYPE(err) == T_NODE) continue;
199
200 if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
201 return sysexit_status(err);
202 }
203 else if (rb_obj_is_kind_of(err, rb_eSignal)) {
204 VALUE sig = rb_iv_get(err, "signo");
205 ruby_default_signal(NUM2INT(sig));
206 }
207 else if (ex == 0) {
208 ex = 1;
209 }
210 }
211
212 #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
213 switch (ex) {
214 #if EXIT_SUCCESS != 0
215 case 0: return EXIT_SUCCESS;
216 #endif
217 #if EXIT_FAILURE != 1
218 case 1: return EXIT_FAILURE;
219 #endif
220 }
221 #endif
222
223 return ex;
224 }
225
226 int
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
227 ruby_exec_node(void *n, const char *file)
511dc44 initial import
Laurent Sansonetti authored
228 {
229 int state;
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
230 VALUE iseq = (VALUE)n;
511dc44 initial import
Laurent Sansonetti authored
231 rb_thread_t *th = GET_THREAD();
232
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
233 if (!n) return 0;
511dc44 initial import
Laurent Sansonetti authored
234
235 PUSH_TAG();
236 if ((state = EXEC_TAG()) == 0) {
237 SAVE_ROOT_JMPBUF(th, {
238 th->base_block = 0;
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
239 rb_iseq_eval(iseq);
511dc44 initial import
Laurent Sansonetti authored
240 });
241 }
242 POP_TAG();
243 return state;
244 }
245
246 void
247 ruby_stop(int ex)
248 {
249 exit(ruby_cleanup(ex));
250 }
251
252 int
253 ruby_run_node(void *n)
254 {
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
255 VALUE v = (VALUE)n;
511dc44 initial import
Laurent Sansonetti authored
256
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
257 switch (v) {
511dc44 initial import
Laurent Sansonetti authored
258 case Qtrue: return EXIT_SUCCESS;
259 case Qfalse: return EXIT_FAILURE;
260 }
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
261 if (FIXNUM_P(v)) {
262 return FIX2INT(v);
511dc44 initial import
Laurent Sansonetti authored
263 }
264 Init_stack((void *)&n);
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
265 return ruby_cleanup(ruby_exec_node(n, 0));
511dc44 initial import
Laurent Sansonetti authored
266 }
267
268 /*
269 * call-seq:
270 * Module.nesting => array
271 *
272 * Returns the list of +Modules+ nested at the point of call.
273 *
274 * module M1
275 * module M2
276 * $a = Module.nesting
277 * end
278 * end
279 * $a #=> [M1::M2, M1]
280 * $a[0].name #=> "M1::M2"
281 */
282
283 static VALUE
284 rb_mod_nesting(void)
285 {
286 VALUE ary = rb_ary_new();
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
287 const NODE *cref = vm_cref();
511dc44 initial import
Laurent Sansonetti authored
288
289 while (cref && cref->nd_next) {
290 VALUE klass = cref->nd_clss;
291 if (!NIL_P(klass)) {
292 rb_ary_push(ary, klass);
293 }
294 cref = cref->nd_next;
295 }
296 return ary;
297 }
298
299 /*
300 * call-seq:
301 * Module.constants => array
302 *
303 * Returns an array of the names of all constants defined in the
304 * system. This list includes the names of all modules and classes.
305 *
306 * p Module.constants.sort[1..5]
307 *
308 * <em>produces:</em>
309 *
310 * ["ARGV", "ArgumentError", "Array", "Bignum", "Binding"]
311 */
312
313 static VALUE
314 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
315 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
316 const NODE *cref = vm_cref();
511dc44 initial import
Laurent Sansonetti authored
317 VALUE klass;
318 VALUE cbase = 0;
319 void *data = 0;
320
321 if (argc > 0) {
322 return rb_mod_constants(argc, argv, rb_cModule);
323 }
324
325 while (cref) {
326 klass = cref->nd_clss;
327 if (!NIL_P(klass)) {
328 data = rb_mod_const_at(cref->nd_clss, data);
329 if (!cbase) {
330 cbase = klass;
331 }
332 }
333 cref = cref->nd_next;
334 }
335
336 if (cbase) {
337 data = rb_mod_const_of(cbase, data);
338 }
339 return rb_const_list(data);
340 }
341
342 void
343 rb_frozen_class_p(VALUE klass)
344 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
345 const char *desc = "something(?!)";
511dc44 initial import
Laurent Sansonetti authored
346
347 if (OBJ_FROZEN(klass)) {
b8396fa new dispatcher, work still in progress
Laurent Sansonetti authored
348 if (RCLASS_SINGLETON(klass))
511dc44 initial import
Laurent Sansonetti authored
349 desc = "object";
350 else {
351 switch (TYPE(klass)) {
352 case T_MODULE:
353 case T_ICLASS:
354 desc = "module";
355 break;
356 case T_CLASS:
357 desc = "class";
358 break;
359 }
360 }
361 rb_error_frozen(desc);
362 }
363 }
364
365 NORETURN(static void rb_longjmp(int, VALUE));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
366 VALUE rb_make_backtrace(void);
511dc44 initial import
Laurent Sansonetti authored
367
368 static void
369 rb_longjmp(int tag, VALUE mesg)
370 {
371 VALUE at;
372 VALUE e;
373 rb_thread_t *th = GET_THREAD();
374 const char *file;
375 int line = 0;
376
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
377 if (rb_thread_set_raised(th)) {
511dc44 initial import
Laurent Sansonetti authored
378 th->errinfo = exception_error;
379 JUMP_TAG(TAG_FATAL);
380 }
381
382 if (NIL_P(mesg))
383 mesg = th->errinfo;
384 if (NIL_P(mesg)) {
385 mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
386 }
387
388 file = rb_sourcefile();
389 if (file) line = rb_sourceline();
390 if (file && !NIL_P(mesg)) {
391 at = get_backtrace(mesg);
392 if (NIL_P(at)) {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
393 at = rb_make_backtrace();
511dc44 initial import
Laurent Sansonetti authored
394 set_backtrace(mesg, at);
395 }
396 }
397 if (!NIL_P(mesg)) {
398 th->errinfo = mesg;
399 }
400
401 if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) &&
402 !rb_obj_is_kind_of(e, rb_eSystemExit)) {
403 int status;
404
405 PUSH_TAG();
406 if ((status = EXEC_TAG()) == 0) {
407 RB_GC_GUARD(e) = rb_obj_as_string(e);
408 if (file) {
409 warn_printf("Exception `%s' at %s:%d - %s\n",
410 rb_obj_classname(th->errinfo),
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
411 file, line, RSTRING_PTR(e));
511dc44 initial import
Laurent Sansonetti authored
412 }
413 else {
414 warn_printf("Exception `%s' - %s\n",
415 rb_obj_classname(th->errinfo),
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
416 RSTRING_PTR(e));
511dc44 initial import
Laurent Sansonetti authored
417 }
418 }
419 POP_TAG();
420 if (status == TAG_FATAL && th->errinfo == exception_error) {
421 th->errinfo = mesg;
422 }
423 else if (status) {
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
424 rb_thread_reset_raised(th);
511dc44 initial import
Laurent Sansonetti authored
425 JUMP_TAG(status);
426 }
427 }
428
429 rb_trap_restore_mask();
430
431 if (tag != TAG_FATAL) {
432 EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self,
433 0 /* TODO: id */, 0 /* TODO: klass */);
434 }
435
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
436 rb_thread_raised_clear(th);
511dc44 initial import
Laurent Sansonetti authored
437 JUMP_TAG(tag);
438 }
439
440 void
441 rb_exc_raise(VALUE mesg)
442 {
443 rb_longjmp(TAG_RAISE, mesg);
444 }
445
446 void
447 rb_exc_fatal(VALUE mesg)
448 {
449 rb_longjmp(TAG_FATAL, mesg);
450 }
451
452 void
453 rb_interrupt(void)
454 {
455 static const char fmt[1] = {'\0'};
456 rb_raise(rb_eInterrupt, fmt);
457 }
458
459 static VALUE get_errinfo(void);
460
461 /*
462 * call-seq:
463 * raise
464 * raise(string)
465 * raise(exception [, string [, array]])
466 * fail
467 * fail(string)
468 * fail(exception [, string [, array]])
469 *
470 * With no arguments, raises the exception in <code>$!</code> or raises
471 * a <code>RuntimeError</code> if <code>$!</code> is +nil+.
472 * With a single +String+ argument, raises a
473 * +RuntimeError+ with the string as a message. Otherwise,
474 * the first parameter should be the name of an +Exception+
475 * class (or an object that returns an +Exception+ object when sent
476 * an +exception+ message). The optional second parameter sets the
477 * message associated with the exception, and the third parameter is an
478 * array of callback information. Exceptions are caught by the
479 * +rescue+ clause of <code>begin...end</code> blocks.
480 *
481 * raise "Failed to create socket"
482 * raise ArgumentError, "No parameters", caller
483 */
484
485 static VALUE
486 rb_f_raise(int argc, VALUE *argv)
487 {
488 VALUE err;
489 if (argc == 0) {
490 err = get_errinfo();
491 if (!NIL_P(err)) {
492 argc = 1;
493 argv = &err;
494 }
495 }
496 rb_raise_jump(rb_make_exception(argc, argv));
497 return Qnil; /* not reached */
498 }
499
500 VALUE
501 rb_make_exception(int argc, VALUE *argv)
502 {
503 VALUE mesg;
504 ID exception;
505 int n;
506
507 mesg = Qnil;
508 switch (argc) {
509 case 0:
510 mesg = Qnil;
511 break;
512 case 1:
513 if (NIL_P(argv[0]))
514 break;
515 if (TYPE(argv[0]) == T_STRING) {
516 mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
517 break;
518 }
519 n = 0;
520 goto exception_call;
521
522 case 2:
523 case 3:
524 n = 1;
525 exception_call:
526 exception = rb_intern("exception");
527 if (!rb_respond_to(argv[0], exception)) {
528 rb_raise(rb_eTypeError, "exception class/object expected");
529 }
530 mesg = rb_funcall(argv[0], exception, n, argv[1]);
531 break;
532 default:
533 rb_raise(rb_eArgError, "wrong number of arguments");
534 break;
535 }
536 if (argc > 0) {
537 if (!rb_obj_is_kind_of(mesg, rb_eException))
538 rb_raise(rb_eTypeError, "exception object expected");
539 if (argc > 2)
540 set_backtrace(mesg, argv[2]);
541 }
542
543 return mesg;
544 }
545
546 void
547 rb_raise_jump(VALUE mesg)
548 {
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
549 rb_thread_t *th = GET_THREAD();
550 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
511dc44 initial import
Laurent Sansonetti authored
551 /* TODO: fix me */
552 rb_longjmp(TAG_RAISE, mesg);
553 }
554
555 void
556 rb_jump_tag(int tag)
557 {
558 JUMP_TAG(tag);
559 }
560
561 int
562 rb_block_given_p(void)
563 {
564 rb_thread_t *th = GET_THREAD();
565 if (GC_GUARDED_PTR_REF(th->cfp->lfp[0])) {
566 return Qtrue;
567 }
568 else {
569 return Qfalse;
570 }
571 }
572
573 int
574 rb_iterator_p()
575 {
576 return rb_block_given_p();
577 }
578
579 /*
580 * call-seq:
581 * block_given? => true or false
582 * iterator? => true or false
583 *
584 * Returns <code>true</code> if <code>yield</code> would execute a
585 * block in the current context. The <code>iterator?</code> form
586 * is mildly deprecated.
587 *
588 * def try
589 * if block_given?
590 * yield
591 * else
592 * "no block"
593 * end
594 * end
595 * try #=> "no block"
596 * try { "hello" } #=> "hello"
597 * try do "hello" end #=> "hello"
598 */
599
600
601 VALUE
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
602 rb_f_block_given_p(void)
511dc44 initial import
Laurent Sansonetti authored
603 {
604 rb_thread_t *th = GET_THREAD();
605 rb_control_frame_t *cfp = th->cfp;
606 cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
607
511dc44 initial import
Laurent Sansonetti authored
608 if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
609 return Qtrue;
610 }
611 else {
612 return Qfalse;
613 }
614 }
615
616 VALUE rb_eThreadError;
617
618 void
619 rb_need_block()
620 {
621 if (!rb_block_given_p()) {
622 vm_localjump_error("no block given", Qnil, 0);
623 }
624 }
625
626 VALUE
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
627 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
628 VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
511dc44 initial import
Laurent Sansonetti authored
629 {
630 int state;
631 rb_thread_t *th = GET_THREAD();
632 rb_control_frame_t *cfp = th->cfp;
633 volatile VALUE result;
634 volatile VALUE e_info = th->errinfo;
635 va_list args;
636
637 PUSH_TAG();
638 if ((state = EXEC_TAG()) == 0) {
639 retry_entry:
640 result = (*b_proc) (data1);
641 }
642 else {
643 th->cfp = cfp; /* restore */
644
645 if (state == TAG_RAISE) {
646 int handle = Qfalse;
647 VALUE eclass;
648
649 va_init_list(args, data2);
650 while ((eclass = va_arg(args, VALUE)) != 0) {
651 if (rb_obj_is_kind_of(th->errinfo, eclass)) {
652 handle = Qtrue;
653 break;
654 }
655 }
656 va_end(args);
657
658 if (handle) {
659 if (r_proc) {
660 PUSH_TAG();
661 if ((state = EXEC_TAG()) == 0) {
662 result = (*r_proc) (data2, th->errinfo);
663 }
664 POP_TAG();
665 if (state == TAG_RETRY) {
666 state = 0;
667 th->errinfo = Qnil;
668 goto retry_entry;
669 }
670 }
671 else {
672 result = Qnil;
673 state = 0;
674 }
675 if (state == 0) {
676 th->errinfo = e_info;
677 }
678 }
679 }
680 }
681 POP_TAG();
682 if (state)
683 JUMP_TAG(state);
684
685 return result;
686 }
687
688 VALUE
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
689 rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
690 VALUE (* r_proc)(ANYARGS), VALUE data2)
511dc44 initial import
Laurent Sansonetti authored
691 {
692 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
693 (VALUE)0);
694 }
695
696 VALUE
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
697 rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
511dc44 initial import
Laurent Sansonetti authored
698 {
699 VALUE result = Qnil; /* OK */
700 int status;
701 rb_thread_t *th = GET_THREAD();
702 rb_control_frame_t *cfp = th->cfp;
703 struct rb_vm_trap_tag trap_tag;
704 rb_jmpbuf_t org_jmpbuf;
705
706 trap_tag.prev = th->trap_tag;
707
708 PUSH_TAG();
709 th->trap_tag = &trap_tag;
710 MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1);
711 if ((status = EXEC_TAG()) == 0) {
712 SAVE_ROOT_JMPBUF(th, result = (*proc) (data));
713 }
714 MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1);
715 th->trap_tag = trap_tag.prev;
716 POP_TAG();
717
718 if (state) {
719 *state = status;
720 }
721 if (status != 0) {
722 th->cfp = cfp;
723 return Qnil;
724 }
725
726 return result;
727 }
728
729 VALUE
730 rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
731 {
732 int state;
733 volatile VALUE result = Qnil;
734
735 PUSH_TAG();
736 if ((state = EXEC_TAG()) == 0) {
737 result = (*b_proc) (data1);
738 }
739 POP_TAG();
740 /* TODO: fix me */
741 /* retval = prot_tag ? prot_tag->retval : Qnil; */ /* save retval */
742 (*e_proc) (data2);
743 if (state)
744 JUMP_TAG(state);
745 return result;
746 }
747
748 VALUE
749 rb_with_disable_interrupt(VALUE (*proc)(ANYARGS), VALUE data)
750 {
751 VALUE result = Qnil; /* OK */
752 int status;
753
754 DEFER_INTS;
755 {
756 int thr_critical = rb_thread_critical;
757
758 rb_thread_critical = Qtrue;
759 PUSH_TAG();
760 if ((status = EXEC_TAG()) == 0) {
761 result = (*proc) (data);
762 }
763 POP_TAG();
764 rb_thread_critical = thr_critical;
765 }
766 ENABLE_INTS;
767 if (status)
768 JUMP_TAG(status);
769
770 return result;
771 }
772
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
773 static ID
774 frame_func_id(rb_control_frame_t *cfp)
511dc44 initial import
Laurent Sansonetti authored
775 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
776 rb_iseq_t *iseq = cfp->iseq;
777 if (!iseq) {
778 return cfp->method_id;
779 }
780 while (iseq) {
781 if (RUBY_VM_IFUNC_P(iseq)) {
782 return rb_intern("<ifunc>");
783 }
784 if (iseq->defined_method_id) {
785 return iseq->defined_method_id;
786 }
787 if (iseq->local_iseq == iseq) {
788 break;
789 }
790 iseq = iseq->parent_iseq;
511dc44 initial import
Laurent Sansonetti authored
791 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
792 return 0;
511dc44 initial import
Laurent Sansonetti authored
793 }
794
795 ID
796 rb_frame_this_func(void)
797 {
798 return frame_func_id(GET_THREAD()->cfp);
799 }
800
801 ID
802 rb_frame_callee(void)
803 {
804 rb_thread_t *th = GET_THREAD();
805 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
806 /* check if prev_cfp can be accessible */
807 if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
808 return 0;
809 }
810 return frame_func_id(prev_cfp);
811 }
812
813 void
814 rb_frame_pop(void)
815 {
816 rb_thread_t *th = GET_THREAD();
817 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
818 }
819
820 /*
821 * call-seq:
822 * append_features(mod) => mod
823 *
824 * When this module is included in another, Ruby calls
825 * <code>append_features</code> in this module, passing it the
826 * receiving module in _mod_. Ruby's default implementation is
827 * to add the constants, methods, and module variables of this module
828 * to _mod_ if this module has not already been added to
829 * _mod_ or one of its ancestors. See also <code>Module#include</code>.
830 */
831
832 static VALUE
833 rb_mod_append_features(VALUE module, VALUE include)
834 {
835 switch (TYPE(include)) {
836 case T_CLASS:
837 case T_MODULE:
838 break;
839 default:
840 Check_Type(include, T_CLASS);
841 break;
842 }
843 rb_include_module(include, module);
844
845 return module;
846 }
847
848 /*
849 * call-seq:
850 * include(module, ...) => self
851 *
852 * Invokes <code>Module.append_features</code> on each parameter in turn.
853 */
854
855 static VALUE
856 rb_mod_include(int argc, VALUE *argv, VALUE module)
857 {
858 int i;
859
860 for (i = 0; i < argc; i++)
861 Check_Type(argv[i], T_MODULE);
862 while (argc--) {
863 rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
864 rb_funcall(argv[argc], rb_intern("included"), 1, module);
865 }
866 return module;
867 }
868
e18c29a wip
Laurent Sansonetti authored
869 VALUE
511dc44 initial import
Laurent Sansonetti authored
870 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
871 {
872 PASS_PASSED_BLOCK();
e18c29a wip
Laurent Sansonetti authored
873 return rb_funcall2(obj, idInitialize, argc, argv);
511dc44 initial import
Laurent Sansonetti authored
874 }
875
876 void
877 rb_extend_object(VALUE obj, VALUE module)
878 {
879 rb_include_module(rb_singleton_class(obj), module);
880 }
881
882 /*
883 * call-seq:
884 * extend_object(obj) => obj
885 *
886 * Extends the specified object by adding this module's constants and
887 * methods (which are added as singleton methods). This is the callback
888 * method used by <code>Object#extend</code>.
889 *
890 * module Picky
891 * def Picky.extend_object(o)
892 * if String === o
893 * puts "Can't add Picky to a String"
894 * else
895 * puts "Picky added to #{o.class}"
896 * super
897 * end
898 * end
899 * end
900 * (s = Array.new).extend Picky # Call Object.extend
901 * (s = "quick brown fox").extend Picky
902 *
903 * <em>produces:</em>
904 *
905 * Picky added to Array
906 * Can't add Picky to a String
907 */
908
909 static VALUE
910 rb_mod_extend_object(VALUE mod, VALUE obj)
911 {
912 rb_extend_object(obj, mod);
913 return obj;
914 }
915
916 /*
917 * call-seq:
918 * obj.extend(module, ...) => obj
919 *
920 * Adds to _obj_ the instance methods from each module given as a
921 * parameter.
922 *
923 * module Mod
924 * def hello
925 * "Hello from Mod.\n"
926 * end
927 * end
928 *
929 * class Klass
930 * def hello
931 * "Hello from Klass.\n"
932 * end
933 * end
934 *
935 * k = Klass.new
936 * k.hello #=> "Hello from Klass.\n"
937 * k.extend(Mod) #=> #<Klass:0x401b3bc8>
938 * k.hello #=> "Hello from Mod.\n"
939 */
940
941 static VALUE
942 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
943 {
944 int i;
945
946 if (argc == 0) {
947 rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
948 }
949 for (i = 0; i < argc; i++)
950 Check_Type(argv[i], T_MODULE);
951 while (argc--) {
952 rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
953 rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
954 }
955 return obj;
956 }
957
958 /*
959 * call-seq:
960 * include(module, ...) => self
961 *
962 * Invokes <code>Module.append_features</code>
963 * on each parameter in turn. Effectively adds the methods and constants
964 * in each module to the receiver.
965 */
966
967 static VALUE
968 top_include(int argc, VALUE *argv, VALUE self)
969 {
970 rb_thread_t *th = GET_THREAD();
971
972 rb_secure(4);
973 if (th->top_wrapper) {
974 rb_warning
975 ("main#include in the wrapped load is effective only in wrapper module");
976 return rb_mod_include(argc, argv, th->top_wrapper);
977 }
978 return rb_mod_include(argc, argv, rb_cObject);
979 }
980
981 VALUE rb_f_trace_var();
982 VALUE rb_f_untrace_var();
983
984 static VALUE *
985 errinfo_place(void)
986 {
987 rb_thread_t *th = GET_THREAD();
988 rb_control_frame_t *cfp = th->cfp;
989 rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
990
991 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
992 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
993 if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
994 return &cfp->dfp[-2];
511dc44 initial import
Laurent Sansonetti authored
995 }
996 else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
997 TYPE(cfp->dfp[-2]) != T_NODE &&
998 !FIXNUM_P(cfp->dfp[-2])) {
999 return &cfp->dfp[-2];
511dc44 initial import
Laurent Sansonetti authored
1000 }
1001 }
1002 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1003 }
1004 return 0;
1005 }
1006
1007 static VALUE
1008 get_errinfo(void)
1009 {
1010 VALUE *ptr = errinfo_place();
1011 if (ptr) {
1012 return *ptr;
1013 }
1014 else {
1015 return Qnil;
1016 }
1017 }
1018
1019 static VALUE
1020 errinfo_getter(ID id)
1021 {
1022 return get_errinfo();
1023 }
1024
1025 #if 0
1026 static void
1027 errinfo_setter(VALUE val, ID id, VALUE *var)
1028 {
1029 if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
1030 rb_raise(rb_eTypeError, "assigning non-exception to $!");
1031 }
1032 else {
1033 VALUE *ptr = errinfo_place();
1034 if (ptr) {
1035 *ptr = val;
1036 }
1037 else {
1038 rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
1039 }
1040 }
1041 }
1042 #endif
1043
1044 VALUE
1045 rb_errinfo(void)
1046 {
1047 rb_thread_t *th = GET_THREAD();
1048 return th->errinfo;
1049 }
1050
1051 void
1052 rb_set_errinfo(VALUE err)
1053 {
1054 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
1055 rb_raise(rb_eTypeError, "assigning non-exception to $!");
1056 }
1057 GET_THREAD()->errinfo = err;
1058 }
1059
1060 VALUE
1061 rb_rubylevel_errinfo(void)
1062 {
1063 return get_errinfo();
1064 }
1065
1066 static VALUE
1067 errat_getter(ID id)
1068 {
1069 VALUE err = get_errinfo();
1070 if (!NIL_P(err)) {
1071 return get_backtrace(err);
1072 }
1073 else {
1074 return Qnil;
1075 }
1076 }
1077
1078 static void
1079 errat_setter(VALUE val, ID id, VALUE *var)
1080 {
1081 VALUE err = get_errinfo();
1082 if (NIL_P(err)) {
1083 rb_raise(rb_eArgError, "$! not set");
1084 }
1085 set_backtrace(err, val);
1086 }
1087
1088 int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
1089
1090 /*
1091 * call-seq:
1092 * local_variables => array
1093 *
1094 * Returns the names of the current local variables.
1095 *
1096 * fred = 1
1097 * for i in 1..10
1098 * # ...
1099 * end
1100 * local_variables #=> ["fred", "i"]
1101 */
1102
1103 static VALUE
1104 rb_f_local_variables(void)
1105 {
1106 VALUE ary = rb_ary_new();
1107 rb_thread_t *th = GET_THREAD();
1108 rb_control_frame_t *cfp =
1109 vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
1110 int i;
1111
1112 while (1) {
1113 if (cfp->iseq) {
1114 for (i = 0; i < cfp->iseq->local_table_size; i++) {
1115 ID lid = cfp->iseq->local_table[i];
1116 if (lid) {
1117 const char *vname = rb_id2name(lid);
1118 /* should skip temporary variable */
1119 if (vname) {
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
1120 rb_ary_push(ary, ID2SYM(lid));
511dc44 initial import
Laurent Sansonetti authored
1121 }
1122 }
1123 }
1124 }
1125 if (cfp->lfp != cfp->dfp) {
1126 /* block */
1127 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
1128
1129 if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
1130 break;
1131 }
1132 else {
1133 while (cfp->dfp != dfp) {
1134 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1135 }
1136 }
1137 }
1138 else {
1139 break;
1140 }
1141 }
1142 return ary;
1143 }
1144
1145
1146 /*
1147 * call-seq:
1148 * __method__ => symbol
1149 * __callee__ => symbol
1150 *
1151 * Returns the name of the current method as a Symbol.
1152 * If called outside of a method, it returns <code>nil</code>.
1153 *
1154 */
1155
1156 static VALUE
1157 rb_f_method_name(void)
1158 {
1159 ID fname = rb_frame_callee();
1160
1161 if (fname) {
1162 return ID2SYM(fname);
1163 }
1164 else {
1165 return Qnil;
1166 }
1167 }
1168
1169 void
1170 Init_eval(void)
1171 {
1172 /* TODO: fix position */
1173 GET_THREAD()->vm->mark_object_ary = rb_ary_new();
1174
1175 rb_define_virtual_variable("$@", errat_getter, errat_setter);
1176 rb_define_virtual_variable("$!", errinfo_getter, 0);
1177
1178 rb_define_global_function("eval", rb_f_eval, -1);
1179 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
1180 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
1181
1182 rb_define_global_function("raise", rb_f_raise, -1);
1183 rb_define_global_function("fail", rb_f_raise, -1);
1184
1185 rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
1186 rb_define_global_function("local_variables", rb_f_local_variables, 0);
1187
1188 rb_define_global_function("__method__", rb_f_method_name, 0);
1189 rb_define_global_function("__callee__", rb_f_method_name, 0);
1190
1191 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
1192 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
1193 rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
1194 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
1195 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
1196
1197 rb_undef_method(rb_cClass, "module_function");
1198
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1199 {
1200 extern void Init_vm_eval(void);
1201 extern void Init_eval_method(void);
1202 Init_vm_eval();
1203 Init_eval_method();
1204 }
511dc44 initial import
Laurent Sansonetti authored
1205
1206 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
1207 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
1208
1209 rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
1210
1211 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
1212
1213 rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
1214 rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
1215
1216 rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
1217
1218 exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
1219 rb_ivar_set(exception_error, idThrowState, INT2FIX(TAG_FATAL));
1220 rb_register_mark_object(exception_error);
6711c4e retain global exceptions
Laurent Sansonetti authored
1221 rb_objc_retain((void *)exception_error);
511dc44 initial import
Laurent Sansonetti authored
1222 }
1223
1224
1225 /* for parser */
1226
1227 int
1228 rb_dvar_defined(ID id)
1229 {
1230 rb_thread_t *th = GET_THREAD();
1231 rb_iseq_t *iseq;
1232 if (th->base_block && (iseq = th->base_block->iseq)) {
1233 while (iseq->type == ISEQ_TYPE_BLOCK ||
1234 iseq->type == ISEQ_TYPE_RESCUE ||
1235 iseq->type == ISEQ_TYPE_ENSURE ||
1236 iseq->type == ISEQ_TYPE_EVAL) {
1237 int i;
1238
1239 for (i = 0; i < iseq->local_table_size; i++) {
1240 if (iseq->local_table[i] == id) {
1241 return 1;
1242 }
1243 }
1244 iseq = iseq->parent_iseq;
1245 }
1246 }
1247 return 0;
1248 }
1249
1250 int
1251 rb_local_defined(ID id)
1252 {
1253 rb_thread_t *th = GET_THREAD();
1254 rb_iseq_t *iseq;
1255
1256 if (th->base_block && th->base_block->iseq) {
1257 int i;
1258 iseq = th->base_block->iseq->local_iseq;
1259
1260 for (i=0; i<iseq->local_table_size; i++) {
1261 if (iseq->local_table[i] == id) {
1262 return 1;
1263 }
1264 }
1265 }
1266 return 0;
1267 }
1268
1269 int
1270 rb_parse_in_eval(void)
1271 {
1272 return GET_THREAD()->parse_in_eval != 0;
1273 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1274
1275
Something went wrong with that request. Please try again.