diff options
Diffstat (limited to 'mrbgems/mruby-compiler/core/parse.y')
| -rw-r--r-- | mrbgems/mruby-compiler/core/parse.y | 384 |
1 files changed, 231 insertions, 153 deletions
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 2c2bff714..ed4265a16 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -13,7 +13,6 @@ #include <ctype.h> #include <errno.h> -#include <stdlib.h> #include <string.h> #include <mruby.h> #include <mruby/compile.h> @@ -34,7 +33,6 @@ typedef struct mrb_parser_heredoc_info parser_heredoc_info; static int yyparse(parser_state *p); static int yylex(void *lval, parser_state *p); static void yyerror(parser_state *p, const char *s); -static void yywarn(parser_state *p, const char *s); static void yywarning(parser_state *p, const char *s); static void backref_error(parser_state *p, node *n); static void void_expr_error(parser_state *p, node *n); @@ -106,7 +104,7 @@ parser_palloc(parser_state *p, size_t size) void *m = mrb_pool_alloc(p->pool, size); if (!m) { - MRB_THROW(p->jmp); + MRB_THROW(p->mrb->jmp); } return m; } @@ -286,9 +284,10 @@ local_var_p(parser_state *p, mrb_sym sym) const mrb_sym *v = ir->lv; int i; - if (!v) break; - for (i=0; i+1 < ir->nlocals; i++) { - if (v[i] == sym) return TRUE; + if (v) { + for (i=0; i+1 < ir->nlocals; i++) { + if (v[i] == sym) return TRUE; + } } if (MRB_PROC_SCOPE_P(u)) break; u = u->upper; @@ -500,13 +499,18 @@ new_call(parser_state *p, node *a, mrb_sym b, node *c, int pass) static node* new_fcall(parser_state *p, mrb_sym b, node *c) { - node *n = new_self(p); - NODE_LINENO(n, c); - n = list4((node*)NODE_FCALL, n, nsym(b), c); + node *n = list4((node*)NODE_FCALL, 0, nsym(b), c); NODE_LINENO(n, c); return n; } +/* (a b . c) */ +static node* +new_callargs(parser_state *p, node *a, node *b, node *c) +{ + return cons(a, cons(b, c)); +} + /* (:super . c) */ static node* new_super(parser_state *p, node *c) @@ -518,7 +522,7 @@ new_super(parser_state *p, node *c) static node* new_zsuper(parser_state *p) { - return list1((node*)NODE_ZSUPER); + return cons((node*)NODE_ZSUPER, 0); } /* (:yield . c) */ @@ -527,7 +531,12 @@ new_yield(parser_state *p, node *c) { if (c) { if (c->cdr) { - yyerror(p, "both block arg and actual block given"); + if (c->cdr->cdr) { + yyerror(p, "both block arg and actual block given"); + } + if (c->cdr->car) { + return cons((node*)NODE_YIELD, push(c->car, c->cdr->car)); + } } return cons((node*)NODE_YIELD, c->car); } @@ -961,13 +970,14 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) static node* new_imaginary(parser_state *p, node *imaginary) { - return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Complex), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1); + return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Complex), + new_callargs(p, list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary), 0, 0), 1); } static node* new_rational(parser_state *p, node *rational) { - return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Rational), list1(list1(rational)), 1); + return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Rational), new_callargs(p, list1(rational), 0, 0), 1); } /* (:int . i) */ @@ -1190,17 +1200,17 @@ call_uni_op(parser_state *p, node *recv, const char *m) static node* call_bin_op(parser_state *p, node *recv, const char *m, node *arg1) { - return new_call(p, recv, intern_cstr(m), list1(list1(arg1)), 1); + return new_call(p, recv, intern_cstr(m), new_callargs(p, list1(arg1), 0, 0), 1); } static void args_with_block(parser_state *p, node *a, node *b) { if (b) { - if (a->cdr) { + if (a->cdr && a->cdr->cdr) { yyerror(p, "both block arg and actual block given"); } - a->cdr = b; + a->cdr->cdr = b; } } @@ -1227,19 +1237,16 @@ call_with_block(parser_state *p, node *a, node *b) switch (typen(a->car)) { case NODE_SUPER: case NODE_ZSUPER: - if (!a->cdr) a->cdr = cons(0, b); - else { - args_with_block(p, a->cdr, b); - } + if (!a->cdr) a->cdr = new_callargs(p, 0, 0, b); + else args_with_block(p, a->cdr, b); break; case NODE_CALL: case NODE_FCALL: case NODE_SCALL: - n = a->cdr->cdr->cdr; - if (!n->car) n->car = cons(0, b); - else { - args_with_block(p, n->car, b); - } + /* (NODE_CALL recv mid (args kw . blk)) */ + n = a->cdr->cdr->cdr; /* (args kw . blk) */ + if (!n->car) n->car = new_callargs(p, 0, 0, b); + else args_with_block(p, n->car, b); break; default: break; @@ -1247,7 +1254,7 @@ call_with_block(parser_state *p, node *a, node *b) } static node* -negate_lit(parser_state *p, node *n) +new_negate(parser_state *p, node *n) { return cons((node*)NODE_NEGATE, n); } @@ -1261,10 +1268,11 @@ cond(node *n) static node* ret_args(parser_state *p, node *n) { - if (n->cdr) { + if (n->cdr->cdr) { yyerror(p, "block argument should not be given"); return NULL; } + if (!n->car) return NULL; if (!n->car->cdr) return n->car->car; return new_array(p, n->car); } @@ -1293,6 +1301,24 @@ var_reference(parser_state *p, node *lhs) return lhs; } +static node* +label_reference(parser_state *p, mrb_sym sym) +{ + const char *name = mrb_sym_name(p->mrb, sym); + node *n; + + if (local_var_p(p, sym)) { + n = new_lvar(p, sym); + } + else if (ISUPPER(name[0])) { + n = new_const(p, sym); + } + else { + n = new_fcall(p, sym, 0); + } + return n; +} + typedef enum mrb_string_type string_type; static node* @@ -1623,7 +1649,7 @@ bodystmt : compstmt NODE_LINENO($$, $1); } else if ($3) { - yywarn(p, "else without rescue is useless"); + yywarning(p, "else without rescue is useless"); $$ = push($1, $3); } else { @@ -1754,6 +1780,44 @@ command_asgn : lhs '=' command_rhs { $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5); } + | defn_head f_opt_arglist_paren '=' command + { + $$ = $1; + endless_method_name(p, $1); + void_expr_error(p, $4); + defn_setup(p, $$, $2, $4); + nvars_unnest(p); + p->in_def--; + } + | defn_head f_opt_arglist_paren '=' command modifier_rescue arg + { + $$ = $1; + endless_method_name(p, $1); + void_expr_error(p, $4); + void_expr_error(p, $6); + defn_setup(p, $$, $2, new_mod_rescue(p, $4, $6)); + nvars_unnest(p); + p->in_def--; + } + | defs_head f_opt_arglist_paren '=' command + { + $$ = $1; + void_expr_error(p, $4); + defs_setup(p, $$, $2, $4); + nvars_unnest(p); + p->in_def--; + p->in_single--; + } + | defs_head f_opt_arglist_paren '=' command modifier_rescue arg + { + $$ = $1; + void_expr_error(p, $4); + void_expr_error(p, $6); + defs_setup(p, $$, $2, new_mod_rescue(p, $4, $6)); + nvars_unnest(p); + p->in_def--; + p->in_single--; + } | backref tOP_ASGN command_rhs { backref_error(p, $1); @@ -2253,11 +2317,11 @@ arg : lhs '=' arg_rhs } | tUMINUS_NUM tINTEGER tPOW arg { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); + $$ = new_negate(p, call_bin_op(p, $2, "**", $4)); } | tUMINUS_NUM tFLOAT tPOW arg { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); + $$ = new_negate(p, call_bin_op(p, $2, "**", $4)); } | tUPLUS arg { @@ -2265,7 +2329,7 @@ arg : lhs '=' arg_rhs } | tUMINUS arg { - $$ = call_uni_op(p, $2, "-@"); + $$ = new_negate(p, $2); } | arg '|' arg { @@ -2370,7 +2434,7 @@ arg : lhs '=' arg_rhs nvars_unnest(p); p->in_def--; } - | defs_head f_arglist_paren '=' arg + | defs_head f_opt_arglist_paren '=' arg { $$ = $1; void_expr_error(p, $4); @@ -2379,7 +2443,7 @@ arg : lhs '=' arg_rhs p->in_def--; p->in_single--; } - | defs_head f_arglist_paren '=' arg modifier_rescue arg + | defs_head f_opt_arglist_paren '=' arg modifier_rescue arg { $$ = $1; void_expr_error(p, $4); @@ -2403,7 +2467,7 @@ aref_args : none } | args comma assocs trailer { - $$ = push($1, new_kw_hash(p, $3)); + $$ = push($1, new_hash(p, $3)); } | assocs trailer { @@ -2430,39 +2494,23 @@ paren_args : '(' opt_call_args ')' } | '(' args comma tBDOT3 rparen { -#if 1 - mrb_sym r = intern_op(mul); - mrb_sym b = intern_op(and); - $$ = cons(push($2, new_splat(p, new_lvar(p, r))), - new_block_arg(p, new_lvar(p, b))); -#else mrb_sym r = intern_op(mul); mrb_sym k = intern_op(pow); mrb_sym b = intern_op(and); - $$ = cons(list2(push($2, new_splat(p, new_lvar(p, r))), - new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k))))), - new_block_arg(p, new_lvar(p, b))); -#endif + $$ = new_callargs(p, push($2, new_splat(p, new_lvar(p, r))), + new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k)))), + new_block_arg(p, new_lvar(p, b))); } | '(' tBDOT3 rparen { -#if 1 - mrb_sym r = intern_op(mul); - mrb_sym b = intern_op(and); - if (local_var_p(p, r) && local_var_p(p, b)) { - $$ = cons(list1(new_splat(p, new_lvar(p, r))), - new_block_arg(p, new_lvar(p, b))); - } -#else mrb_sym r = intern_op(mul); mrb_sym k = intern_op(pow); mrb_sym b = intern_op(and); if (local_var_p(p, r) && local_var_p(p, k) && local_var_p(p, b)) { - $$ = cons(list2(new_splat(p, new_lvar(p, r)), - new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k))))), - new_block_arg(p, new_lvar(p, b))); + $$ = new_callargs(p, list1(new_splat(p, new_lvar(p, r))), + new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k)))), + new_block_arg(p, new_lvar(p, b))); } -#endif else { yyerror(p, "unexpected argument forwarding ..."); $$ = 0; @@ -2478,17 +2526,17 @@ opt_call_args : none | call_args opt_terms | args comma { - $$ = cons($1,0); + $$ = new_callargs(p,$1,0,0); NODE_LINENO($$, $1); } | args comma assocs comma { - $$ = cons(push($1, new_kw_hash(p, $3)), 0); + $$ = new_callargs(p,$1,new_kw_hash(p,$3),0); NODE_LINENO($$, $1); } | assocs comma { - $$ = cons(list1(new_kw_hash(p, $1)), 0); + $$ = new_callargs(p,0,new_kw_hash(p,$1),0); NODE_LINENO($$, $1); } ; @@ -2496,27 +2544,27 @@ opt_call_args : none call_args : command { void_expr_error(p, $1); - $$ = cons(list1($1), 0); + $$ = new_callargs(p, list1($1), 0, 0); NODE_LINENO($$, $1); } | args opt_block_arg { - $$ = cons($1, $2); + $$ = new_callargs(p, $1, 0, $2); NODE_LINENO($$, $1); } | assocs opt_block_arg { - $$ = cons(list1(new_kw_hash(p, $1)), $2); + $$ = new_callargs(p, 0, new_kw_hash(p, $1), $2); NODE_LINENO($$, $1); } | args comma assocs opt_block_arg { - $$ = cons(push($1, new_kw_hash(p, $3)), $4); + $$ = new_callargs(p, $1, new_kw_hash(p, $3), $4); NODE_LINENO($$, $1); } | block_arg { - $$ = cons(0, $1); + $$ = new_callargs(p, 0, 0, $1); NODE_LINENO($$, $1); } ; @@ -2548,20 +2596,19 @@ opt_block_arg : comma block_arg } ; -comma : ',' - | ',' opt_nl heredoc_bodies +comma : ',' opt_nl ; args : arg { void_expr_error(p, $1); - $$ = cons($1, 0); + $$ = list1($1); NODE_LINENO($$, $1); } | tSTAR arg { void_expr_error(p, $2); - $$ = cons(new_splat(p, $2), 0); + $$ = list1(new_splat(p, $2)); NODE_LINENO($$, $2); } | args comma arg @@ -2673,7 +2720,7 @@ primary : literal } | operation brace_block { - $$ = new_fcall(p, $1, cons(0, $2)); + $$ = new_fcall(p, $1, new_callargs(p, 0, 0, $2)); } | method_call | method_call brace_block @@ -3268,7 +3315,14 @@ string_fragment : tCHAR } | tSTRING_BEG string_rep tSTRING { - $$ = new_dstr(p, push($2, $3)); + node *n = $2; + if (intn($3->cdr->cdr) > 0) { + n = push(n, $3); + } + else { + cons_free($3); + } + $$ = new_dstr(p, n); } ; @@ -3310,7 +3364,14 @@ xstring : tXSTRING_BEG tXSTRING } | tXSTRING_BEG string_rep tXSTRING { - $$ = new_dxstr(p, push($2, $3)); + node *n = $2; + if (intn($3->cdr->cdr) > 0) { + n = push(n, $3); + } + else { + cons_free($3); + } + $$ = new_dxstr(p, n); } ; @@ -3373,7 +3434,14 @@ words : tWORDS_BEG tSTRING } | tWORDS_BEG string_rep tSTRING { - $$ = new_words(p, push($2, $3)); + node *n = $2; + if (intn($3->cdr->cdr) > 0) { + n = push(n, $3); + } + else { + cons_free($3); + } + $$ = new_words(p, n); } ; @@ -3385,8 +3453,15 @@ symbol : basic_symbol } | tSYMBEG tSTRING_BEG string_rep tSTRING { + node *n = $3; p->lstate = EXPR_ENDARG; - $$ = new_dsym(p, new_dstr(p, push($3, $4))); + if (intn($4->cdr->cdr) > 0) { + n = push(n, $4); + } + else { + cons_free($4); + } + $$ = new_dsym(p, new_dstr(p, n)); } ; @@ -3416,7 +3491,11 @@ symbols : tSYMBOLS_BEG tSTRING } | tSYMBOLS_BEG string_rep tSTRING { - $$ = new_symbols(p, push($2, $3)); + node *n = $2; + if (intn($3->cdr->cdr) > 0) { + n = push(n, $3); + } + $$ = new_symbols(p, n); } ; @@ -3424,11 +3503,11 @@ numeric : tINTEGER | tFLOAT | tUMINUS_NUM tINTEGER %prec tLOWEST { - $$ = negate_lit(p, $2); + $$ = new_negate(p, $2); } | tUMINUS_NUM tFLOAT %prec tLOWEST { - $$ = negate_lit(p, $2); + $$ = new_negate(p, $2); } ; @@ -3501,12 +3580,7 @@ var_ref : variable } | keyword__ENCODING__ { -#ifdef MRB_UTF8_STRING - const char *enc = "UTF-8"; -#else - const char *enc = "ASCII-8BIT"; -#endif - $$ = new_str(p, enc, strlen(enc)); + $$ = new_fcall(p, MRB_SYM_2(p->mrb, __ENCODING__), 0); } ; @@ -3547,39 +3621,21 @@ f_arglist_paren : '(' f_args rparen } | '(' f_arg ',' tBDOT3 rparen { -#if 1 - /* til real keyword args implemented */ - mrb_sym r = intern_op(mul); - mrb_sym b = intern_op(and); - local_add_f(p, r); - $$ = new_args(p, $2, 0, r, 0, - new_args_tail(p, 0, 0, b)); -#else mrb_sym r = intern_op(mul); mrb_sym k = intern_op(pow); mrb_sym b = intern_op(and); - local_add_f(p, r); local_add_f(p, k); + local_add_f(p, r); $$ = new_args(p, $2, 0, r, 0, new_args_tail(p, 0, new_kw_rest_args(p, nsym(k)), b)); -#endif } | '(' tBDOT3 rparen { -#if 1 - /* til real keyword args implemented */ - mrb_sym r = intern_op(mul); - mrb_sym b = intern_op(and); - local_add_f(p, r); - $$ = new_args(p, 0, 0, r, 0, - new_args_tail(p, 0, 0, b)); -#else mrb_sym r = intern_op(mul); mrb_sym k = intern_op(pow); mrb_sym b = intern_op(and); - local_add_f(p, r); local_add_f(p, k); + local_add_f(p, r); $$ = new_args(p, 0, 0, r, 0, new_args_tail(p, 0, new_kw_rest_args(p, nsym(k)), b)); -#endif } ; @@ -3938,22 +3994,22 @@ assocs : assoc } ; -label_tag : tLABEL_TAG - | tLABEL_TAG heredoc_bodies - ; - assoc : arg tASSOC arg { void_expr_error(p, $1); void_expr_error(p, $3); $$ = cons($1, $3); } - | tIDENTIFIER label_tag arg + | tIDENTIFIER tLABEL_TAG arg { void_expr_error(p, $3); $$ = cons(new_sym(p, $1), $3); } - | string_fragment label_tag arg + | tIDENTIFIER tLABEL_TAG + { + $$ = cons(new_sym(p, $1), label_reference(p, $1)); + } + | string_fragment tLABEL_TAG arg { void_expr_error(p, $3); if (typen($1->car) == NODE_DSTR) { @@ -4012,7 +4068,7 @@ opt_terms : /* none */ ; opt_nl : /* none */ - | nl + | opt_nl nl ; rparen : opt_terms ')' @@ -4025,7 +4081,6 @@ trailer : /* none */ term : ';' {yyerrok;} | nl - | heredoc_body ; nl : '\n' @@ -4033,6 +4088,7 @@ nl : '\n' p->lineno += $<num>1; p->column = 0; } + | heredoc_body ; terms : term @@ -4087,7 +4143,7 @@ yyerror_c(parser_state *p, const char *msg, char c) } static void -yywarn(parser_state *p, const char *s) +yywarning(parser_state *p, const char *s) { char* c; size_t n; @@ -4115,12 +4171,6 @@ yywarn(parser_state *p, const char *s) } static void -yywarning(parser_state *p, const char *s) -{ - yywarn(p, s); -} - -static void yywarning_s(parser_state *p, const char *msg, const char *s) { char buf[256]; @@ -6225,10 +6275,10 @@ parser_yylex(parser_state *p) if (last_state == EXPR_FNAME) goto gvar; tokfix(p); { - unsigned long n = strtoul(tok(p), NULL, 10); - if (n > INT_MAX) { - yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX)); - return 0; + mrb_int n = mrb_int_read(tok(p), NULL, NULL); + if (n > INT32_MAX) { + yywarning(p, "capture group index too big; always nil"); + return keyword_nil; } pylval.nd = new_nth_ref(p, (int)n); } @@ -6513,6 +6563,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt) int i = 0; if (!cxt) return; + if (!p->tree) return; if (intn(p->tree->car) != NODE_SCOPE) return; n0 = n = p->tree->cdr->car; while (n) { @@ -6533,53 +6584,39 @@ MRB_API void mrb_parser_parse(parser_state *p, mrbc_context *c) { struct mrb_jmpbuf buf1; - p->jmp = &buf1; + struct mrb_jmpbuf *prev = p->mrb->jmp; + p->mrb->jmp = &buf1; - MRB_TRY(p->jmp) { + MRB_TRY(p->mrb->jmp) { int n = 1; p->cmd_start = TRUE; p->in_def = p->in_single = 0; p->nerr = p->nwarn = 0; p->lex_strterm = NULL; - parser_init_cxt(p, c); - if (p->mrb->jmp) { - n = yyparse(p); - } - else { - struct mrb_jmpbuf buf2; - - p->mrb->jmp = &buf2; - MRB_TRY(p->mrb->jmp) { - n = yyparse(p); - } - MRB_CATCH(p->mrb->jmp) { - p->nerr++; - } - MRB_END_EXC(p->mrb->jmp); - p->mrb->jmp = 0; - } + n = yyparse(p); if (n != 0 || p->nerr > 0) { p->tree = 0; + p->mrb->jmp = prev; return; } - if (!p->tree) { - p->tree = new_nil(p); - } parser_update_cxt(p, c); if (c && c->dump_result) { mrb_parser_dump(p->mrb, p->tree, 0); } } - MRB_CATCH(p->jmp) { - yyerror(p, "memory allocation error"); + MRB_CATCH(p->mrb->jmp) { p->nerr++; - p->tree = 0; - return; + if (p->mrb->exc == NULL) { + yyerror(p, "memory allocation error"); + p->nerr++; + p->tree = 0; + } } MRB_END_EXC(p->jmp); + p->mrb->jmp = prev; } MRB_API parser_state* @@ -6964,8 +7001,13 @@ dump_args(mrb_state *mrb, node *n, int offset) } n = n->cdr; if (n->car) { + mrb_sym rest = sym(n->car); + dump_prefix(n, offset+1); - printf("rest=*%s\n", mrb_sym_name(mrb, sym(n->car))); + if (rest == MRB_OPSYM(mul)) + printf("rest=*\n"); + else + printf("rest=*%s\n", mrb_sym_name(mrb, rest)); } n = n->cdr; if (n->car) { @@ -7242,9 +7284,16 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) printf("args:\n"); dump_recur(mrb, tree->car, offset+2); if (tree->cdr) { - dump_prefix(tree, offset+1); - printf("block:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); + if (tree->cdr->car) { + dump_prefix(tree, offset+1); + printf("kwargs:\n"); + mrb_parser_dump(mrb, tree->cdr->car, offset+2); + } + if (tree->cdr->cdr) { + dump_prefix(tree, offset+1); + printf("block:\n"); + mrb_parser_dump(mrb, tree->cdr->cdr, offset+2); + } } } break; @@ -7385,7 +7434,17 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) break; case NODE_ZSUPER: - printf("NODE_ZSUPER\n"); + printf("NODE_ZSUPER:\n"); + if (tree) { + dump_prefix(tree, offset+1); + printf("args:\n"); + dump_recur(mrb, tree->car, offset+2); + if (tree->cdr) { + dump_prefix(tree, offset+1); + printf("block:\n"); + mrb_parser_dump(mrb, tree->cdr, offset+2); + } + } break; case NODE_RETURN: @@ -7711,7 +7770,10 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) break; case NODE_KW_REST_ARGS: - printf("NODE_KW_REST_ARGS %s\n", mrb_sym_name(mrb, sym(tree))); + if (tree) + printf("NODE_KW_REST_ARGS %s\n", mrb_sym_name(mrb, sym(tree))); + else + printf("NODE_KW_REST_ARGS\n"); break; default: @@ -7720,3 +7782,19 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) } #endif } + +typedef mrb_bool mrb_parser_foreach_top_variable_func(mrb_state *mrb, mrb_sym sym, void *user); +void mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user); + +void +mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user) +{ + const mrb_ast_node *n = p->tree; + if ((intptr_t)n->car == NODE_SCOPE) { + n = n->cdr->car; + for (; n; n = n->cdr) { + mrb_sym sym = sym(n->car); + if (sym && !func(mrb, sym, user)) break; + } + } +} |
