summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-01-14 19:44:14 -0500
committerOri Bernstein <ori@eigenstate.org>2014-01-14 19:44:14 -0500
commit26fef326df126ced69c6eb4f531b487de37e23c7 (patch)
tree3f35a354bca4e70627111821ac7d61e82eef63ed
parenta14644877bbb7cbe45cbd006f2773a3e4b9008a7 (diff)
downloadmc-26fef326df126ced69c6eb4f531b487de37e23c7.tar.gz
Add support for break/continue in loops.
Yeah, I resisted until now. Oh well.
-rw-r--r--6/isel.c1
-rw-r--r--6/simp.c37
-rw-r--r--libstd/sys-linux.myr1
-rw-r--r--parse/gram.y15
-rw-r--r--parse/infer.c5
-rw-r--r--parse/ops.def4
-rw-r--r--parse/tok.c2
-rw-r--r--test/loop.myr16
-rw-r--r--test/tests2
9 files changed, 77 insertions, 6 deletions
diff --git a/6/isel.c b/6/isel.c
index 7241134..d2b3af8 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -719,6 +719,7 @@ Loc *selexpr(Isel *s, Node *n)
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;
diff --git a/6/simp.c b/6/simp.c
index 2abb1c6..8762d40 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -37,6 +37,12 @@ struct Simp {
/* 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 @@ static void simploop(Simp *s, Node *n)
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 @@ static void simpiter(Simp *s, Node *n)
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 @@ static void simpiter(Simp *s, Node *n)
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 @@ static Node *rval(Simp *s, Node *n, Node *dst)
r = NULL;
args = n->expr.args;
switch (exprop(n)) {
- case Obad:
case Olor: case Oland:
r = simplazy(s, n);
break;
@@ -1402,6 +1422,17 @@ static Node *rval(Simp *s, Node *n, Node *dst)
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 @@ static Node *rval(Simp *s, Node *n, Node *dst)
}
}
r = visit(s, n);
+ break;
+ case Obad:
+ die("Bad operator");
+ break;
}
return r;
}
diff --git a/libstd/sys-linux.myr b/libstd/sys-linux.myr
index be9e5af..67585af 100644
--- a/libstd/sys-linux.myr
+++ b/libstd/sys-linux.myr
@@ -2,6 +2,7 @@ use "types.use"
use "sleq.use"
pkg std =
+ type pid = int64
type scno = int64 /* syscall */
type fdopt = int64 /* fd options */
type fd = int64 /* fd */
diff --git a/parse/gram.y b/parse/gram.y
index 1005275..d7ec7f2 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -85,6 +85,8 @@ static void constrainwith(Type *t, char *str);
%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 @@ static void constrainwith(Type *t, char *str);
%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 @@ endlns : /* none */
;
stmt : goto
+ | break
+ | continue
| retexpr
| label
| ifstmt
@@ -708,6 +713,14 @@ stmt : goto
| /* empty */ {$$ = NULL;}
;
+break : Tbreak
+ {$$ = mkexpr($1->line, Obreak, NULL);}
+ ;
+
+continue : Tcontinue
+ {$$ = mkexpr($1->line, Ocontinue, NULL);}
+ ;
+
forstmt : Tfor optexprln optexprln optexprln block
{$$ = mkloopstmt($1->line, $2, $3, $4, $5);}
| Tfor expr Tin exprln block
diff --git a/parse/infer.c b/parse/infer.c
index 07f7524..0f00587 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1190,6 +1190,11 @@ static void inferexpr(Inferstate *st, Node *n, Type *ret, int *sawret)
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));
diff --git a/parse/ops.def b/parse/ops.def
index d7799ce..298ccb2 100644
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -45,7 +45,9 @@ O(Osize, 1)
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)
diff --git a/parse/tok.c b/parse/tok.c
index 72edc8e..b1a0f05 100644
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -159,8 +159,10 @@ static void eatspace(void)
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},
diff --git a/test/loop.myr b/test/loop.myr
index cbdfa2e..6bf93cf 100644
--- a/test/loop.myr
+++ b/test/loop.myr
@@ -5,8 +5,20 @@ const main = {
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")
}
diff --git a/test/tests b/test/tests
index b984ab2..e897885 100644
--- a/test/tests
+++ b/test/tests
@@ -56,7 +56,7 @@ B voidcall E 12
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