diff options
| author | Hiroshi Mimaki <[email protected]> | 2018-11-27 09:09:20 +0900 |
|---|---|---|
| committer | Hiroshi Mimaki <[email protected]> | 2018-11-27 09:09:20 +0900 |
| commit | e3ae0e4f2962418106875217adcd4f5971ce4689 (patch) | |
| tree | 3000278ca91d089918c3b6103aedcff71baed99d | |
| parent | 0711c861ca939c73bed9d91601f6cc38bdf474ba (diff) | |
| parent | 26475d0a7897c25f8632b776014a19c3a6f6ecc2 (diff) | |
| download | mruby-e3ae0e4f2962418106875217adcd4f5971ce4689.tar.gz mruby-e3ae0e4f2962418106875217adcd4f5971ce4689.zip | |
Merge branch 'master' into stable
| -rw-r--r-- | doc/limitations.md | 22 | ||||
| -rw-r--r-- | include/mruby/irep.h | 5 | ||||
| -rw-r--r-- | include/mruby/throw.h | 8 | ||||
| -rw-r--r-- | mrbgems/mruby-array-ext/mrblib/array.rb | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 12 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 40 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/parse.y | 67 |
7 files changed, 112 insertions, 44 deletions
diff --git a/doc/limitations.md b/doc/limitations.md index 92858cb1f..825435f01 100644 --- a/doc/limitations.md +++ b/doc/limitations.md @@ -219,7 +219,7 @@ $ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' [[{"a"=>1}], {:b=>2}] ``` -#### mruby [] +#### mruby [mruby 2.0.0] ``` $ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)' @@ -227,3 +227,23 @@ trace (most recent call last): [0] -e:1 -e:1: keyword argument hash with non symbol keys (ArgumentError) ``` + +## Argument Destructuring + +```ruby +def m(a,(b,c),d); p [a,b,c,d]; end +m(1,[2,3],4) # => [1,2,3,4] +``` +Destructured arguments (`b` and `c` in above example) cannot be accessed +from the default expression of optional arguments and keyword arguments, +since actual assignment is done after the evaluation of those default +expressions. Thus: + +```ruby +def f(a,(b,c),d=b) + p [a,b,c,d] +end +f(1,[2,3]) +``` + +CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`. diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 78cbc2b74..027a294d5 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -48,8 +48,13 @@ typedef struct mrb_irep { #define MRB_ISEQ_NO_FREE 1 MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb); + +/* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*); + +/* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*); + void mrb_irep_free(mrb_state*, struct mrb_irep*); void mrb_irep_incref(mrb_state*, struct mrb_irep*); void mrb_irep_decref(mrb_state*, struct mrb_irep*); diff --git a/include/mruby/throw.h b/include/mruby/throw.h index 5d3d214e7..4a1fd8d60 100644 --- a/include/mruby/throw.h +++ b/include/mruby/throw.h @@ -15,9 +15,9 @@ #if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) -#define MRB_TRY(buf) do { try { +#define MRB_TRY(buf) try { #define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; } -#define MRB_END_EXC(buf) } } while(0) +#define MRB_END_EXC(buf) } #define MRB_THROW(buf) throw((buf)->impl) typedef mrb_int mrb_jmpbuf_impl; @@ -34,9 +34,9 @@ typedef mrb_int mrb_jmpbuf_impl; #define MRB_LONGJMP longjmp #endif -#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) { +#define MRB_TRY(buf) if (MRB_SETJMP((buf)->impl) == 0) { #define MRB_CATCH(buf) } else { -#define MRB_END_EXC(buf) } } while(0) +#define MRB_END_EXC(buf) } #define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1); #define mrb_jmpbuf_impl jmp_buf diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index bb95d70c5..6096696cb 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -291,7 +291,7 @@ class Array # #=> "100 is out of bounds" # - def fetch(n=nil, ifnone=NONE, &block) + def fetch(n, ifnone=NONE, &block) warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block idx = n diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 19f533acd..8d7c719d8 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -56,6 +56,7 @@ #include <mruby/dump.h> #include <mruby/string.h> #include <mruby/variable.h> +#include <mruby/throw.h> #ifdef ENABLE_READLINE @@ -491,7 +492,10 @@ main(int argc, char **argv) while (TRUE) { char *utf8; + struct mrb_jmpbuf c_jmp; + MRB_TRY(&c_jmp); + mrb->jmp = &c_jmp; if (args.rfp) { if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL) goto done; @@ -555,8 +559,7 @@ main(int argc, char **argv) MIRB_LINE_FREE(line); #endif -done: - + done: if (code_block_open) { if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) { fputs("concatenated input string too long\n", stderr); @@ -648,6 +651,11 @@ done: } mrb_parser_free(parser); cxt->lineno++; + MRB_CATCH(&c_jmp) { + p(mrb, mrb_obj_value(mrb->exc), 0); + mrb->exc = 0; + } + MRB_END_EXC(&c_jmp); } #ifdef ENABLE_READLINE diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index ba7d8cf63..b3659863b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -734,15 +734,13 @@ lambda_body(codegen_scope *s, node *tree, int blk) mrb_aspec a; int ma, oa, ra, pa, ka, kd, ba; int pos, i; - node *n, *opt; + node *opt; + node *margs, *pargs; node *tail; /* mandatory arguments */ ma = node_len(tree->car->car); - n = tree->car->car; - while (n) { - n = n->cdr; - } + margs = tree->car->car; tail = tree->car->cdr->cdr->cdr->cdr; /* optional arguments */ @@ -751,6 +749,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) ra = tree->car->cdr->cdr->car ? 1 : 0; /* mandatory arugments after rest argument */ pa = node_len(tree->car->cdr->cdr->cdr->car); + pargs = tree->car->cdr->cdr->cdr->car; /* keyword arguments */ ka = tail? node_len(tail->cdr->car) : 0; /* keyword dictionary? */ @@ -798,6 +797,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) dispatch(s, pos+i*3+1); } + /* keyword arguments */ if (tail) { node *kwds = tail->cdr->car; int kwrest = 0; @@ -836,7 +836,34 @@ lambda_body(codegen_scope *s, node *tree, int blk) genop_0(s, OP_KEYEND); } } + + /* argument destructuring */ + if (margs) { + node *n = margs; + + pos = 1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } + if (pargs) { + node *n = margs; + + pos = ma+oa+ra+1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } } + codegen(s, tree->cdr->car, VAL); pop(); if (s->pc > 0) { @@ -1066,6 +1093,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) idx = new_sym(s, nsym(tree)); genop_2(s, OP_SETGV, sp, idx); break; + case NODE_ARG: case NODE_LVAR: idx = lv_idx(s, nsym(tree)); if (idx > 0) { @@ -1173,7 +1201,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) pop_n(post+1); genop_3(s, OP_APOST, cursp(), n, post); n = 1; - if (t->car) { /* rest */ + if (t->car && t->car != (node*)-1) { /* rest */ gen_assignment(s, t->car, cursp(), NOVAL); } if (t->cdr && t->cdr->car) { diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 70b9d0fc4..d143344c3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -682,6 +682,25 @@ new_arg(parser_state *p, mrb_sym sym) return cons((node*)NODE_ARG, nsym(sym)); } +static void +local_add_margs(parser_state *p, node *n) +{ + while (n) { + if (n->car->car == (node*)NODE_MASGN) { + node *t = n->car->cdr->cdr; + + n->car->cdr->cdr = NULL; + while (t) { + local_add_f(p, sym(t->car)); + t = t->cdr; + } + local_add_margs(p, n->car->cdr->car->car); + local_add_margs(p, n->car->cdr->car->cdr->cdr->car); + } + n = n->cdr; + } +} + /* (m o r m2 tail) */ /* m: (a b c) */ /* o: ((a . e1) (b . e2)) */ @@ -693,6 +712,8 @@ new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail { node *n; + local_add_margs(p, m); + local_add_margs(p, m2); n = cons(m2, tail); n = cons(nsym(rest), n); n = cons(opt, n); @@ -1171,7 +1192,7 @@ heredoc_end(parser_state *p) %type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs %type <nd> command_asgn command_rhs mrhs superclass block_call block_command %type <nd> f_block_optarg f_block_opt -%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs +%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_margs %type <nd> assoc_list assocs assoc undef_list backref for_var %type <nd> block_param opt_block_param block_param_def f_opt %type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body @@ -2447,44 +2468,24 @@ for_var : lhs | mlhs ; -f_marg : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_marg_list : f_marg - { - $$ = list1($1); - } - | f_marg_list ',' f_marg - { - $$ = push($1, $3); - } - ; - -f_margs : f_marg_list +f_margs : f_arg { $$ = list3($1,0,0); } - | f_marg_list ',' tSTAR f_norm_arg + | f_arg ',' tSTAR f_norm_arg { $$ = list3($1, new_arg(p, $4), 0); } - | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list + | f_arg ',' tSTAR f_norm_arg ',' f_arg { $$ = list3($1, new_arg(p, $4), $6); } - | f_marg_list ',' tSTAR + | f_arg ',' tSTAR { local_add_f(p, 0); $$ = list3($1, (node*)-1, 0); } - | f_marg_list ',' tSTAR ',' f_marg_list + | f_arg ',' tSTAR ',' f_arg { $$ = list3($1, (node*)-1, $5); } @@ -2492,7 +2493,7 @@ f_margs : f_marg_list { $$ = list3(0, new_arg(p, $2), 0); } - | tSTAR f_norm_arg ',' f_marg_list + | tSTAR f_norm_arg ',' f_arg { $$ = list3(0, new_arg(p, $2), $4); } @@ -2505,7 +2506,7 @@ f_margs : f_marg_list { local_add_f(p, 0); } - f_marg_list + f_arg { $$ = list3(0, (node*)-1, $4); } @@ -3295,9 +3296,15 @@ f_arg_item : f_norm_arg { $$ = new_arg(p, $1); } - | tLPAREN f_margs rparen + | tLPAREN + { + $<nd>$ = local_switch(p); + } + f_margs rparen { - $$ = new_masgn(p, $2, 0); + $$ = new_masgn(p, $3, p->locals->car); + local_resume(p, $<nd>2); + local_add_f(p, 0); } ; |
