shithub: mc

Download patch

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;