ref: 26fef326df126ced69c6eb4f531b487de37e23c7
parent: a14644877bbb7cbe45cbd006f2773a3e4b9008a7
author: Ori Bernstein <[email protected]>
date: Tue Jan 14 14:44:14 EST 2014
Add support for break/continue in loops. Yeah, I resisted until now. Oh well.
--- a/6/isel.c
+++ b/6/isel.c
@@ -719,6 +719,7 @@
case Oslice: case Oidx: case Osize: case Numops:
case Oucon: case Ouget: case Otup: case Oarr: case Ostruct:
case Oslbase: case Osllen: case Ocast:
+ case Obreak: case Ocontinue:
dump(n, stdout);
die("Should not see %s in isel", opstr(exprop(n)));
break;
--- a/6/simp.c
+++ b/6/simp.c
@@ -37,6 +37,12 @@
/* pre/postinc handling */
Node **incqueue;
size_t nqueue;
+
+ /* break/continue handling */
+ Node **loopstep;
+ size_t nloopstep;
+ Node **loopexit;
+ size_t nloopexit;
/* location handling */
Node **blobs;
@@ -469,19 +475,28 @@
Node *lbody;
Node *lend;
Node *lcond;
+ Node *lstep;
lbody = genlbl();
lcond = genlbl();
+ lstep = genlbl();
lend = genlbl();
+ lappend(&s->loopstep, &s->nloopstep, lstep);
+ lappend(&s->loopexit, &s->nloopexit, lend);
+
simp(s, n->loopstmt.init); /* init */
jmp(s, lcond); /* goto test */
simp(s, lbody); /* body lbl */
simp(s, n->loopstmt.body); /* body */
+ simp(s, lstep); /* test lbl */
simp(s, n->loopstmt.step); /* step */
simp(s, lcond); /* test lbl */
simpcond(s, n->loopstmt.cond, lbody, lend); /* repeat? */
simp(s, lend); /* exit */
+
+ s->nloopstep--;
+ s->nloopexit--;
}
/* pat; seq;
@@ -514,6 +529,9 @@
lmatch = genlbl();
lend = genlbl();
+ lappend(&s->loopstep, &s->nloopstep, lstep);
+ lappend(&s->loopexit, &s->nloopexit, lend);
+
zero = mkintlit(n->line, 0);
zero->expr.type = tyintptr;
@@ -539,6 +557,9 @@
val = load(idxaddr(s, seq, idx));
umatch(s, n->iterstmt.elt, val, val->expr.type, lbody, lstep);
simp(s, lend);
+
+ s->nloopstep--;
+ s->nloopexit--;
}
static Ucon *finducon(Node *n)
@@ -1230,7 +1251,6 @@
r = NULL;
args = n->expr.args;
switch (exprop(n)) {
- case Obad:
case Olor: case Oland:
r = simplazy(s, n);
break;
@@ -1402,6 +1422,17 @@
r = visit(s, n);
}
break;
+ case Obreak:
+ if (s->nloopexit == 0)
+ fatal(n->line, "trying to break when not in loop");
+ jmp(s, s->loopexit[s->nloopexit - 1]);
+ break;
+ case Ocontinue:
+ if (s->nloopstep == 0)
+ fatal(n->line, "trying to continue when not in loop");
+ jmp(s, s->loopstep[s->nloopstep - 1]);
+ break;
+ break;
default:
if (istyfloat(exprtype(n))) {
switch (exprop(n)) {
@@ -1413,6 +1444,10 @@
}
}
r = visit(s, n);
+ break;
+ case Obad:
+ die("Bad operator");
+ break;
}
return r;
}
--- a/libstd/sys-linux.myr
+++ b/libstd/sys-linux.myr
@@ -2,6 +2,7 @@
use "sleq.use"
pkg std =
+ type pid = int64
type scno = int64 /* syscall */
type fdopt = int64 /* fd options */
type fd = int64 /* fd */
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -85,6 +85,8 @@
%token<tok> Tmatch /* match */
%token<tok> Tdefault /* default */
%token<tok> Tgoto /* goto */
+%token<tok> Tbreak /* break */
+%token<tok> Tcontinue /* continue */
%token<tok> Tintlit
%token<tok> Tstrlit
@@ -134,7 +136,8 @@
%type <tydef> tydef typeid
%type <node> traitdef
-%type <node> exprln retexpr goto expr atomicexpr littok literal asnexpr lorexpr landexpr borexpr
+%type <node> exprln retexpr goto continue break expr atomicexpr
+%type <node> littok literal asnexpr lorexpr landexpr borexpr
%type <node> bandexpr cmpexpr unionexpr addexpr mulexpr shiftexpr prefixexpr postfixexpr
%type <node> funclit seqlit tuplit name block stmt label use
%type <node> declbody declcore structent arrayelt structelt tuphead
@@ -699,6 +702,8 @@
;
stmt : goto
+ | break
+ | continue
| retexpr
| label
| ifstmt
@@ -706,6 +711,14 @@
| whilestmt
| matchstmt
| /* empty */ {$$ = NULL;}
+ ;
+
+break : Tbreak
+ {$$ = mkexpr($1->line, Obreak, NULL);}
+ ;
+
+continue : Tcontinue
+ {$$ = mkexpr($1->line, Ocontinue, NULL);}
;
forstmt : Tfor optexprln optexprln optexprln block
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1190,6 +1190,11 @@
t = unify(st, n, mktype(-1, Tyvoid), ret);
settype(st, n, t);
break;
+ case Obreak:
+ case Ocontinue:
+ /* nullary: nothing to infer. */
+ settype(st, n, mktype(-1, Tyvoid));
+ break;
case Ojmp: /* goto void* -> void */
infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktype(-1, Tyvoid));
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -45,7 +45,9 @@
O(Ocall, 0)
O(Ocast, 1)
O(Oret, 1)
-O(Ojmp, 1)
+O(Ojmp, 0)
+O(Obreak, 0)
+O(Ocontinue, 0)
O(Ovar, 1)
O(Olit, 1)
O(Olbl, 1)
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -159,8 +159,10 @@
static int kwd(char *s)
{
static const struct {char* kw; int tt;} kwmap[] = {
+ {"break", Tbreak},
{"castto", Tcast},
{"const", Tconst},
+ {"continue", Tcontinue},
{"default", Tdefault},
{"elif", Telif},
{"else", Telse},
--- a/test/loop.myr
+++ b/test/loop.myr
@@ -5,8 +5,20 @@
var n
n = 0
+ for i = 0; i < 5; ++i
+ std.put("%i", i)
+ ;;
+ for i = 0; i < 5; ++i
+ if i > 3
+ break
+ ;;
+ std.put("%i", i)
+ ;;
for i = 0; i < 10; ++i
- n += i
+ if i < 6
+ continue
+ ;;
+ std.put("%i", i)
;;
- std.exit(n)
+ std.put("\n")
}
--- a/test/tests
+++ b/test/tests
@@ -56,7 +56,7 @@
B callbig E 42
B nestfn E 42
# B closure E 55 ## BUGGERED
-B loop E 45
+B loop P 0123401236789
B subrangefor P 12
B patiter P 23512
B condiftrue E 7