diff --git a/compile.c b/compile.c index 370a1f4522..97b4a874c5 100644 --- a/compile.c +++ b/compile.c @@ -7056,6 +7056,15 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i return COMPILE_OK; } +static void +compile_lvar(rb_iseq_t *iseq, LINK_ANCHOR *const ret, int line, ID id) +{ + int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id); + + debugs("id: %s idx: %d\n", rb_id2name(id), idx); + ADD_GETLOCAL(ret, line, idx, get_lvar_level(iseq)); +} + static LABEL * qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, const NODE *node, int line) { @@ -7282,6 +7291,20 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD iseq->body->builtin_inline_p = true; return COMPILE_OK; } + else if (strcmp("arg!", builtin_func) == 0) { + if (!args_node) goto bad_arg; + if (nd_type(args_node) != NODE_LIST) goto bad_arg; + if (args_node->nd_next) goto bad_arg; + args_node = args_node->nd_head; + if (nd_type(args_node) != NODE_LIT) goto bad_arg; + if (!SYMBOL_P(args_node->nd_lit)) goto bad_arg; + if (!popped) { + compile_lvar(iseq, ret, line, SYM2ID(args_node->nd_lit)); + } + return COMPILE_OK; + bad_arg: + rb_bug("unexpected argument to arg!"); + } else if (1) { rb_bug("can't find builtin function:%s", builtin_func); } @@ -8272,11 +8295,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in } case NODE_LVAR:{ if (!popped) { - ID id = node->nd_vid; - int idx = body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id); - - debugs("id: %s idx: %d\n", rb_id2name(id), idx); - ADD_GETLOCAL(ret, line, idx, get_lvar_level(iseq)); + compile_lvar(iseq, ret, line, node->nd_vid); } break; } diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 17f0d99a50..4b8e1ed1d1 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -156,6 +156,12 @@ def collect_builtin base, tree, name, bs, inlines, locals = nil func_name = nil # required inlines[inlines.size] = [lineno, text, nil, nil] argc -= 1 + when 'arg' + argc == 1 or raise "unexpected argument number #{argc}" + (arg = args.first)[0] == :symbol_literal or raise "symbol literal expected #{args}" + (arg = arg[1])[0] == :symbol or raise "symbol expected #{arg}" + (var = arg[1] and var = var[1]) or raise "argument name expected #{arg}" + func_name = nil end end