PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/vm_eval.c

https://github.com/fizx/ruby
C | 1743 lines | 1185 code | 199 blank | 359 comment | 217 complexity | a71abd96b2a20b40e780a287216f2fed MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, GPL-2.0, BSD-3-Clause
  1. /**********************************************************************
  2. vm_eval.c -
  3. $Author$
  4. created at: Sat May 24 16:02:32 JST 2008
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
  7. Copyright (C) 2000 Information-technology Promotion Agency, Japan
  8. **********************************************************************/
  9. static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
  10. static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
  11. static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
  12. static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
  13. static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
  14. static int vm_backtrace_each(rb_thread_t *th, int lev, rb_backtrace_iter_func *iter, void *arg);
  15. static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
  16. static VALUE vm_exec(rb_thread_t *th);
  17. static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
  18. static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
  19. typedef enum call_type {
  20. CALL_PUBLIC,
  21. CALL_FCALL,
  22. CALL_VCALL,
  23. CALL_TYPE_MAX
  24. } call_type;
  25. static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
  26. static inline VALUE
  27. vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
  28. const rb_method_entry_t *me)
  29. {
  30. const rb_method_definition_t *def = me->def;
  31. VALUE val;
  32. VALUE klass = me->klass;
  33. const rb_block_t *blockptr = 0;
  34. if (!def) return Qnil;
  35. if (th->passed_block) {
  36. blockptr = th->passed_block;
  37. th->passed_block = 0;
  38. }
  39. again:
  40. switch (def->type) {
  41. case VM_METHOD_TYPE_ISEQ: {
  42. rb_control_frame_t *reg_cfp;
  43. int i;
  44. rb_vm_set_finish_env(th);
  45. reg_cfp = th->cfp;
  46. CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
  47. *reg_cfp->sp++ = recv;
  48. for (i = 0; i < argc; i++) {
  49. *reg_cfp->sp++ = argv[i];
  50. }
  51. vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me);
  52. val = vm_exec(th);
  53. break;
  54. }
  55. case VM_METHOD_TYPE_CFUNC: {
  56. EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
  57. {
  58. rb_control_frame_t *reg_cfp = th->cfp;
  59. rb_control_frame_t *cfp =
  60. vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
  61. recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
  62. cfp->me = me;
  63. val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
  64. if (reg_cfp != th->cfp + 1) {
  65. rb_bug("cfp consistency error - call0");
  66. }
  67. vm_pop_frame(th);
  68. }
  69. EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
  70. break;
  71. }
  72. case VM_METHOD_TYPE_ATTRSET: {
  73. if (argc != 1) {
  74. rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
  75. }
  76. val = rb_ivar_set(recv, def->body.attr_id, argv[0]);
  77. break;
  78. }
  79. case VM_METHOD_TYPE_IVAR: {
  80. if (argc != 0) {
  81. rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
  82. }
  83. val = rb_attr_get(recv, def->body.attr_id);
  84. break;
  85. }
  86. case VM_METHOD_TYPE_BMETHOD: {
  87. val = vm_call_bmethod(th, recv, argc, argv, blockptr, me);
  88. break;
  89. }
  90. case VM_METHOD_TYPE_ZSUPER: {
  91. klass = RCLASS_SUPER(klass);
  92. if (!klass || !(me = rb_method_entry(klass, id))) {
  93. return method_missing(recv, id, argc, argv, NOEX_SUPER);
  94. }
  95. RUBY_VM_CHECK_INTS();
  96. if (!(def = me->def)) return Qnil;
  97. goto again;
  98. }
  99. case VM_METHOD_TYPE_MISSING: {
  100. VALUE new_args = rb_ary_new4(argc, argv);
  101. RB_GC_GUARD(new_args);
  102. rb_ary_unshift(new_args, ID2SYM(id));
  103. return rb_funcall2(recv, idMethodMissing,
  104. argc+1, RARRAY_PTR(new_args));
  105. }
  106. case VM_METHOD_TYPE_OPTIMIZED: {
  107. switch (def->body.optimize_type) {
  108. case OPTIMIZED_METHOD_TYPE_SEND:
  109. val = send_internal(argc, argv, recv, CALL_FCALL);
  110. break;
  111. case OPTIMIZED_METHOD_TYPE_CALL: {
  112. rb_proc_t *proc;
  113. GetProcPtr(recv, proc);
  114. val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
  115. break;
  116. }
  117. default:
  118. rb_bug("vm_call0: unsupported optimized method type (%d)", def->body.optimize_type);
  119. val = Qundef;
  120. break;
  121. }
  122. break;
  123. }
  124. default:
  125. rb_bug("vm_call0: unsupported method type (%d)", def->type);
  126. val = Qundef;
  127. }
  128. RUBY_VM_CHECK_INTS();
  129. return val;
  130. }
  131. VALUE
  132. rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
  133. const rb_method_entry_t *me)
  134. {
  135. return vm_call0(th, recv, id, argc, argv, me);
  136. }
  137. static inline VALUE
  138. vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
  139. {
  140. VALUE recv = th->cfp->self;
  141. VALUE klass;
  142. ID id;
  143. rb_method_entry_t *me;
  144. rb_control_frame_t *cfp = th->cfp;
  145. if (!cfp->iseq) {
  146. klass = cfp->me->klass;
  147. klass = RCLASS_SUPER(klass);
  148. if (klass == 0) {
  149. klass = vm_search_normal_superclass(cfp->me->klass, recv);
  150. }
  151. id = cfp->me->def->original_id;
  152. }
  153. else {
  154. rb_bug("vm_call_super: should not be reached");
  155. }
  156. me = rb_method_entry(klass, id);
  157. if (!me) {
  158. return method_missing(recv, id, argc, argv, NOEX_SUPER);
  159. }
  160. return vm_call0(th, recv, id, argc, argv, me);
  161. }
  162. VALUE
  163. rb_call_super(int argc, const VALUE *argv)
  164. {
  165. PASS_PASSED_BLOCK();
  166. return vm_call_super(GET_THREAD(), argc, argv);
  167. }
  168. static inline void
  169. stack_check(void)
  170. {
  171. rb_thread_t *th = GET_THREAD();
  172. if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
  173. rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
  174. rb_exc_raise(sysstack_error);
  175. }
  176. }
  177. static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
  178. static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self);
  179. #define NOEX_OK NOEX_NOSUPER
  180. /*!
  181. * \internal
  182. * calls the specified method.
  183. *
  184. * This function is called by functions in rb_call* family.
  185. * \param recv receiver of the method
  186. * \param mid an ID that represents the name of the method
  187. * \param argc the number of method arguments
  188. * \param argv a pointer to an array of method arguments
  189. * \param scope
  190. * \param self self in the caller. Qundef means the current control frame's self.
  191. *
  192. * \note \a self is used in order to controlling access to protected methods.
  193. */
  194. static inline VALUE
  195. rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
  196. call_type scope, VALUE self)
  197. {
  198. rb_method_entry_t *me = rb_search_method_entry(recv, mid);
  199. rb_thread_t *th = GET_THREAD();
  200. int call_status = rb_method_call_status(th, me, scope, self);
  201. if (call_status != NOEX_OK) {
  202. return method_missing(recv, mid, argc, argv, call_status);
  203. }
  204. stack_check();
  205. return vm_call0(th, recv, mid, argc, argv, me);
  206. }
  207. struct rescue_funcall_args {
  208. VALUE recv;
  209. VALUE sym;
  210. int argc;
  211. VALUE *argv;
  212. };
  213. static VALUE
  214. check_funcall_exec(struct rescue_funcall_args *args)
  215. {
  216. VALUE new_args = rb_ary_new4(args->argc, args->argv);
  217. RB_GC_GUARD(new_args);
  218. rb_ary_unshift(new_args, args->sym);
  219. return rb_funcall2(args->recv, idMethodMissing,
  220. args->argc+1, RARRAY_PTR(new_args));
  221. }
  222. static VALUE
  223. check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
  224. {
  225. if (rb_respond_to(args->recv, SYM2ID(args->sym))) {
  226. rb_exc_raise(e);
  227. }
  228. return Qundef;
  229. }
  230. static VALUE
  231. check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
  232. {
  233. rb_method_entry_t *me = rb_search_method_entry(recv, mid);
  234. rb_thread_t *th = GET_THREAD();
  235. int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
  236. if (call_status != NOEX_OK) {
  237. if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
  238. return Qundef;
  239. }
  240. else {
  241. struct rescue_funcall_args args;
  242. th->method_missing_reason = 0;
  243. args.recv = recv;
  244. args.sym = ID2SYM(mid);
  245. args.argc = argc;
  246. args.argv = argv;
  247. return rb_rescue2(check_funcall_exec, (VALUE)&args,
  248. check_funcall_failed, (VALUE)&args,
  249. rb_eNoMethodError, (VALUE)0);
  250. }
  251. }
  252. stack_check();
  253. return vm_call0(th, recv, mid, argc, argv, me);
  254. }
  255. VALUE
  256. rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
  257. {
  258. return check_funcall(recv, mid, argc, argv);
  259. }
  260. static const char *
  261. rb_type_str(enum ruby_value_type type)
  262. {
  263. #define type_case(t) case t: return #t;
  264. switch (type) {
  265. type_case(T_NONE)
  266. type_case(T_OBJECT)
  267. type_case(T_CLASS)
  268. type_case(T_MODULE)
  269. type_case(T_FLOAT)
  270. type_case(T_STRING)
  271. type_case(T_REGEXP)
  272. type_case(T_ARRAY)
  273. type_case(T_HASH)
  274. type_case(T_STRUCT)
  275. type_case(T_BIGNUM)
  276. type_case(T_FILE)
  277. type_case(T_DATA)
  278. type_case(T_MATCH)
  279. type_case(T_COMPLEX)
  280. type_case(T_RATIONAL)
  281. type_case(T_NIL)
  282. type_case(T_TRUE)
  283. type_case(T_FALSE)
  284. type_case(T_SYMBOL)
  285. type_case(T_FIXNUM)
  286. type_case(T_UNDEF)
  287. type_case(T_NODE)
  288. type_case(T_ICLASS)
  289. type_case(T_ZOMBIE)
  290. default: return NULL;
  291. }
  292. #undef type_case
  293. }
  294. static inline rb_method_entry_t *
  295. rb_search_method_entry(VALUE recv, ID mid)
  296. {
  297. VALUE klass = CLASS_OF(recv);
  298. if (!klass) {
  299. VALUE flags, klass;
  300. if (IMMEDIATE_P(recv)) {
  301. rb_raise(rb_eNotImpError,
  302. "method `%s' called on unexpected immediate object (%p)",
  303. rb_id2name(mid), (void *)recv);
  304. }
  305. flags = RBASIC(recv)->flags;
  306. klass = RBASIC(recv)->klass;
  307. if (flags == 0) {
  308. rb_raise(rb_eNotImpError,
  309. "method `%s' called on terminated object"
  310. " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
  311. rb_id2name(mid), (void *)recv, flags, klass);
  312. }
  313. else {
  314. int type = BUILTIN_TYPE(recv);
  315. const char *typestr = rb_type_str(type);
  316. if (typestr && T_OBJECT <= type && type < T_NIL)
  317. rb_raise(rb_eNotImpError,
  318. "method `%s' called on hidden %s object"
  319. " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
  320. rb_id2name(mid), typestr, (void *)recv, flags, klass);
  321. if (typestr)
  322. rb_raise(rb_eNotImpError,
  323. "method `%s' called on unexpected %s object"
  324. " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
  325. rb_id2name(mid), typestr, (void *)recv, flags, klass);
  326. else
  327. rb_raise(rb_eNotImpError,
  328. "method `%s' called on broken T_???" "(0x%02x) object"
  329. " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
  330. rb_id2name(mid), type, (void *)recv, flags, klass);
  331. }
  332. }
  333. return rb_method_entry(klass, mid);
  334. }
  335. static inline int
  336. rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self)
  337. {
  338. VALUE klass;
  339. ID oid;
  340. int noex;
  341. if (UNDEFINED_METHOD_ENTRY_P(me)) {
  342. return scope == CALL_VCALL ? NOEX_VCALL : 0;
  343. }
  344. klass = me->klass;
  345. oid = me->def->original_id;
  346. noex = me->flag;
  347. if (oid != idMethodMissing) {
  348. /* receiver specified form for private method */
  349. if (UNLIKELY(noex)) {
  350. if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
  351. return NOEX_PRIVATE;
  352. }
  353. /* self must be kind of a specified form for protected method */
  354. if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) {
  355. VALUE defined_class = klass;
  356. if (TYPE(defined_class) == T_ICLASS) {
  357. defined_class = RBASIC(defined_class)->klass;
  358. }
  359. if (self == Qundef) {
  360. self = th->cfp->self;
  361. }
  362. if (!rb_obj_is_kind_of(self, defined_class)) {
  363. return NOEX_PROTECTED;
  364. }
  365. }
  366. if (NOEX_SAFE(noex) > th->safe_level) {
  367. rb_raise(rb_eSecurityError, "calling insecure method: %s",
  368. rb_id2name(me->called_id));
  369. }
  370. }
  371. }
  372. return NOEX_OK;
  373. }
  374. /*!
  375. * \internal
  376. * calls the specified method.
  377. *
  378. * This function is called by functions in rb_call* family.
  379. * \param recv receiver
  380. * \param mid an ID that represents the name of the method
  381. * \param argc the number of method arguments
  382. * \param argv a pointer to an array of method arguments
  383. * \param scope
  384. */
  385. static inline VALUE
  386. rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
  387. {
  388. return rb_call0(recv, mid, argc, argv, scope, Qundef);
  389. }
  390. NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
  391. VALUE obj, int call_status));
  392. /*
  393. * call-seq:
  394. * obj.method_missing(symbol [, *args] ) => result
  395. *
  396. * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
  397. * <i>symbol</i> is the symbol for the method called, and <i>args</i>
  398. * are any arguments that were passed to it. By default, the interpreter
  399. * raises an error when this method is called. However, it is possible
  400. * to override the method to provide more dynamic behavior.
  401. * If it is decided that a particular method should not be handled, then
  402. * <i>super</i> should be called, so that ancestors can pick up the
  403. * missing method.
  404. * The example below creates
  405. * a class <code>Roman</code>, which responds to methods with names
  406. * consisting of roman numerals, returning the corresponding integer
  407. * values.
  408. *
  409. * class Roman
  410. * def romanToInt(str)
  411. * # ...
  412. * end
  413. * def method_missing(methId)
  414. * str = methId.id2name
  415. * romanToInt(str)
  416. * end
  417. * end
  418. *
  419. * r = Roman.new
  420. * r.iv #=> 4
  421. * r.xxiii #=> 23
  422. * r.mm #=> 2000
  423. */
  424. static VALUE
  425. rb_method_missing(int argc, const VALUE *argv, VALUE obj)
  426. {
  427. rb_thread_t *th = GET_THREAD();
  428. raise_method_missing(th, argc, argv, obj, th->method_missing_reason);
  429. return Qnil; /* not reached */
  430. }
  431. #define NOEX_MISSING 0x80
  432. static void
  433. raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
  434. int last_call_status)
  435. {
  436. ID id;
  437. VALUE exc = rb_eNoMethodError;
  438. const char *format = 0;
  439. if (argc == 0 || !SYMBOL_P(argv[0])) {
  440. rb_raise(rb_eArgError, "no id given");
  441. }
  442. stack_check();
  443. id = SYM2ID(argv[0]);
  444. if (last_call_status & NOEX_PRIVATE) {
  445. format = "private method `%s' called for %s";
  446. }
  447. else if (last_call_status & NOEX_PROTECTED) {
  448. format = "protected method `%s' called for %s";
  449. }
  450. else if (last_call_status & NOEX_VCALL) {
  451. format = "undefined local variable or method `%s' for %s";
  452. exc = rb_eNameError;
  453. }
  454. else if (last_call_status & NOEX_SUPER) {
  455. format = "super: no superclass method `%s' for %s";
  456. }
  457. if (!format) {
  458. format = "undefined method `%s' for %s";
  459. }
  460. {
  461. int n = 0;
  462. VALUE mesg;
  463. VALUE args[3];
  464. mesg = rb_const_get(exc, rb_intern("message"));
  465. if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) {
  466. args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]);
  467. }
  468. else {
  469. args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]);
  470. }
  471. args[n++] = argv[0];
  472. if (exc == rb_eNoMethodError) {
  473. args[n++] = rb_ary_new4(argc - 1, argv + 1);
  474. }
  475. exc = rb_class_new_instance(n, args, exc);
  476. if (!(last_call_status & NOEX_MISSING)) {
  477. th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
  478. }
  479. rb_exc_raise(exc);
  480. }
  481. }
  482. static inline VALUE
  483. method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
  484. {
  485. VALUE *nargv, result, argv_ary = 0;
  486. rb_thread_t *th = GET_THREAD();
  487. th->method_missing_reason = call_status;
  488. th->passed_block = 0;
  489. if (id == idMethodMissing) {
  490. raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
  491. }
  492. else if (id == ID_ALLOCATOR) {
  493. rb_raise(rb_eTypeError, "allocator undefined for %s",
  494. rb_class2name(obj));
  495. }
  496. if (argc < 0x100) {
  497. nargv = ALLOCA_N(VALUE, argc + 1);
  498. }
  499. else {
  500. argv_ary = rb_ary_tmp_new(argc + 1);
  501. nargv = RARRAY_PTR(argv_ary);
  502. }
  503. nargv[0] = ID2SYM(id);
  504. MEMCPY(nargv + 1, argv, VALUE, argc);
  505. if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
  506. raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
  507. }
  508. result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
  509. if (argv_ary) rb_ary_clear(argv_ary);
  510. return result;
  511. }
  512. void
  513. rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
  514. VALUE obj, int call_status)
  515. {
  516. th->passed_block = 0;
  517. raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
  518. }
  519. /*!
  520. * Calls a method
  521. * \param recv receiver of the method
  522. * \param mid an ID that represents the name of the method
  523. * \param args an Array object which contains method arguments
  524. *
  525. * \pre \a args must refer an Array object.
  526. */
  527. VALUE
  528. rb_apply(VALUE recv, ID mid, VALUE args)
  529. {
  530. int argc;
  531. VALUE *argv;
  532. argc = RARRAY_LENINT(args);
  533. argv = ALLOCA_N(VALUE, argc);
  534. MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
  535. return rb_call(recv, mid, argc, argv, CALL_FCALL);
  536. }
  537. /*!
  538. * Calls a method
  539. * \param recv receiver of the method
  540. * \param mid an ID that represents the name of the method
  541. * \param n the number of arguments
  542. * \param ... arbitrary number of method arguments
  543. *
  544. * \pre each of arguments after \a n must be a VALUE.
  545. */
  546. VALUE
  547. rb_funcall(VALUE recv, ID mid, int n, ...)
  548. {
  549. VALUE *argv;
  550. va_list ar;
  551. va_init_list(ar, n);
  552. if (n > 0) {
  553. long i;
  554. argv = ALLOCA_N(VALUE, n);
  555. for (i = 0; i < n; i++) {
  556. argv[i] = va_arg(ar, VALUE);
  557. }
  558. va_end(ar);
  559. }
  560. else {
  561. argv = 0;
  562. }
  563. return rb_call(recv, mid, n, argv, CALL_FCALL);
  564. }
  565. /*!
  566. * Calls a method
  567. * \param recv receiver of the method
  568. * \param mid an ID that represents the name of the method
  569. * \param argc the number of arguments
  570. * \param argv pointer to an array of method arguments
  571. */
  572. VALUE
  573. rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
  574. {
  575. return rb_call(recv, mid, argc, argv, CALL_FCALL);
  576. }
  577. /*!
  578. * Calls a method.
  579. *
  580. * Same as rb_funcall2 but this function can call only public methods.
  581. * \param recv receiver of the method
  582. * \param mid an ID that represents the name of the method
  583. * \param argc the number of arguments
  584. * \param argv pointer to an array of method arguments
  585. */
  586. VALUE
  587. rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
  588. {
  589. return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
  590. }
  591. static VALUE
  592. send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
  593. {
  594. VALUE vid;
  595. VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
  596. rb_thread_t *th = GET_THREAD();
  597. if (argc == 0) {
  598. rb_raise(rb_eArgError, "no method name given");
  599. }
  600. vid = *argv++; argc--;
  601. PASS_PASSED_BLOCK_TH(th);
  602. return rb_call0(recv, rb_to_id(vid), argc, argv, scope, self);
  603. }
  604. /*
  605. * call-seq:
  606. * obj.send(symbol [, args...]) => obj
  607. * obj.__send__(symbol [, args...]) => obj
  608. *
  609. * Invokes the method identified by _symbol_, passing it any
  610. * arguments specified. You can use <code>__send__</code> if the name
  611. * +send+ clashes with an existing method in _obj_.
  612. *
  613. * class Klass
  614. * def hello(*args)
  615. * "Hello " + args.join(' ')
  616. * end
  617. * end
  618. * k = Klass.new
  619. * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
  620. */
  621. VALUE
  622. rb_f_send(int argc, VALUE *argv, VALUE recv)
  623. {
  624. return send_internal(argc, argv, recv, CALL_FCALL);
  625. }
  626. /*
  627. * call-seq:
  628. * obj.public_send(symbol [, args...]) => obj
  629. *
  630. * Invokes the method identified by _symbol_, passing it any
  631. * arguments specified. Unlike send, public_send calls public
  632. * methods only.
  633. *
  634. * 1.public_send(:puts, "hello") # causes NoMethodError
  635. */
  636. VALUE
  637. rb_f_public_send(int argc, VALUE *argv, VALUE recv)
  638. {
  639. return send_internal(argc, argv, recv, CALL_PUBLIC);
  640. }
  641. /* yield */
  642. static inline VALUE
  643. rb_yield_0(int argc, const VALUE * argv)
  644. {
  645. return vm_yield(GET_THREAD(), argc, argv);
  646. }
  647. VALUE
  648. rb_yield(VALUE val)
  649. {
  650. if (val == Qundef) {
  651. return rb_yield_0(0, 0);
  652. }
  653. else {
  654. return rb_yield_0(1, &val);
  655. }
  656. }
  657. VALUE
  658. rb_yield_values(int n, ...)
  659. {
  660. if (n == 0) {
  661. return rb_yield_0(0, 0);
  662. }
  663. else {
  664. int i;
  665. VALUE *argv;
  666. va_list args;
  667. argv = ALLOCA_N(VALUE, n);
  668. va_init_list(args, n);
  669. for (i=0; i<n; i++) {
  670. argv[i] = va_arg(args, VALUE);
  671. }
  672. va_end(args);
  673. return rb_yield_0(n, argv);
  674. }
  675. }
  676. VALUE
  677. rb_yield_values2(int argc, const VALUE *argv)
  678. {
  679. return rb_yield_0(argc, argv);
  680. }
  681. VALUE
  682. rb_yield_splat(VALUE values)
  683. {
  684. VALUE tmp = rb_check_array_type(values);
  685. volatile VALUE v;
  686. if (NIL_P(tmp)) {
  687. rb_raise(rb_eArgError, "not an array");
  688. }
  689. v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp));
  690. return v;
  691. }
  692. static VALUE
  693. loop_i(void)
  694. {
  695. for (;;) {
  696. rb_yield_0(0, 0);
  697. }
  698. return Qnil;
  699. }
  700. /*
  701. * call-seq:
  702. * loop {|| block }
  703. *
  704. * Repeatedly executes the block.
  705. *
  706. * loop do
  707. * print "Input: "
  708. * line = gets
  709. * break if !line or line =~ /^qQ/
  710. * # ...
  711. * end
  712. *
  713. * StopIteration raised in the block breaks the loop.
  714. */
  715. static VALUE
  716. rb_f_loop(VALUE self)
  717. {
  718. RETURN_ENUMERATOR(self, 0, 0);
  719. rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
  720. return Qnil; /* dummy */
  721. }
  722. static const char *
  723. vm_frametype_name(const rb_control_frame_t *cfp);
  724. VALUE
  725. rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
  726. VALUE (* bl_proc) (ANYARGS), VALUE data2)
  727. {
  728. int state;
  729. volatile VALUE retval = Qnil;
  730. NODE *node = NEW_IFUNC(bl_proc, data2);
  731. rb_thread_t *th = GET_THREAD();
  732. rb_control_frame_t *volatile cfp = th->cfp;
  733. TH_PUSH_TAG(th);
  734. state = TH_EXEC_TAG();
  735. if (state == 0) {
  736. iter_retry:
  737. {
  738. rb_block_t *blockptr;
  739. if (bl_proc) {
  740. blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
  741. blockptr->iseq = (void *)node;
  742. blockptr->proc = 0;
  743. }
  744. else {
  745. blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
  746. }
  747. th->passed_block = blockptr;
  748. }
  749. retval = (*it_proc) (data1);
  750. }
  751. else {
  752. VALUE err = th->errinfo;
  753. if (state == TAG_BREAK) {
  754. VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
  755. VALUE *cdfp = cfp->dfp;
  756. if (cdfp == escape_dfp) {
  757. state = 0;
  758. th->state = 0;
  759. th->errinfo = Qnil;
  760. /* check skipped frame */
  761. while (th->cfp != cfp) {
  762. /* printf("skipped frame: %s\n", vm_frametype_name(th->cfp)); */
  763. if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
  764. const rb_method_entry_t *me = th->cfp->me;
  765. EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
  766. }
  767. th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
  768. }
  769. }
  770. else{
  771. /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
  772. }
  773. }
  774. else if (state == TAG_RETRY) {
  775. VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
  776. VALUE *cdfp = cfp->dfp;
  777. if (cdfp == escape_dfp) {
  778. state = 0;
  779. th->state = 0;
  780. th->errinfo = Qnil;
  781. th->cfp = cfp;
  782. goto iter_retry;
  783. }
  784. }
  785. }
  786. TH_POP_TAG();
  787. switch (state) {
  788. case 0:
  789. break;
  790. default:
  791. TH_JUMP_TAG(th, state);
  792. }
  793. return retval;
  794. }
  795. struct iter_method_arg {
  796. VALUE obj;
  797. ID mid;
  798. int argc;
  799. VALUE *argv;
  800. };
  801. static VALUE
  802. iterate_method(VALUE obj)
  803. {
  804. const struct iter_method_arg * arg =
  805. (struct iter_method_arg *) obj;
  806. return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
  807. }
  808. VALUE
  809. rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
  810. VALUE (*bl_proc) (ANYARGS), VALUE data2)
  811. {
  812. struct iter_method_arg arg;
  813. arg.obj = obj;
  814. arg.mid = mid;
  815. arg.argc = argc;
  816. arg.argv = argv;
  817. return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
  818. }
  819. VALUE
  820. rb_each(VALUE obj)
  821. {
  822. return rb_call(obj, idEach, 0, 0, CALL_FCALL);
  823. }
  824. static VALUE
  825. eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
  826. {
  827. int state;
  828. VALUE result = Qundef;
  829. VALUE envval;
  830. rb_binding_t *bind = 0;
  831. rb_thread_t *th = GET_THREAD();
  832. rb_env_t *env = NULL;
  833. rb_block_t block;
  834. volatile int parse_in_eval;
  835. volatile int mild_compile_error;
  836. if (file == 0) {
  837. file = rb_sourcefile();
  838. line = rb_sourceline();
  839. }
  840. parse_in_eval = th->parse_in_eval;
  841. mild_compile_error = th->mild_compile_error;
  842. PUSH_TAG();
  843. if ((state = EXEC_TAG()) == 0) {
  844. rb_iseq_t *iseq;
  845. volatile VALUE iseqval;
  846. if (scope != Qnil) {
  847. if (rb_obj_is_kind_of(scope, rb_cBinding)) {
  848. GetBindingPtr(scope, bind);
  849. envval = bind->env;
  850. }
  851. else {
  852. rb_raise(rb_eTypeError,
  853. "wrong argument type %s (expected Binding)",
  854. rb_obj_classname(scope));
  855. }
  856. GetEnvPtr(envval, env);
  857. th->base_block = &env->block;
  858. }
  859. else {
  860. rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
  861. if (cfp != 0) {
  862. block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
  863. th->base_block = &block;
  864. th->base_block->self = self;
  865. th->base_block->iseq = cfp->iseq; /* TODO */
  866. }
  867. else {
  868. rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
  869. }
  870. }
  871. /* make eval iseq */
  872. th->parse_in_eval++;
  873. th->mild_compile_error++;
  874. iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
  875. th->mild_compile_error--;
  876. th->parse_in_eval--;
  877. vm_set_eval_stack(th, iseqval, cref);
  878. th->base_block = 0;
  879. if (0) { /* for debug */
  880. printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval)));
  881. }
  882. /* save new env */
  883. GetISeqPtr(iseqval, iseq);
  884. if (bind && iseq->local_table_size > 0) {
  885. bind->env = rb_vm_make_env_object(th, th->cfp);
  886. }
  887. /* kick */
  888. CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
  889. result = vm_exec(th);
  890. }
  891. POP_TAG();
  892. th->mild_compile_error = mild_compile_error;
  893. th->parse_in_eval = parse_in_eval;
  894. if (state) {
  895. if (state == TAG_RAISE) {
  896. VALUE errinfo = th->errinfo;
  897. if (strcmp(file, "(eval)") == 0) {
  898. VALUE mesg, errat, bt2;
  899. extern VALUE rb_get_backtrace(VALUE info);
  900. ID id_mesg;
  901. CONST_ID(id_mesg, "mesg");
  902. errat = rb_get_backtrace(errinfo);
  903. mesg = rb_attr_get(errinfo, id_mesg);
  904. if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
  905. (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
  906. if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
  907. if (OBJ_FROZEN(mesg)) {
  908. VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
  909. rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
  910. }
  911. else {
  912. rb_str_update(mesg, 0, 0, rb_str_new2(": "));
  913. rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
  914. }
  915. }
  916. RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
  917. }
  918. }
  919. rb_exc_raise(errinfo);
  920. }
  921. JUMP_TAG(state);
  922. }
  923. return result;
  924. }
  925. static VALUE
  926. eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
  927. {
  928. return eval_string_with_cref(self, src, scope, 0, file, line);
  929. }
  930. /*
  931. * call-seq:
  932. * eval(string [, binding [, filename [,lineno]]]) => obj
  933. *
  934. * Evaluates the Ruby expression(s) in <em>string</em>. If
  935. * <em>binding</em> is given, which must be a <code>Binding</code>
  936. * object, the evaluation is performed in its context. If the
  937. * optional <em>filename</em> and <em>lineno</em> parameters are
  938. * present, they will be used when reporting syntax errors.
  939. *
  940. * def getBinding(str)
  941. * return binding
  942. * end
  943. * str = "hello"
  944. * eval "str + ' Fred'" #=> "hello Fred"
  945. * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
  946. */
  947. VALUE
  948. rb_f_eval(int argc, VALUE *argv, VALUE self)
  949. {
  950. VALUE src, scope, vfile, vline;
  951. const char *file = "(eval)";
  952. int line = 1;
  953. rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
  954. if (rb_safe_level() >= 4) {
  955. StringValue(src);
  956. if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
  957. rb_raise(rb_eSecurityError,
  958. "Insecure: can't modify trusted binding");
  959. }
  960. }
  961. else {
  962. SafeStringValue(src);
  963. }
  964. if (argc >= 3) {
  965. StringValue(vfile);
  966. }
  967. if (argc >= 4) {
  968. line = NUM2INT(vline);
  969. }
  970. if (!NIL_P(vfile))
  971. file = RSTRING_PTR(vfile);
  972. return eval_string(self, src, scope, file, line);
  973. }
  974. VALUE
  975. rb_eval_string(const char *str)
  976. {
  977. return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
  978. }
  979. VALUE
  980. rb_eval_string_protect(const char *str, int *state)
  981. {
  982. return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
  983. }
  984. VALUE
  985. rb_eval_string_wrap(const char *str, int *state)
  986. {
  987. int status;
  988. rb_thread_t *th = GET_THREAD();
  989. VALUE self = th->top_self;
  990. VALUE wrapper = th->top_wrapper;
  991. VALUE val;
  992. th->top_wrapper = rb_module_new();
  993. th->top_self = rb_obj_clone(rb_vm_top_self());
  994. rb_extend_object(th->top_self, th->top_wrapper);
  995. val = rb_eval_string_protect(str, &status);
  996. th->top_self = self;
  997. th->top_wrapper = wrapper;
  998. if (state) {
  999. *state = status;
  1000. }
  1001. else if (status) {
  1002. JUMP_TAG(status);
  1003. }
  1004. return val;
  1005. }
  1006. VALUE
  1007. rb_eval_cmd(VALUE cmd, VALUE arg, int level)
  1008. {
  1009. int state;
  1010. VALUE val = Qnil; /* OK */
  1011. volatile int safe = rb_safe_level();
  1012. if (OBJ_TAINTED(cmd)) {
  1013. level = 4;
  1014. }
  1015. if (TYPE(cmd) != T_STRING) {
  1016. PUSH_TAG();
  1017. rb_set_safe_level_force(level);
  1018. if ((state = EXEC_TAG()) == 0) {
  1019. val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
  1020. RARRAY_PTR(arg));
  1021. }
  1022. POP_TAG();
  1023. rb_set_safe_level_force(safe);
  1024. if (state)
  1025. JUMP_TAG(state);
  1026. return val;
  1027. }
  1028. PUSH_TAG();
  1029. if ((state = EXEC_TAG()) == 0) {
  1030. val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
  1031. }
  1032. POP_TAG();
  1033. rb_set_safe_level_force(safe);
  1034. if (state) rb_vm_jump_tag_but_local_jump(state, val);
  1035. return val;
  1036. }
  1037. /* block eval under the class/module context */
  1038. static VALUE
  1039. yield_under(VALUE under, VALUE self, VALUE values)
  1040. {
  1041. rb_thread_t *th = GET_THREAD();
  1042. rb_block_t block, *blockptr;
  1043. NODE *cref;
  1044. if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
  1045. block = *blockptr;
  1046. block.self = self;
  1047. th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
  1048. }
  1049. cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
  1050. cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
  1051. if (values == Qundef) {
  1052. return vm_yield_with_cref(th, 1, &self, cref);
  1053. }
  1054. else {
  1055. return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
  1056. }
  1057. }
  1058. /* string eval under the class/module context */
  1059. static VALUE
  1060. eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
  1061. {
  1062. NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
  1063. if (rb_safe_level() >= 4) {
  1064. StringValue(src);
  1065. }
  1066. else {
  1067. SafeStringValue(src);
  1068. }
  1069. return eval_string_with_cref(self, src, Qnil, cref, file, line);
  1070. }
  1071. static VALUE
  1072. specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
  1073. {
  1074. if (rb_block_given_p()) {
  1075. if (argc > 0) {
  1076. rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
  1077. }
  1078. return yield_under(klass, self, Qundef);
  1079. }
  1080. else {
  1081. const char *file = "(eval)";
  1082. int line = 1;
  1083. if (argc == 0) {
  1084. rb_raise(rb_eArgError, "block not supplied");
  1085. }
  1086. else {
  1087. if (rb_safe_level() >= 4) {
  1088. StringValue(argv[0]);
  1089. }
  1090. else {
  1091. SafeStringValue(argv[0]);
  1092. }
  1093. if (argc > 3) {
  1094. const char *name = rb_id2name(rb_frame_callee());
  1095. rb_raise(rb_eArgError,
  1096. "wrong number of arguments: %s(src) or %s{..}",
  1097. name, name);
  1098. }
  1099. if (argc > 2)
  1100. line = NUM2INT(argv[2]);
  1101. if (argc > 1) {
  1102. file = StringValuePtr(argv[1]);
  1103. }
  1104. }
  1105. return eval_under(klass, self, argv[0], file, line);
  1106. }
  1107. }
  1108. /*
  1109. * call-seq:
  1110. * obj.instance_eval(string [, filename [, lineno]] ) => obj
  1111. * obj.instance_eval {| | block } => obj
  1112. *
  1113. * Evaluates a string containing Ruby source code, or the given block,
  1114. * within the context of the receiver (_obj_). In order to set the
  1115. * context, the variable +self+ is set to _obj_ while
  1116. * the code is executing, giving the code access to _obj_'s
  1117. * instance variables. In the version of <code>instance_eval</code>
  1118. * that takes a +String+, the optional second and third
  1119. * parameters supply a filename and starting line number that are used
  1120. * when reporting compilation errors.
  1121. *
  1122. * class KlassWithSecret
  1123. * def initialize
  1124. * @secret = 99
  1125. * end
  1126. * end
  1127. * k = KlassWithSecret.new
  1128. * k.instance_eval { @secret } #=> 99
  1129. */
  1130. VALUE
  1131. rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
  1132. {
  1133. VALUE klass;
  1134. if (SPECIAL_CONST_P(self)) {
  1135. klass = Qnil;
  1136. }
  1137. else {
  1138. klass = rb_singleton_class(self);
  1139. }
  1140. return specific_eval(argc, argv, klass, self);
  1141. }
  1142. /*
  1143. * call-seq:
  1144. * obj.instance_exec(arg...) {|var...| block } => obj
  1145. *
  1146. * Executes the given block within the context of the receiver
  1147. * (_obj_). In order to set the context, the variable +self+ is set
  1148. * to _obj_ while the code is executing, giving the code access to
  1149. * _obj_'s instance variables. Arguments are passed as block parameters.
  1150. *
  1151. * class KlassWithSecret
  1152. * def initialize
  1153. * @secret = 99
  1154. * end
  1155. * end
  1156. * k = KlassWithSecret.new
  1157. * k.instance_exec(5) {|x| @secret+x } #=> 104
  1158. */
  1159. VALUE
  1160. rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
  1161. {
  1162. VALUE klass;
  1163. if (SPECIAL_CONST_P(self)) {
  1164. klass = Qnil;
  1165. }
  1166. else {
  1167. klass = rb_singleton_class(self);
  1168. }
  1169. return yield_under(klass, self, rb_ary_new4(argc, argv));
  1170. }
  1171. /*
  1172. * call-seq:
  1173. * mod.class_eval(string [, filename [, lineno]]) => obj
  1174. * mod.module_eval {|| block } => obj
  1175. *
  1176. * Evaluates the string or block in the context of _mod_. This can
  1177. * be used to add methods to a class. <code>module_eval</code> returns
  1178. * the result of evaluating its argument. The optional _filename_
  1179. * and _lineno_ parameters set the text for error messages.
  1180. *
  1181. * class Thing
  1182. * end
  1183. * a = %q{def hello() "Hello there!" end}
  1184. * Thing.module_eval(a)
  1185. * puts Thing.new.hello()
  1186. * Thing.module_eval("invalid code", "dummy", 123)
  1187. *
  1188. * <em>produces:</em>
  1189. *
  1190. * Hello there!
  1191. * dummy:123:in `module_eval': undefined local variable
  1192. * or method `code' for Thing:Class
  1193. */
  1194. VALUE
  1195. rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
  1196. {
  1197. return specific_eval(argc, argv, mod, mod);
  1198. }
  1199. /*
  1200. * call-seq:
  1201. * mod.module_exec(arg...) {|var...| block } => obj
  1202. * mod.class_exec(arg...) {|var...| block } => obj
  1203. *
  1204. * Evaluates the given block in the context of the class/module.
  1205. * The method defined in the block will belong to the receiver.
  1206. *
  1207. * class Thing
  1208. * end
  1209. * Thing.class_exec{
  1210. * def hello() "Hello there!" end
  1211. * }
  1212. * puts Thing.new.hello()
  1213. *
  1214. * <em>produces:</em>
  1215. *
  1216. * Hello there!
  1217. */
  1218. VALUE
  1219. rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
  1220. {
  1221. return yield_under(mod, mod, rb_ary_new4(argc, argv));
  1222. }
  1223. /*
  1224. * call-seq:
  1225. * throw(tag [, obj])
  1226. *
  1227. * Transfers control to the end of the active +catch+ block
  1228. * waiting for _tag_. Raises +ArgumentError+ if there
  1229. * is no +catch+ block for the _tag_. The optional second
  1230. * parameter supplies a return value for the +catch+ block,
  1231. * which otherwise defaults to +nil+. For examples, see
  1232. * <code>Kernel::catch</code>.
  1233. */
  1234. static VALUE
  1235. rb_f_throw(int argc, VALUE *argv)
  1236. {
  1237. VALUE tag, value;
  1238. rb_scan_args(argc, argv, "11", &tag, &value);
  1239. rb_throw_obj(tag, value);
  1240. return Qnil; /* not reached */
  1241. }
  1242. void
  1243. rb_throw_obj(VALUE tag, VALUE value)
  1244. {
  1245. rb_thread_t *th = GET_THREAD();
  1246. struct rb_vm_tag *tt = th->tag;
  1247. while (tt) {
  1248. if (tt->tag == tag) {
  1249. tt->retval = value;
  1250. break;
  1251. }
  1252. tt = tt->prev;
  1253. }
  1254. if (!tt) {
  1255. VALUE desc = rb_inspect(tag);
  1256. rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
  1257. }
  1258. rb_trap_restore_mask();
  1259. th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
  1260. JUMP_TAG(TAG_THROW);
  1261. }
  1262. void
  1263. rb_throw(const char *tag, VALUE val)
  1264. {
  1265. rb_throw_obj(ID2SYM(rb_intern(tag)), val);
  1266. }
  1267. static VALUE
  1268. catch_i(VALUE tag, VALUE data)
  1269. {
  1270. return rb_yield_0(1, &tag);
  1271. }
  1272. /*
  1273. * call-seq:
  1274. * catch([arg]) {|tag| block } => obj
  1275. *
  1276. * +catch+ executes its block. If a +throw+ is
  1277. * executed, Ruby searches up its stack for a +catch+ block
  1278. * with a tag corresponding to the +throw+'s
  1279. * _tag_. If found, that block is terminated, and
  1280. * +catch+ returns the value given to +throw+. If
  1281. * +throw+ is not called, the block terminates normally, and
  1282. * the value of +catch+ is the value of the last expression
  1283. * evaluated. +catch+ expressions may be nested, and the
  1284. * +throw+ call need not be in lexical scope.
  1285. *
  1286. * def routine(n)
  1287. * puts n
  1288. * throw :done if n <= 0
  1289. * routine(n-1)
  1290. * end
  1291. *
  1292. *
  1293. * catch(:done) { routine(3) }
  1294. *
  1295. * <em>produces:</em>
  1296. *
  1297. * 3
  1298. * 2
  1299. * 1
  1300. * 0
  1301. *
  1302. * when _arg_ is given, +catch+ yields it as is, or when no
  1303. * _arg_ is given, +catch+ assigns a new unique object to
  1304. * +throw+. this is useful for nested +catch+. _arg_ can
  1305. * be an arbitrary object, not only Symbol.
  1306. *
  1307. */
  1308. static VALUE
  1309. rb_f_catch(int argc, VALUE *argv)
  1310. {
  1311. VALUE tag;
  1312. if (argc == 0) {
  1313. tag = rb_obj_alloc(rb_cObject);
  1314. }
  1315. else {
  1316. rb_scan_args(argc, argv, "01", &tag);
  1317. }
  1318. return rb_catch_obj(tag, catch_i, 0);
  1319. }
  1320. VALUE
  1321. rb_catch(const char *tag, VALUE (*func)(), VALUE data)
  1322. {
  1323. VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
  1324. return rb_catch_obj(vtag, func, data);
  1325. }
  1326. VALUE
  1327. rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
  1328. {
  1329. int state;
  1330. volatile VALUE val = Qnil; /* OK */
  1331. rb_thread_t *th = GET_THREAD();
  1332. rb_control_frame_t *saved_cfp = th->cfp;
  1333. PUSH_TAG();
  1334. th->tag->tag = tag;
  1335. if ((state = EXEC_TAG()) == 0) {
  1336. /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
  1337. val = (*func)(tag, data, 1, &tag, Qnil);
  1338. }
  1339. else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
  1340. th->cfp = saved_cfp;
  1341. val = th->tag->retval;
  1342. th->errinfo = Qnil;
  1343. state = 0;
  1344. }
  1345. POP_TAG();
  1346. if (state)
  1347. JUMP_TAG(state);
  1348. return val;
  1349. }
  1350. /*
  1351. * call-seq:
  1352. * caller(start=1) => array
  1353. *
  1354. * Returns the current execution stack---an array containing strings in
  1355. * the form ``<em>file:line</em>'' or ``<em>file:line: in
  1356. * `method'</em>''. The optional _start_ parameter
  1357. * determines the number of initial stack entries to omit from the
  1358. * result.
  1359. *
  1360. * def a(skip)
  1361. * caller(skip)
  1362. * end
  1363. * def b(skip)
  1364. * a(skip)
  1365. * end
  1366. * def c(skip)
  1367. * b(skip)
  1368. * end
  1369. * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
  1370. * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
  1371. * c(2) #=> ["prog:8:in `c'", "prog:12"]
  1372. * c(3) #=> ["prog:13"]
  1373. */
  1374. static VALUE
  1375. rb_f_caller(int argc, VALUE *argv)
  1376. {
  1377. VALUE level;
  1378. int lev;
  1379. rb_scan_args(argc, argv, "01", &level);
  1380. if (NIL_P(level))
  1381. lev = 1;
  1382. else
  1383. lev = NUM2INT(level);
  1384. if (lev < 0)
  1385. rb_raise(rb_eArgError, "negative level (%d)", lev);
  1386. return vm_backtrace(GET_THREAD(), lev);
  1387. }
  1388. static int
  1389. print_backtrace(void *arg, VALUE file, int line, VALUE method)
  1390. {
  1391. fprintf((FILE *)arg, "\tfrom %s:%d:in `%s'\n",
  1392. RSTRING_PTR(file), line, RSTRING_PTR(method));
  1393. return FALSE;
  1394. }
  1395. void
  1396. rb_backtrace(void)
  1397. {
  1398. vm_backtrace_each(GET_THREAD(), -1, print_backtrace, stderr);
  1399. }
  1400. VALUE
  1401. rb_make_backtrace(void)
  1402. {
  1403. return vm_backtrace(GET_THREAD(), -1);
  1404. }
  1405. VALUE
  1406. rb_thread_backtrace(VALUE thval)
  1407. {
  1408. rb_thread_t *th;
  1409. GetThreadPtr(thval, th);
  1410. switch (th->status) {
  1411. case THREAD_RUNNABLE:
  1412. case THREAD_STOPPED:
  1413. case THREAD_STOPPED_FOREVER:
  1414. break;
  1415. case THREAD_TO_KILL:
  1416. case THREAD_KILLED:
  1417. return Qnil;
  1418. }
  1419. return vm_backtrace(th, 0);
  1420. }
  1421. int
  1422. rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
  1423. {
  1424. return vm_backtrace_each(GET_THREAD(), -1, iter, arg);
  1425. }
  1426. /*
  1427. * call-seq:
  1428. * local_variables => array
  1429. *
  1430. * Returns the names of the current local variables.
  1431. *
  1432. * fred = 1
  1433. * for i in 1..10
  1434. * # ...
  1435. * end
  1436. * local_variables #=> [:fred, :i]
  1437. */
  1438. static VALUE
  1439. rb_f_local_variables(void)
  1440. {
  1441. VALUE ary = rb_ary_new();
  1442. rb_thread_t *th = GET_THREAD();
  1443. rb_control_frame_t *cfp =
  1444. vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
  1445. int i;
  1446. while (cfp) {
  1447. if (cfp->iseq) {
  1448. for (i = 0; i < cfp->iseq->local_table_size; i++) {
  1449. ID lid = cfp->iseq->local_table[i];
  1450. if (lid) {
  1451. const char *vname = rb_id2name(lid);
  1452. /* should skip temporary variable */
  1453. if (vname) {
  1454. rb_ary_push(ary, ID2SYM(lid));
  1455. }
  1456. }
  1457. }
  1458. }
  1459. if (cfp->lfp != cfp->dfp) {
  1460. /* block */
  1461. VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
  1462. if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
  1463. break;
  1464. }
  1465. else {
  1466. while (cfp->dfp != dfp) {
  1467. cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
  1468. }
  1469. }
  1470. }
  1471. else {
  1472. break;
  1473. }
  1474. }
  1475. return ary;
  1476. }
  1477. /*
  1478. * call-seq:
  1479. * block_given? => true or false
  1480. * iterator? => true or false
  1481. *
  1482. * Returns <code>true</code> if <code>yield</code> would execute a
  1483. * block in the current context. The <code>iterator?</code> form
  1484. * is mildly deprecated.
  1485. *
  1486. * def try
  1487. * if block_given?
  1488. * yield
  1489. * else
  1490. * "no block"
  1491. * end
  1492. * end
  1493. * try #=> "no block"
  1494. * try { "hello" } #=> "hello"
  1495. * try do "hello" end #=> "hello"
  1496. */
  1497. VALUE
  1498. rb_f_block_given_p(void)
  1499. {
  1500. rb_thread_t *th = GET_THREAD();
  1501. rb_control_frame_t *cfp = th->cfp;
  1502. cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
  1503. if (cfp != 0 &&
  1504. (cfp->lfp[0] & 0x02) == 0 &&
  1505. GC_GUARDED_PTR_REF(cfp->lfp[0])) {
  1506. return Qtrue;
  1507. }
  1508. else {
  1509. return Qfalse;
  1510. }
  1511. }
  1512. void
  1513. Init_vm_eval(void)
  1514. {
  1515. rb_define_global_function("eval", rb_f_eval, -1);
  1516. rb_define_global_function("local_variables", rb_f_local_variables, 0);
  1517. rb_define_global_function("iterator?", rb_f_block_given_p, 0);
  1518. rb_define_global_function("block_given?", rb_f_block_given_p, 0);
  1519. rb_define_global_function("catch", rb_f_catch, -1);
  1520. rb_define_global_function("throw", rb_f_throw, -1);
  1521. rb_define_global_function("loop", rb_f_loop, 0);
  1522. rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
  1523. rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
  1524. rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
  1525. #if 1
  1526. rb_add_method(rb_cBasicObject, rb_intern("__send__"),
  1527. VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
  1528. rb_add_method(rb_mKernel, rb_intern("send"),
  1529. VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
  1530. #else
  1531. rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
  1532. rb_define_method(rb_mKernel, "send", rb_f_send, -1);
  1533. #endif
  1534. rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
  1535. rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
  1536. rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
  1537. rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
  1538. rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
  1539. rb_define_global_function("caller", rb_f_caller, -1);
  1540. }