summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/bintest/mrbc.rb9
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c34
-rw-r--r--mrbgems/mruby-compiler/core/parse.y132
3 files changed, 110 insertions, 65 deletions
diff --git a/mrbgems/mruby-compiler/bintest/mrbc.rb b/mrbgems/mruby-compiler/bintest/mrbc.rb
index e4dc6a9a8..e27365edb 100644
--- a/mrbgems/mruby-compiler/bintest/mrbc.rb
+++ b/mrbgems/mruby-compiler/bintest/mrbc.rb
@@ -10,3 +10,12 @@ assert('Compiling multiple files without new line in last line. #2361') do
assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
assert_equal 0, $?.exitstatus
end
+
+assert('parsing function with void argument') do
+ a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb')
+ a.write('f ()')
+ a.flush
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1`
+ assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
+ assert_equal 0, $?.exitstatus
+end
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 0c84dd558..414ca2627 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -772,6 +772,8 @@ attrsym(codegen_scope *s, mrb_sym a)
return mrb_intern(s->mrb, name2, len+1);
}
+#define CALL_MAXARGS 127
+
static int
gen_values(codegen_scope *s, node *t, int val)
{
@@ -780,7 +782,9 @@ gen_values(codegen_scope *s, node *t, int val)
while (t) {
is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
- if (n >= 127 || is_splat) {
+ if (
+ n >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
+ || is_splat) {
if (val) {
if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
codegen(s, t->car->cdr, VAL);
@@ -831,8 +835,6 @@ gen_values(codegen_scope *s, node *t, int val)
return n;
}
-#define CALL_MAXARGS 127
-
static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
{
@@ -1059,7 +1061,9 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
n++;
}
}
- push();
+ if (!val) {
+ push();
+ }
}
}
@@ -1362,6 +1366,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos1, pos2;
node *e = tree->cdr->cdr->car;
+ if (!tree->car) {
+ codegen(s, e, val);
+ return;
+ }
switch ((intptr_t)tree->car->car) {
case NODE_TRUE:
case NODE_INT:
@@ -1512,7 +1520,9 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
if (pos3) dispatch_linked(s, pos3);
if (head) pop();
- genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ if (cursp() != pos) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ }
push();
}
else {
@@ -1798,8 +1808,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
pop();
- if (val && vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ if (val) {
+ if (vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
}
else {
@@ -2024,6 +2036,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
}
+ if (val) push();
break;
case NODE_RETRY:
@@ -2058,6 +2071,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
}
}
+ if (val) push();
}
break;
@@ -2285,7 +2299,11 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
node *n = tree;
- if (!n) break;
+ if (!n) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ break;
+ }
codegen(s, n->car, VAL);
n = n->cdr;
while (n) {
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 0ff7d819c..e81d191d9 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -871,6 +871,7 @@ call_with_block(parser_state *p, node *a, node *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 {
@@ -1936,7 +1937,6 @@ arg_rhs : arg %prec tOP_ASGN
| arg modifier_rescue arg
{
void_expr_error(p, $1);
- void_expr_error(p, $3);
$$ = new_mod_rescue(p, $1, $3);
}
;
@@ -2109,7 +2109,7 @@ primary : literal
}
| tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
{
- $$ = 0;
+ $$ = new_nil(p);
}
| tLPAREN compstmt ')'
{
@@ -2137,17 +2137,9 @@ primary : literal
{
$$ = new_return(p, 0);
}
- | keyword_yield '(' call_args rparen
- {
- $$ = new_yield(p, $3);
- }
- | keyword_yield '(' rparen
- {
- $$ = new_yield(p, 0);
- }
- | keyword_yield
+ | keyword_yield opt_paren_args
{
- $$ = new_yield(p, 0);
+ $$ = new_yield(p, $2);
}
| keyword_not '(' expr rparen
{
@@ -3761,6 +3753,44 @@ scan_hex(const int *start, int len, int *retlen)
return retval;
}
+static int32_t
+read_escape_unicode(parser_state *p, int limit)
+{
+ int32_t c;
+ int buf[9];
+ int i;
+
+ /* Look for opening brace */
+ i = 0;
+ buf[0] = nextc(p);
+ if (buf[0] < 0) goto eof;
+ if (ISXDIGIT(buf[0])) {
+ /* \uxxxx form */
+ for (i=1; i<limit; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (!ISXDIGIT(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ }
+ else {
+ pushback(p, buf[0]);
+ }
+ c = scan_hex(buf, i, &i);
+ if (i == 0) {
+ eof:
+ yyerror(p, "Invalid escape character syntax");
+ return -1;
+ }
+ if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
+ yyerror(p, "Invalid Unicode code point");
+ return -1;
+ }
+ return c;
+}
+
/* Return negative to indicate Unicode code point */
static int32_t
read_escape(parser_state *p)
@@ -3833,53 +3863,17 @@ read_escape(parser_state *p)
return c;
case 'u': /* Unicode */
- {
- int buf[9];
- int i;
-
- /* Look for opening brace */
- i = 0;
- buf[0] = nextc(p);
- if (buf[0] < 0) goto eof;
- if (buf[0] == '{') {
+ if (peek(p, '{')) {
/* \u{xxxxxxxx} form */
- for (i=0; i<9; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (buf[i] == '}') {
- break;
- }
- else if (!ISXDIGIT(buf[i])) {
- yyerror(p, "Invalid escape character syntax");
- pushback(p, buf[i]);
- return 0;
- }
- }
- }
- else if (ISXDIGIT(buf[0])) {
- /* \uxxxx form */
- for (i=1; i<4; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (!ISXDIGIT(buf[i])) {
- pushback(p, buf[i]);
- break;
- }
- }
+ nextc(p);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) return 0;
+ if (nextc(p) != '}') goto eof;
}
else {
- pushback(p, buf[0]);
+ c = read_escape_unicode(p, 4);
+ if (c < 0) return 0;
}
- c = scan_hex(buf, i, &i);
- if (i == 0) {
- yyerror(p, "Invalid escape character syntax");
- return 0;
- }
- if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
- yyerror(p, "Invalid Unicode code point");
- return 0;
- }
- }
return -c;
case 'b':/* backspace */
@@ -4002,6 +3996,20 @@ parse_string(parser_state *p)
tokadd(p, '\\');
tokadd(p, c);
}
+ else if (c == 'u' && peek(p, '{')) {
+ /* \u{xxxx xxxx xxxx} form */
+ nextc(p);
+ while (1) {
+ do c = nextc(p); while (ISSPACE(c));
+ if (c == '}') break;
+ pushback(p, c);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) break;
+ tokadd(p, -c);
+ }
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
else {
pushback(p, c);
tokadd(p, read_escape(p));
@@ -6060,7 +6068,17 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_FCALL:
case NODE_CALL:
- printf("NODE_CALL:\n");
+ case NODE_SCALL:
+ switch (nodetype) {
+ case NODE_FCALL:
+ printf("NODE_FCALL:\n"); break;
+ case NODE_CALL:
+ printf("NODE_CALL(.):\n"); break;
+ case NODE_SCALL:
+ printf("NODE_SCALL(&.):\n"); break;
+ default:
+ break;
+ }
mrb_parser_dump(mrb, tree->car, offset+1);
dump_prefix(tree, offset+1);
printf("method='%s' (%d)\n",
@@ -6541,7 +6559,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_HEREDOC:
printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term);
- mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+ dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
break;
default: