ref: 7b024df82962f4bfe24db5b74fe2a92aac26cf8e
parent: 27b4f894b3b7456b64908ad8c2d50ba66ebb513a
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Mar 6 06:47:45 EST 2018
Add ternary operator.
--- a/6/isel.c
+++ b/6/isel.c
@@ -939,7 +939,7 @@
/* 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:
--- a/lib/std/bld.sub
+++ b/lib/std/bld.sub
@@ -82,6 +82,7 @@
utf.myr
varargs.myr
writeall.myr
+ valgrind+x64.s
# asm optimizations
memops.myr
--- a/lib/std/bytealloc.myr
+++ b/lib/std/bytealloc.myr
@@ -25,9 +25,11 @@
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 @@
tracealloc(p, sz)
unlock(memlck)
;;
+ vgalloc(p, sz)
-> p
}
@@ -165,6 +168,7 @@
else
bigfree(p, sz)
;;
+ vgfree(p, sz)
}
const bigalloc = {sz
--- a/lib/std/search.myr
+++ b/lib/std/search.myr
@@ -32,8 +32,7 @@
match cmp(sl[mid], key)
| `After: hi = mid - 1
| `Before: lo = mid + 1
- | `Equal:
- -> `Some (mid : @idx)
+ | `Equal: -> `Some (mid : @idx)
;;
;;
-> `None
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -277,6 +277,33 @@
}
}
+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
@@ -587,6 +614,9 @@
flatten(s, asn(lval(s, s->tret), t));
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]);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -83,6 +83,7 @@
%token<tok> Tcsqbrac /* ] */
%token<tok> Ttick /* ` */
%token<tok> Tderef /* # */
+%token<tok> Tqmark /* ? */
%token<tok> Ttype /* type */
%token<tok> Tfor /* for */
@@ -145,7 +146,7 @@
%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 @@
exprln : expr Tendln
;
-expr : lorexpr asnop expr
+expr : ternexpr asnop expr
{$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | lorexpr
+ | ternexpr
;
asnop : Tasn
@@ -708,6 +709,12 @@
| Tbandeq /* &= */
| Tbsleq /* <<= */
| Tbsreq /* >>= */
+ ;
+
+ternexpr
+ : lorexpr
+ | lorexpr Tqmark lorexpr Tcolon lorexpr
+ {$$ = mkexpr($1->loc, Otern, $1, $3, $5, NULL);}
;
lorexpr : lorexpr Tlor landexpr
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1772,10 +1772,10 @@
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 @@
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;
}
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -55,6 +55,7 @@
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 */
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -522,6 +522,7 @@
case ',': tt = Tcomma; break;
case '`': tt = Ttick; break;
case '#': tt = Tderef; break;
+ case '?': tt = Tqmark; break;
case ':':
if (match(':'))
tt = Twith;