shithub: scc

Download patch

ref: d90d76bddf5a29e8d393f1803cf3db3330e532bb
parent: c5c6bf38f751f19db8d848e04d989f1da59c0792
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Mar 12 06:07:04 EDT 2015

Simplify node() function

Node() creates a new node, and it was accepting a value that
was the kind of node, and a vararg list of descendant. This created
a lot of problems, and some ugly unions were needed. This patch
simplifies the Node struct and make that node only receives a node
operator.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -140,23 +140,14 @@
 extern uint8_t next(void);
 extern void expect(uint8_t tok);
 
-
 typedef struct node {
-	void (*code)(struct node *);
+	uint8_t op;
 	Type *type;
-	uint8_t typeop;
-	uint8_t nchilds;
-	struct {
-		bool lvalue : 1;
-		bool symbol: 1;
-		bool constant : 1;
-	} b;
-	union unode {
-		Symbol *sym;
-		Type *type;
-		char op;
-	} u;
-	struct node *childs[];
+	Symbol *sym;
+	bool lvalue : 1;
+	bool symbol: 1;
+	bool constant : 1;
+	struct node *left, *rigth;
 } Node;
 
 enum {
@@ -165,7 +156,7 @@
 	OBAND, OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
 	OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
 	OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
-	OCOMMA,
+	OCOMMA, OCAST, OSYM, OASK, OFIELD, OTYP,
 	/* TODO: This order is important, but must be changed */
 	OAND, OOR,
 	/*
@@ -175,10 +166,10 @@
 	OEQ = 0x40, ONE, OLT, OGE, OLE, OGT
 };
 
+/*TODO: clean these declarations */
 extern void
 	emitdcl(Symbol *), emitefun(void),
-	emitsym(Node *), emitunary(Node *),
-	emitbin(Node *), emitexp(Node *),
+	emitexp(Node *),
 	emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
 	emitbloop(void), emiteloop(void),
 	emitswitch(short, Node *), emitcase(Symbol *, Node *),
@@ -187,20 +178,13 @@
 	emitdefault(Symbol *),
 	emitstruct(Symbol *sym), emitestruct(void);
 
-enum {
-	CAST, FIELD, UNARY, BINARY,
-	SIZEOFCODE, SYMBOL, TERNARY
-};
-
-extern Node *node(char kind, Type *tp, ...);
-
+extern Node *node(uint8_t op, Type *tp, Node *left, Node *rigth);
+extern Node *symbol(Symbol *sym);
 extern void freetree(Node *np);
 
-#define NEGATE(n, v) ((n)->u.op ^= (v))
-/* TODO: remove some of these ugly macros */
-#define ISNODEBIN(n) ((n)->code == emitbin)
-#define ISNODECMP(n) (ISNODEBIN(n) && (n)->u.op >= OEQ)
-#define ISNODELOG(n) (ISNODEBIN(n) && (n)->u.op >= OAND)
+#define NEGATE(n, v) ((n)->op ^= (v))
+#define ISNODECMP(n) ((n)->op >= OEQ)
+#define ISNODELOG(n) ((n)->op >= OAND)
 
 extern Node *expr(void);
 extern void extdecl(void), decl(void);
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -7,7 +7,11 @@
 #include "../inc/cc.h"
 #include "cc1.h"
 
-char *opcodes[] = {
+static void emitbin(Node *), emitunary(Node *), emitternary(Node *),
+     emitcast(Node *), emitsym(Node *), emitfield(Node *),
+     emitsizeof(Node *);
+
+char *optxt[] = {
 	[OADD] = "+",
 	[OSUB] = "-",
 	[OMUL] = "*",
@@ -47,6 +51,50 @@
 	[OCOMMA] = ","
 };
 
+void (*opcode[])(Node *) = {
+	[OADD] = emitbin,
+	[OSUB] = emitbin,
+	[OMUL] = emitbin,
+	[OINC] = emitunary,
+	[ODEC] =  emitunary,
+	[OSIZE] = emitsizeof,
+	[OPTR] = emitunary,
+	[OMOD] = emitbin,
+	[ODIV] = emitbin,
+	[OSHL] = emitbin,
+	[OSHR]  = emitbin,
+	[OLT] = emitbin,
+	[OGT] = emitbin,
+	[OGE] = emitbin,
+	[OLE] =  emitbin,
+	[OEQ] = emitbin,
+	[ONE] = emitunary,
+	[OBAND] = emitbin,
+	[OBXOR]  = emitbin,
+	[OBOR] = emitbin,
+	[OASSIGN] = emitbin,
+	[OA_MUL] = emitbin,
+	[OA_DIV] = emitbin,
+	[OA_MOD] = emitbin,
+	[OA_ADD] = emitbin,
+	[OA_SUB] = emitbin,
+	[OA_SHL] = emitbin,
+	[OA_SHR] = emitbin,
+	[OA_AND] = emitbin,
+	[OA_XOR] = emitbin,
+	[OA_OR] = emitbin,
+	[OADDR] = emitunary,
+	[ONEG] = emitunary,
+	[OCPL] = emitunary,
+	[OAND] = emitbin,
+	[OOR] = emitbin,
+	[OCOMMA] = emitbin,
+	[OCAST] = emitcast,
+	[OSYM] = emitsym,
+	[OASK] = emitternary,
+	[OFIELD]= emitfield
+};
+
 void
 freetree(Node *np)
 {
@@ -54,9 +102,8 @@
 
 	if (!np)
 		return;
-
-	for (p = np->childs; np->nchilds--; ++p)
-		freetree(*p);
+	freetree(np->left);
+	freetree(np->rigth);
 	free(np);
 }
 
@@ -86,7 +133,7 @@
 emitconst(Node *np)
 {
 	char *bp, c;
-	Symbol *sym = np->u.sym;
+	Symbol *sym = np->sym;
 
 	if (np->type == inttype) {
 		printf("#%c%x", np->type->letter, sym->u.i);
@@ -113,7 +160,7 @@
 emitsym(Node *np)
 {
 	putchar('\t');
-	(np->b.constant) ? emitconst(np) : emitvar(np->u.sym);
+	(np->constant) ? emitconst(np) : emitvar(np->sym);
 }
 
 static void
@@ -134,34 +181,34 @@
 void
 emitcast(Node *np)
 {
-	Node *child = np->childs[0];
+	Node *lp = np->left;
 
-	(*child->code)(child);
-	printf("\t%c%c", child->type->letter, np->type->letter);
+	(*opcode[lp->op])(lp);
+	printf("\t%c%c", lp->type->letter, np->type->letter);
 }
 
 void
 emitunary(Node *np)
 {
-	Node *child;
+	Node *lp;
 	char letter;
 
 	letter = np->type->letter;
-	child = np->childs[0];
-	(*child->code)(child);
-	printf("\t%s%c", opcodes[np->u.op], letter);
+	lp = np->left;
+	(*opcode[lp->op])(lp);
+	printf("\t%s%c", optxt[np->op], letter);
 }
 
 void
 emitbin(Node *np)
 {
-	Node *child1, *child2;
+	Node *lp, *rp;
 
-	child1 = np->childs[0];
-	child2 = np->childs[1];
-	(*child1->code)(child1);
-	(*child2->code)(child2);
-	printf("\t%s%c", opcodes[np->u.op], np->type->letter);
+	lp = np->left;
+	rp = np->rigth;
+	(*opcode[lp->op])(lp);
+	(*opcode[rp->op])(rp);
+	printf("\t%s%c", optxt[np->op], np->type->letter);
 }
 
 void
@@ -169,12 +216,12 @@
 {
 	Node *cond, *ifyes, *ifno;
 
-	cond = np->childs[0];
-	ifyes = np->childs[1];
-	ifno = np->childs[2];
-	(*cond->code)(cond);
-	(*ifyes->code)(ifyes);
-	(*ifno->code)(ifno);
+	cond = np->left;
+	ifyes = np->rigth->left;
+	ifno = np->rigth->rigth;
+	(*opcode[cond->op])(cond);
+	(*opcode[ifyes->op])(ifyes);
+	(*opcode[ifno->op])(ifno);
 	printf("\t?%c", np->type->letter);
 }
 
@@ -181,7 +228,7 @@
 void
 emitsizeof(Node *np)
 {
-	printf("\t#%c", np->u.type->letter);
+	printf("\t#%c", np->left->type->letter);
 }
 
 void
@@ -188,7 +235,7 @@
 emitexp(Node *np)
 {
 	if (np)
-		(*np->code)(np);
+		(*opcode[np->op])(np);
 	putchar('\n');
 }
 
@@ -195,7 +242,7 @@
 void
 emitprint(Node *np)
 {
-	(*np->code)(np);
+	(*opcode[np->op])(np);
 	printf("\tk%c\n", np->type->letter);
 	fflush(stdout);
 }
@@ -273,97 +320,36 @@
 void
 emitfield(Node *np)
 {
-	Node *child;
+	Node *lp = np->left;
 
-	child = np->childs[0];
-	(*child->code)(child);
+	(*opcode[lp->op])(lp);
 	putchar('\t');
-	emitvar(np->u.sym);
+	emitvar(np->sym);
 }
 
-enum {
-	SYM, TYP, OP
-};
-
-
-/*TODO: Remove type of union unode */
-
-struct kindnode {
-	uint8_t nchilds;
-	char unode;
-	void (*code)(Node *);
-} kindnodes [] = {
-	[CAST]= {
-		.nchilds = 1,
-		.code = emitcast
-	},
-	[FIELD] = {  /*TODO: Create a node for the symbol */
-		.nchilds = 1,
-		.unode = SYM,
-		.code = emitfield
-	},
-	[UNARY] = {
-		.nchilds = 1,
-		.unode = OP,
-		.code = emitunary
-	},
-	[BINARY] = {
-		.nchilds = 2,
-		.unode = OP,
-		.code = emitbin
-	},
-	[SIZEOFCODE] = {
-		.nchilds = 0,
-		.unode = TYP,
-		.code = emitsizeof
-	},
-	[SYMBOL] = {
-		.nchilds = 0,
-		.unode = SYM,
-		.code = emitsym
-	},
-	[TERNARY] = {
-		.nchilds = 3,
-		.code = emitternary
-	}
-};
-
 Node *
-node(char kind, Type *tp, ...)
+node(uint8_t op, Type *tp, Node *left, Node *rigth)
 {
-	uint8_t nchilds, i;
-	va_list va;
-	struct kindnode *kp;
 	Node *np;
 
-	va_start(va, tp);
-	kp = &kindnodes[kind];
-	nchilds = kp->nchilds;
-	np = xmalloc(sizeof(*np) + nchilds * sizeof(np));
-
-	np->code = kp->code;
-	np->nchilds = nchilds;
+	np = xmalloc(sizeof(*np));
+	np->op = op;
 	np->type = tp;
-	np->typeop = tp->op;
-	np->b.symbol = np->b.lvalue = 0;
+	np->sym = NULL;
+	np->constant = np->symbol = np->lvalue = 0;
+	np->left = left;
+	np->rigth = rigth;
+	return np;
+}
 
-	switch (kp->unode) {
-	case TYP:
-		np->u.type = va_arg(va, Type *);
-		break;
-	case SYM:
-		np->u.sym = va_arg(va, Symbol *);
-		np->b.symbol = 1;
-		np->b.constant = 1;
-		break;
-	case OP:
-		np->u.op = va_arg(va, int);
-		break;
-	}
+Node *
+symbol(Symbol *sym)
+{
+	Node *np;
 
-	for (i = 0; i < nchilds; ++i)
-		np->childs[i] = va_arg(va, Node *);
-
-	va_end(va);
+	np = node(OSYM, sym->type, NULL, NULL);
+	np->symbol = 1;
+	np->constant = 1;
+	np->sym = sym;
 	return np;
 }
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -5,7 +5,8 @@
 #include "../inc/cc.h"
 #include "cc1.h"
 
-#define Q(sym)  node(SYMBOL, inttype, (sym))
+#define BTYPE(np) ((np)->type->op)
+#define TYPE(tp) node(OTYP, (tp), NULL, NULL)
 
 static Symbol *zero, *one;
 
@@ -38,7 +39,7 @@
 	if  (r > RANK_UINT || tp == inttype || tp == uinttype)
 		return np;
 	tp = (r == RANK_UINT) ? uinttype : inttype;
-	return node(CAST, tp, np);
+	return node(OCAST, tp, np, NULL);
 }
 
 static void
@@ -55,9 +56,9 @@
 	tp2 = np2->type;
 	if (tp1 != tp2) {
 		if ((n = tp1->n.rank - tp2->n.rank) > 0)
-			np2 = node(CAST, tp1, np2);
+			np2 = node(OCAST, tp1, np2, NULL);
 		else if (n < 0)
-			np1 = node(CAST, tp2, np1);
+			np1 = node(OCAST, tp2, np1, NULL);
 	}
 	*p1 = np1;
 	*p2 = np2;
@@ -66,7 +67,7 @@
 static void
 chklvalue(Node *np, Type *tp)
 {
-	if (!np->b.lvalue)
+	if (!np->lvalue)
 		error("lvalue required in operation");
 	if (np->type == voidtype)
 		error("invalid use of void expression");
@@ -75,11 +76,14 @@
 Node *
 eval(Node *np)
 {
+	Node *p;
+
 	if (!np)
 		return NULL;
 	if (!ISNODELOG(np))
 		return np;
-	return node(TERNARY, inttype, np, Q(one), Q(zero));
+	p = node(0, inttype, symbol(one), symbol(zero));
+	return node(OASK, inttype, np, p);
 }
 
 static Node *
@@ -87,10 +91,10 @@
 {
 	np1 = eval(np1);
 	np2 = eval(np2);
-	if (np1->typeop != INT || np2->typeop != INT)
+	if (BTYPE(np1) != INT || BTYPE(np2) != INT)
 		error("operator requires integer operands");
 	typeconv(&np1, &np2);
-	return node(BINARY, np1->type, op, np1, np2);
+	return node(op, np1->type, np1, np2);
 }
 
 static Node *
@@ -97,11 +101,11 @@
 numericaluop(char op, Node *np)
 {
 	np = eval(np);
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case INT: case FLOAT:
 		if (op == OADD)
 			return np;
-		return node(UNARY, np->type, op, np);
+		return node(op, np->type, np, NULL);
 	default:
 		error("unary operator requires integer operand");
 	}
@@ -111,15 +115,15 @@
 integeruop(char op, Node *np)
 {
 	np = eval(np);
-	if (np->typeop != INT)
+	if (BTYPE(np) != INT)
 		error("unary operator requires integer operand");
-	return node(UNARY, np->type, op, np);
+	return node(op, np->type, np, NULL);
 }
 
 static Node *
 decay(Node *np)
 {
-	return node(UNARY, mktype(np->type, PTR, 0, NULL), OADDR, np);
+	return node(OADDR, mktype(np->type, PTR, 0, NULL), np, NULL);
 }
 
 /*
@@ -130,11 +134,11 @@
 {
 	if (eqtype(np->type, tp))
 		return np;
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case ENUM: case INT: case FLOAT:
 		switch (tp->op) {
 		case PTR:
-			if (!iscast || np->typeop == FLOAT)
+			if (!iscast || BTYPE(np) == FLOAT)
 				return NULL;
 			/* PASSTHROUGH */
 		case INT: case FLOAT: case ENUM: case VOID:
@@ -167,7 +171,7 @@
 	default:
 			return NULL;
 	}
-	return node(CAST, tp, np);
+	return node(OCAST, tp, np, NULL);
 }
 
 static Node *
@@ -177,21 +181,21 @@
 	Node *size;
 
 	tp = np1->type;
-	size = node(SIZEOFCODE, inttype, tp->type);
-	if (np2->typeop == ARY)
+	size = node(OSIZE, inttype, TYPE(tp->type), NULL);
+	if (BTYPE(np2) == ARY)
 		np2 = decay(np2);
 
-	if (op == OSUB && np2->typeop == PTR) {
+	if (op == OSUB && BTYPE(np2) == PTR) {
 		if (tp != np2->type)
 			goto incorrect;
-		np1 = node(BINARY, inttype, OSUB, np1, np2);
-		return node(BINARY, inttype, ODIV, np1, size);
+		np1 = node(OSUB, inttype, np1, np2);
+		return node(ODIV, inttype, np1, size);
 	}
-	if (np2->typeop != INT)
+	if (BTYPE(np2) != INT)
 		goto incorrect;
-	np2 = node(CAST, tp, promote(np2));
-	np2 = node(BINARY, tp, OMUL, np2, size);
-	return node(BINARY, tp, op, np1, np2);
+	np2 = node(OCAST, tp, promote(np2), NULL);
+	np2 = node(OMUL, tp, np2, size);
+	return node(op, tp, np1, np2);
 
 incorrect:
 	error("incorrect arithmetic operands");
@@ -202,9 +206,9 @@
 {
 	np1 = eval(np1);
 	np2 = eval(np2);
-	switch (np1->typeop) {
+	switch (BTYPE(np1)) {
 	case INT: case FLOAT:
-		switch (np2->typeop) {
+		switch (BTYPE(np2)) {
 		case INT: case FLOAT:
 			typeconv(&np1, &np2);
 			break;
@@ -226,22 +230,27 @@
 		error("incorrect arithmetic operands");
 	}
 
-	return node(BINARY, np1->type, op, np1, np2);
+	return node(op, np1->type, np1, np2);
 }
 
 static Node *
 pcompare(char op, Node *np1, Node *np2)
 {
-	if (np2->typeop == INT && np2->b.symbol && np2->u.sym->u.i == 0) {
-		np2 = node(CAST, pvoidtype, np2);
-	} else if (np2->typeop != PTR) {
+	switch (BTYPE(np2)) {
+	case INT:
+		if (np2->symbol && np2->sym->u.i == 0)
+			np2 = node(OCAST, pvoidtype, np2, NULL);
+		break;
+	case PTR:
+		if (np1->type != np2->type)
+			warn(options.pcompare,
+			     "comparision between different pointer types");
+		break;
+	default:
 		error("incompatibles type in comparision");
-	} else {
-		warn(options.pcompare,
-		     "comparision between different pointer types");
 	}
 
-	return node(BINARY, np1->type, op, np1, np2);
+	return node(op, np1->type, np1, np2);
 }
 
 static Node *
@@ -249,9 +258,9 @@
 {
 	np1 = eval(np1);
 	np2 = eval(np2);
-	switch (np1->typeop) {
+	switch (BTYPE(np1)) {
 	case INT: case FLOAT:
-		switch (np1->typeop) {
+		switch (BTYPE(np1)) {
 		case INT: case FLOAT:
 			typeconv(&np1, &np2);
 			break;
@@ -272,7 +281,7 @@
 		error("incompatibles type in comparision");
 	}
 
-	return node(BINARY, inttype, op, np1, np2);
+	return node(op, inttype, np1, np2);
 }
 
 static Node *
@@ -283,7 +292,7 @@
 		return np;
 	}
 
-	return compare(ONE ^ neg, np, Q(zero));
+	return compare(ONE ^ neg, np, symbol(zero));
 }
 
 static Node *
@@ -291,7 +300,7 @@
 {
 	np1 = exp2cond(np1, 0);
 	np2 = exp2cond(np2, 0);
-	return node(BINARY, inttype, op, np1, np2);
+	return node(op, inttype, np1, np2);
 }
 
 static Node *
@@ -300,7 +309,7 @@
 	extern uint8_t lex_ns;
 	Symbol *sym;
 
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case STRUCT: case UNION:
 		lex_ns = np->type->ns;
 		next();
@@ -310,7 +319,7 @@
 			error("incorrect field in struct/union");
 		lex_ns = NS_IDEN;
 		next();
-		return node(FIELD, sym->type, sym, np);
+		return node(OFIELD, sym->type, symbol(sym), np);
 	default:
 		error("struct or union expected");
 	}
@@ -321,14 +330,14 @@
 {
 	Type *tp;
 
-	if (np1->typeop != INT && np2->typeop != INT)
+	if (BTYPE(np1) != INT && BTYPE(np2) != INT)
 		error("array subscript is not an integer");
 	np1 = arithmetic(OADD, np1, np2);
 	tp = np1->type;
 	if (tp->op != PTR)
 		error("subscripted value is neither array nor pointer nor vector");
-	np1 =  node(UNARY, tp->type, OPTR, np1);
-	np1->b.lvalue = 1;
+	np1 =  node(OPTR, tp->type, np1, NULL);
+	np1->lvalue = 1;
 	return np1;
 }
 
@@ -337,7 +346,7 @@
 {
 	if (ISNODECMP(np))
 		return np;
-	return compare(ONE, np, Q(zero));
+	return compare(ONE, np, symbol(zero));
 }
 
 static Node *
@@ -351,7 +360,7 @@
 		if ((np2 = convert(np2, np1->type, 0)) == NULL)
 			error("incompatible types when assigning");
 	}
-	return node(BINARY, np1->type, op, np1, np2);
+	return node(op, np1->type, np1, np2);
 }
 
 static Node *
@@ -362,14 +371,14 @@
 
 	chklvalue(np, np->type);
 
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case PTR:
 		if (!tp->defined)
 			error("invalid use of indefined type");
-		inc = node(SIZEOFCODE, inttype, tp->type);
+		inc = node(OSIZE, inttype, TYPE(tp->type), NULL);
 		break;
 	case INT: case FLOAT:
-		inc = Q(one);
+		inc = symbol(one);
 		break;
 	default:
 		error("incorrect type in arithmetic operation");
@@ -380,22 +389,22 @@
 static Node *
 address(char op, Node *np)
 {
-	if (!np->b.lvalue)
+	if (!np->lvalue)
 		error("lvalue required in unary expression");
-	if (np->b.symbol && np->u.sym->isregister)
+	if (np->symbol && np->sym->isregister)
 		error("address of register variable '%s' requested", yytext);
-	return node(UNARY, mktype(np->type, PTR, 0, NULL), op, np);
+	return node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
 }
 
 static Node *
 content(char op, Node *np)
 {
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case ARY: case FTN:
 		np = decay(np);
 	case PTR:
-		np = node(UNARY, np->type, op, np);
-		np->b.lvalue = 1;
+		np = node(op, np->type->type, np, NULL);
+		np->lvalue = 1;
 		return np;
 	default:
 		error("invalid argument of unary '*'");
@@ -405,7 +414,7 @@
 static Node *
 negation(char op, Node *np)
 {
-	switch (np->typeop) {
+	switch (BTYPE(np)) {
 	case FTN: case ARY:
 		np = decay(np);
 	case INT: case FLOAT: case PTR:
@@ -428,10 +437,10 @@
 	case STRING: case CONSTANT: case IDEN:
 		if ((sym = yylval.sym) == NULL)
 			error("'%s' undeclared", yytext);
-		np = node(SYMBOL, yylval.sym->type, yylval.sym);
+		np = symbol(yylval.sym);
 		if (yytoken == IDEN) {
-			np->b.lvalue = 1;
-			np->b.constant = 0;
+			np->lvalue = 1;
+			np->constant = 0;
 		}
 		next();
 		break;
@@ -544,7 +553,7 @@
 	case SIZEOF:
 		next();
 		tp = (yytoken == '(') ? sizeexp() : typeof(unary());
-		return node(SIZEOFCODE, inttype, tp);
+		return node(OSIZE, inttype, TYPE(tp), NULL);
 	case INC: case DEC:
 		op = (yytoken == INC) ? OA_ADD : OA_SUB;
 		next();
@@ -584,7 +593,7 @@
 				unexpected();
 			if ((np2 = convert(np1,  tp, 1)) == NULL)
 				error("bad type convertion requested");
-			np2->b.lvalue = np1->b.lvalue;
+			np2->lvalue = np1->lvalue;
 		}
 		break;
 	default:
@@ -747,17 +756,21 @@
 static Node *
 ternary(void)
 {
-	Node *np, *ifyes, *ifno;
+	Node *cond;
 
-	np = or();
+	cond = or();
 	while (accept('?')) {
+		Node *ifyes, *ifno, *np;
+
+		cond = exp2cond(cond, 0);
 		ifyes = promote(expr());
 		expect(':');
 		ifno = promote(ternary());
 		typeconv(&ifyes, &ifno);
-		np = node(TERNARY, ifyes->type, np, ifyes, ifno);
+		np = node(0, ifyes->type, ifyes, ifno);
+		cond = node(OASK, np->type, cond, np);
 	}
-	return np;
+	return cond;
 }
 
 static Node *
@@ -796,7 +809,7 @@
 	np1 = assign();
 	while (accept(',')) {
 		np2 = assign();
-		np1 = node(BINARY, np2->type, OCOMMA, np1, np2);
+		np1 = node(OCOMMA, np2->type, np1, np2);
 	}
 
 	return np1;