summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2018-03-06 11:47:45 -0800
committerOri Bernstein <ori@markovcorp.com>2018-03-06 11:47:45 -0800
commit7b024df82962f4bfe24db5b74fe2a92aac26cf8e (patch)
tree71c499cbc5964b8a9823fef21d1e8b09ee98c0b3
parent27b4f894b3b7456b64908ad8c2d50ba66ebb513a (diff)
downloadmc-7b024df82962f4bfe24db5b74fe2a92aac26cf8e.tar.gz
Add ternary operator.
-rw-r--r--6/isel.c2
-rw-r--r--lib/std/bld.sub1
-rw-r--r--lib/std/bytealloc.myr6
-rw-r--r--lib/std/search.myr3
-rw-r--r--mi/flatten.c30
-rw-r--r--parse/gram.y13
-rw-r--r--parse/infer.c96
-rw-r--r--parse/ops.def1
-rw-r--r--parse/tok.c1
9 files changed, 86 insertions, 67 deletions
diff --git a/6/isel.c b/6/isel.c
index e695096..bd122b7 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -939,7 +939,7 @@ selexpr(Isel *s, Node *n)
/* These operators should never show up in the reduced trees,
* since they should have been replaced with more primitive
* expressions by now */
- case Obad: case Opreinc: case Opostinc: case Opredec:
+ case Obad: case Opreinc: case Opostinc: case Opredec: case Otern:
case Opostdec: case Olor: case Oland: case Oaddeq:
case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
diff --git a/lib/std/bld.sub b/lib/std/bld.sub
index 244b992..01855ff 100644
--- a/lib/std/bld.sub
+++ b/lib/std/bld.sub
@@ -82,6 +82,7 @@ lib std =
utf.myr
varargs.myr
writeall.myr
+ valgrind+x64.s
# asm optimizations
memops.myr
diff --git a/lib/std/bytealloc.myr b/lib/std/bytealloc.myr
index 4d2c921..becef31 100644
--- a/lib/std/bytealloc.myr
+++ b/lib/std/bytealloc.myr
@@ -25,9 +25,11 @@ pkg std =
pkglocal const zbytealloc : (sz:size -> byte#)
pkglocal const align : (m : std.size, align : std.size -> std.size)
pkglocal const allocsz : (sz : std.size -> std.size)
-
;;
+extern const vgalloc : (p : byte#, sz : size -> void)
+extern const vgfree : (p : byte#, sz : size -> void)
+
const Zslab = (0 : slab#)
const Zchunk = (0 : chunk#)
const Slabsz = 512*KiB
@@ -139,6 +141,7 @@ const bytealloc = {sz
tracealloc(p, sz)
unlock(memlck)
;;
+ vgalloc(p, sz)
-> p
}
@@ -165,6 +168,7 @@ const bytefree = {p, sz
else
bigfree(p, sz)
;;
+ vgfree(p, sz)
}
const bigalloc = {sz
diff --git a/lib/std/search.myr b/lib/std/search.myr
index 5e3865b..8e5e259 100644
--- a/lib/std/search.myr
+++ b/lib/std/search.myr
@@ -32,8 +32,7 @@ generic bsearch = {sl, key, cmp
match cmp(sl[mid], key)
| `After: hi = mid - 1
| `Before: lo = mid + 1
- | `Equal:
- -> `Some (mid : @idx)
+ | `Equal: -> `Some (mid : @idx)
;;
;;
-> `None
diff --git a/mi/flatten.c b/mi/flatten.c
index 37b59e5..aba73cd 100644
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -277,6 +277,33 @@ flattencond(Flattenctx *s, Node *n, Node *ltrue, Node *lfalse)
}
}
+static Node*
+flattentern(Flattenctx *s, Node *n)
+{
+ Node *l1, *l2, *l3;
+ Node *res, *t;
+
+ l1 = genlbl(n->loc);
+ l2 = genlbl(n->loc);
+ l3 = genlbl(n->loc);
+
+ res = temp(s, n);
+ flattencond(s, n->expr.args[0], l1, l2);
+
+ append(s, l1);
+ t = assign(s, res, rval(s, n->expr.args[1]));
+ append(s, t);
+ jmp(s, l3);
+
+ append(s, l2);
+ t = assign(s, res, rval(s, n->expr.args[2]));
+ append(s, t);
+
+ append(s, l3);
+
+ return res;
+}
+
/* flatten
* a || b
* to
@@ -588,6 +615,9 @@ rval(Flattenctx *s, Node *n)
if (exitscope(s, NULL, Zloc, Xret))
append(s, mkexpr(n->loc, Oret, s->tret, NULL));
break;
+ case Otern:
+ r = flattentern(s, n);
+ break;
case Oasn:
r = assign(s, args[0], args[1]);
break;
diff --git a/parse/gram.y b/parse/gram.y
index 5c73295..8fb448b 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -83,6 +83,7 @@ static void setupinit(Node *n);
%token<tok> Tcsqbrac /* ] */
%token<tok> Ttick /* ` */
%token<tok> Tderef /* # */
+%token<tok> Tqmark /* ? */
%token<tok> Ttype /* type */
%token<tok> Tfor /* for */
@@ -145,7 +146,7 @@ static void setupinit(Node *n);
%type<node> exprln retexpr goto continue break expr atomicexpr
%type<node> littok literal lorexpr landexpr borexpr strlit bandexpr
-%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr
+%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr ternexpr
%type<node> postfixexpr funclit seqlit tuplit name block stmt label
%type<node> use fnparam declbody declcore typedeclcore autodecl structent
%type<node> arrayelt structelt tuphead ifstmt forstmt whilestmt
@@ -692,9 +693,9 @@ optexprln
exprln : expr Tendln
;
-expr : lorexpr asnop expr
+expr : ternexpr asnop expr
{$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | lorexpr
+ | ternexpr
;
asnop : Tasn
@@ -710,6 +711,12 @@ asnop : Tasn
| Tbsreq /* >>= */
;
+ternexpr
+ : lorexpr
+ | lorexpr Tqmark lorexpr Tcolon lorexpr
+ {$$ = mkexpr($1->loc, Otern, $1, $3, $5, NULL);}
+ ;
+
lorexpr : lorexpr Tlor landexpr
{$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
| landexpr
diff --git a/parse/infer.c b/parse/infer.c
index 360ca36..5424be9 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1772,10 +1772,10 @@ inferexpr(Node **np, Type *ret, int *sawret)
break;
case Oret: /* -> @a -> void */
infersub(n, ret, sawret, &isconst);
- if (sawret)
- *sawret = 1;
if (!ret)
fatal(n, "returns are not valid near %s", ctxstr(n));
+ if (sawret)
+ *sawret = 1;
t = unify(n, ret, type(args[0]));
settype(n, t);
break;
@@ -1817,70 +1817,46 @@ inferexpr(Node **np, Type *ret, int *sawret)
case Ostruct: inferstruct(n, &n->expr.isconst); break;
case Oarr: inferarray(n, &n->expr.isconst); break;
case Olit: /* <lit>:@a::tyclass -> @a */
- infersub(n, ret, sawret, &isconst);
- switch (args[0]->lit.littype) {
- case Lfunc:
- infernode(&args[0]->lit.fnval, NULL, NULL);
- /* FIXME: env capture means this is non-const */
- n->expr.isconst = 1;
- break;
- case Llbl:
- s = getlbl(curstab(), args[0]->loc, args[0]->lit.lblname);
- if (!s)
- fatal(n, "unable to find label %s in function scope\n", args[0]->lit.lblname);
- *np = s;
- break;
- default:
- n->expr.isconst = 1;
- break;
- }
- settype(n, type(args[0]));
- break;
+ infersub(n, ret, sawret, &isconst);
+ switch (args[0]->lit.littype) {
+ case Lfunc:
+ infernode(&args[0]->lit.fnval, NULL, NULL);
+ /* FIXME: env capture means this is non-const */
+ n->expr.isconst = 1;
+ break;
+ case Llbl:
+ s = getlbl(curstab(), args[0]->loc, args[0]->lit.lblname);
+ if (!s)
+ fatal(n, "unable to find label %s in function scope\n", args[0]->lit.lblname);
+ *np = s;
+ break;
+ default:
+ n->expr.isconst = 1;
+ break;
+ }
+ settype(n, type(args[0]));
+ break;
+ case Otern:
+ infersub(n, NULL, sawret, &isconst);
+ unify(n, type(args[0]), mktype(n->loc, Tybool));
+ unify(n, type(args[1]), type(args[2]));
+ settype(n, type(args[1]));
+ break;
case Oundef:
- infersub(n, ret, sawret, &isconst);
- settype(n, mktype(n->loc, Tyvoid));
- break;
+ infersub(n, ret, sawret, &isconst);
+ settype(n, mktype(n->loc, Tyvoid));
+ break;
case Odef:
case Odead:
n->expr.type = mktype(n->loc, Tyvoid);
break;
/* unexpected in frontend */
- case Obad:
- case Ocjmp:
- case Ovjmp:
- case Oset:
- case Oslbase:
- case Osllen:
- case Outag:
- case Ocallind:
- case Oblit:
- case Oclear:
- case Oudata:
- case Otrunc:
- case Oswiden:
- case Ozwiden:
- case Oint2flt:
- case Oflt2int:
- case Oflt2flt:
- case Ofadd:
- case Ofsub:
- case Ofmul:
- case Ofdiv:
- case Ofneg:
- case Ofeq:
- case Ofne:
- case Ofgt:
- case Ofge:
- case Oflt:
- case Ofle:
- case Oueq:
- case Oune:
- case Ougt:
- case Ouge:
- case Oult:
- case Oule:
- case Otupget:
- case Numops:
+ case Obad: case Ocjmp: case Ovjmp: case Oset: case Oslbase: case Osllen:
+ case Outag: case Ocallind: case Oblit: case Oclear: case Oudata: case Otrunc:
+ case Oswiden: case Ozwiden: case Oint2flt: case Oflt2int: case Oflt2flt:
+ case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg: case Ofeq:
+ case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle: case Oueq: case Oune:
+ case Ougt: case Ouge: case Oult: case Oule: case Otupget: case Numops:
die("Should not see %s in fe", opstr[exprop(n)]);
break;
}
diff --git a/parse/ops.def b/parse/ops.def
index dd9447a..c29ca1e 100644
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -55,6 +55,7 @@ O(Oucon, 1, OTmisc, "`")
O(Otup, 1, OTmisc, NULL)
O(Ostruct, 1, OTmisc, NULL)
O(Oarr, 1, OTmisc, NULL)
+O(Otern, 1, OTmisc, "?:")
/* all below this point are backend-only */
O(Odead, 0, OTmisc, "DEAD") /* dead code */
diff --git a/parse/tok.c b/parse/tok.c
index eb5ba1c..5c55cbc 100644
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -522,6 +522,7 @@ oper(void)
case ',': tt = Tcomma; break;
case '`': tt = Ttick; break;
case '#': tt = Tderef; break;
+ case '?': tt = Tqmark; break;
case ':':
if (match(':'))
tt = Twith;