mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: allow at-least-once loop behavior for mruby
mruby does not provide `begin ... end while cond` that behave at-least-once loop, like CRuby does. It remains in TODO.md for long time. But finally we have implemented the behavior.
This commit is contained in:
@@ -9,5 +9,4 @@
|
||||
|
||||
# Things to do (Things we need to consider)
|
||||
|
||||
- `begin ... end while cond` to behave as CRuby
|
||||
- special variables ($1,$2..)
|
||||
|
||||
@@ -3679,12 +3679,13 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (!val) lp->reg = -1;
|
||||
|
||||
/* Jump to body start on first iteration */
|
||||
uint32_t body_start = genjmp2_0(s, OP_JMP, cursp(), NOVAL);
|
||||
uint32_t body_start = genjmp_0(s, OP_JMP);
|
||||
|
||||
/* pc0 is next target - condition check */
|
||||
lp->pc0 = new_label(s);
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
uint32_t pos = JMPLINK_START;
|
||||
if (nt == NODE_WHILE_MOD) {
|
||||
pos = genjmp2_0(s, OP_JMPNOT, cursp(), NOVAL);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ enum node_type {
|
||||
NODE_WHEN,
|
||||
NODE_WHILE,
|
||||
NODE_UNTIL,
|
||||
NODE_WHILE_MOD,
|
||||
NODE_UNTIL_MOD,
|
||||
NODE_ITER,
|
||||
NODE_FOR,
|
||||
NODE_BREAK,
|
||||
|
||||
@@ -483,6 +483,22 @@ new_until(parser_state *p, node *a, node *b)
|
||||
return cons((node*)NODE_UNTIL, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:while_mod cond body) */
|
||||
static node*
|
||||
new_while_mod(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_WHILE_MOD, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:until_mod cond body) */
|
||||
static node*
|
||||
new_until_mod(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_UNTIL_MOD, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:for var obj body) */
|
||||
static node*
|
||||
new_for(parser_state *p, node *v, node *o, node *b)
|
||||
@@ -1794,11 +1810,21 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
|
||||
}
|
||||
| stmt modifier_while expr_value
|
||||
{
|
||||
$$ = new_while(p, cond($3), $1);
|
||||
if ($1 && typen($1->car) == NODE_BEGIN) {
|
||||
$$ = new_while_mod(p, cond($3), $1);
|
||||
}
|
||||
else {
|
||||
$$ = new_while(p, cond($3), $1);
|
||||
}
|
||||
}
|
||||
| stmt modifier_until expr_value
|
||||
{
|
||||
$$ = new_until(p, cond($3), $1);
|
||||
if ($1 && typen($1->car) == NODE_BEGIN) {
|
||||
$$ = new_until_mod(p, cond($3), $1);
|
||||
}
|
||||
else {
|
||||
$$ = new_until(p, cond($3), $1);
|
||||
}
|
||||
}
|
||||
| stmt modifier_rescue stmt
|
||||
{
|
||||
@@ -7283,6 +7309,26 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
|
||||
mrb_parser_dump(mrb, tree->cdr, offset+2);
|
||||
break;
|
||||
|
||||
case NODE_WHILE_MOD:
|
||||
printf("NODE_WHILE_MOD:\n");
|
||||
dump_prefix(tree, offset+1);
|
||||
printf("cond:\n");
|
||||
mrb_parser_dump(mrb, tree->car, offset+2);
|
||||
dump_prefix(tree, offset+1);
|
||||
printf("body:\n");
|
||||
mrb_parser_dump(mrb, tree->cdr, offset+2);
|
||||
break;
|
||||
|
||||
case NODE_UNTIL_MOD:
|
||||
printf("NODE_UNTIL_MOD:\n");
|
||||
dump_prefix(tree, offset+1);
|
||||
printf("cond:\n");
|
||||
mrb_parser_dump(mrb, tree->car, offset+2);
|
||||
dump_prefix(tree, offset+1);
|
||||
printf("body:\n");
|
||||
mrb_parser_dump(mrb, tree->cdr, offset+2);
|
||||
break;
|
||||
|
||||
case NODE_FOR:
|
||||
printf("NODE_FOR:\n");
|
||||
dump_prefix(tree, offset+1);
|
||||
|
||||
+1793
-1749
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user