summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--minic/minic.y65
1 files changed, 56 insertions, 9 deletions
diff --git a/minic/minic.y b/minic/minic.y
index 82b0df0..1814bc3 100644
--- a/minic/minic.y
+++ b/minic/minic.y
@@ -70,6 +70,7 @@ struct Stmt {
 
 int yylex(void), yyerror(char *);
 Symb expr(Node *), lval(Node *);
+void bool(Node *, int, int);
 
 FILE *of;
 int line;
@@ -317,7 +318,7 @@ expr(Node *n)
 		['n'] = "cne",
 	};
 	Symb sr, s0, s1, sl;
-	int o;
+	int o, l;
 
 	sr.t = Tmp;
 	sr.u.n = tmp++;
@@ -327,6 +328,22 @@ expr(Node *n)
 	case 0:
 		abort();
 
+	case 'o':
+	case 'a':
+		l = lbl;
+		lbl += 3;
+		bool(n, l, l+1);
+		fprintf(of, "@l%d\n", l);
+		fprintf(of, "\tjmp @l%d\n", l+2);
+		fprintf(of, "@l%d\n", l+1);
+		fprintf(of, "\tjmp @l%d\n", l+2);
+		fprintf(of, "@l%d\n", l+2);
+		fprintf(of, "\t");
+		sr.ctyp = INT;
+		psymb(sr);
+		fprintf(of, " =w phi @l%d 1, @l%d 0\n", l, l+1);
+		break;
+
 	case 'V':
 		s0 = lval(n);
 		sr.ctyp = s0.ctyp;
@@ -450,6 +467,36 @@ lval(Node *n)
 	return sr;
 }
 
+void
+bool(Node *n, int lt, int lf)
+{
+	Symb s;
+	int l;
+
+	switch (n->op) {
+	default:
+		s = expr(n); /* TODO: insert comparison to 0 with proper type */
+		fprintf(of, "\tjnz ");
+		psymb(s);
+		fprintf(of, ", @l%d, @l%d\n", lt, lf);
+		break;
+	case 'o':
+		l = lbl;
+		lbl += 1;
+		bool(n->l, lt, l);
+		fprintf(of, "@l%d\n", l);
+		bool(n->r, lt, lf);
+		break;
+	case 'a':
+		l = lbl;
+		lbl += 1;
+		bool(n->l, l, lf);
+		fprintf(of, "@l%d\n", l);
+		bool(n->r, lt, lf);
+		break;
+	}
+}
+
 int
 stmt(Stmt *s, int b)
 {
@@ -477,12 +524,9 @@ stmt(Stmt *s, int b)
 	case Seq:
 		return stmt(s->p1, b) || stmt(s->p2, b);
 	case If:
-		x = expr(s->p1);
-		fprintf(of, "\tjnz ");  /* to be clean, a comparison to 0 should be inserted here */
-		psymb(x);
 		l = lbl;
 		lbl += 3;
-		fprintf(of, ", @l%d, @l%d\n", l, l+1);
+		bool(s->p1, l, l+1);
 		fprintf(of, "@l%d\n", l);
 		if (!stmt(s->p2, b))
 		if (s->p3)
@@ -496,10 +540,7 @@ stmt(Stmt *s, int b)
 		l = lbl;
 		lbl += 3;
 		fprintf(of, "@l%d\n", l);
-		x = expr(s->p1);
-		fprintf(of, "\tjnz ");                  /* ditto */
-		psymb(x);
-		fprintf(of, ", @l%d, @l%d\n", l+1, l+2);
+		bool(s->p1, l+1, l+2);
 		fprintf(of, "@l%d\n", l+1);
 		if (!stmt(s->p2, l+2))
 			fprintf(of, "\tjmp @l%d\n", l);
@@ -610,6 +651,8 @@ mkfor(Node *ini, Node *tst, Node *inc, Stmt *s)
 %token IF ELSE WHILE FOR BREAK RETURN
 
 %right '='
+%left OR
+%left AND
 %left '&'
 %left EQ NE
 %left '<' '>' LE GE
@@ -741,6 +784,8 @@ expr: pref
     | expr EQ expr      { $$ = mknode('e', $1, $3); }
     | expr NE expr      { $$ = mknode('n', $1, $3); }
     | expr '&' expr     { $$ = mknode('&', $1, $3); }
+    | expr AND expr     { $$ = mknode('a', $1, $3); }
+    | expr OR expr      { $$ = mknode('o', $1, $3); }
     ;
 
 exp0: expr
@@ -875,6 +920,8 @@ yylex()
 	case DI('>','='): return GE;
 	case DI('+','+'): return PP;
 	case DI('-','-'): return MM;
+	case DI('&','&'): return AND;
+	case DI('|','|'): return OR;
 	}
 #undef DI
 	ungetc(c1, stdin);