commit da01b5b34350799af71e675af4de842c6242409d
parent f7c8c86019559e2033978a962265f31b5681605c
Author: m21c <ho*******@gmail.com>
Date: Tue, 20 Jul 2021 19:47:41 +0200
changed the way statement-lists work
Diffstat:
| M | aria.c | | | 1209 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
1 file changed, 609 insertions(+), 600 deletions(-)
diff --git a/aria.c b/aria.c
@@ -213,7 +213,7 @@ struct Node {
} u;
Node *lhs, *rhs;
- Node *prev, *next;
+ /* ASTMT: rhs points to next stmt (linked list) */
};
struct Type {
@@ -939,8 +939,6 @@ skipwhite:
source->tok.u.u = 0;
source->tok.lhs = NULL;
source->tok.rhs = NULL;
- source->tok.prev = NULL;
- source->tok.next = NULL;
source->tok.loc.column = source->currloc.column;
/* get line */
@@ -1376,8 +1374,6 @@ makenode(Node *tok, Node *lhs) {
*node = *tok;
node->lhs = lhs;
node->rhs = NULL;
- node->next = NULL;
- node->prev = NULL;
return node;
}
@@ -1924,7 +1920,7 @@ isatom(Source *source) {
Node *
stmtlist(Source *source, int indent, EnvKind envkind) {
- Node *result = NULL, *lhs = NULL;
+ Node *head = NULL, *tail = NULL;
int needindent = nextindent(source, indent);
Env *env = NULL;
@@ -1954,7 +1950,7 @@ stmtlist(Source *source, int indent, EnvKind envkind) {
if (!isatom(source))
break;
- if (lhs && source->lastkind != '\n' && source->lastkind != ';')
+ if (tail && source->lastkind != '\n' && source->lastkind != ';')
error(getloc(source), "expected line delimiter");
if (!env) {
@@ -1975,12 +1971,11 @@ stmtlist(Source *source, int indent, EnvKind envkind) {
stmt = makenode(&source->tok, stmt);
stmt->kind = ASTMT;
- if (!lhs) {
- result = lhs = stmt;
+ if (!tail) {
+ head = tail = stmt;
} else {
- lhs->next = stmt;
- lhs->next->prev = lhs;
- lhs = lhs->next;
+ tail->rhs = stmt;
+ tail = stmt;
}
}
@@ -1995,13 +1990,13 @@ stmtlist(Source *source, int indent, EnvKind envkind) {
} else if (env) {
popenv(source);
- result = makenode(&source->tok, result);
- result->kind = ASCOPE;
- result->u.env = env;
- env->stmts = result;
+ head = makenode(&source->tok, head);
+ head->kind = ASCOPE;
+ head->u.env = env;
+ env->stmts = head;
}
- return result;
+ return head;
}
Node *
@@ -2511,21 +2506,6 @@ convint(int srcsize, bool srcsigned, uint64_t value) {
return value;
}
-void
-relinknodes(Node *dst, Node *src) {
- if (src->next) {
- dst->next = src->next;
- dst->next->prev = dst;
- src->next = NULL;
- }
-
- if (src->prev) {
- dst->prev = src->prev;
- dst->prev->next = dst;
- src->prev = NULL;
- }
-}
-
Node *
conv(Node *node);
@@ -2651,7 +2631,6 @@ wrap(Type *ty, Node *node) {
node = makenode(node, node);
node->kind = ACONV;
node->type = ty;
- relinknodes(node, node->lhs);
return node;
}
@@ -2718,336 +2697,345 @@ arithtuplereorder(Env *env, Node *expr, int numops) {
Node *
typecheck(Env *env, Node *expr) {
- Node *c;
- for (c = expr; c; c = c->next) {
- Node *lhs = c->lhs, *rhs = c->rhs;
+ Node *lhs = expr->lhs, *rhs = expr->rhs;
+
+ switch (getnumops(expr->kind)) {
+ case 2:
+ assert(rhs);
+ if (rhs->type->kind == TERRTYPE)
+ expr->type = prim + TERRTYPE;
+ case 1:
+ assert(lhs);
+ if (lhs->type->kind == TERRTYPE)
+ expr->type = prim + TERRTYPE;
+ }
+
+ if (expr->type && expr->type->kind == TERRTYPE)
+ return expr;
- switch (getnumops(c->kind)) {
- case 2:
- assert(rhs);
- if (rhs->type->kind == TERRTYPE)
- c->type = prim + TERRTYPE;
- case 1:
- assert(lhs);
- if (lhs->type->kind == TERRTYPE)
- c->type = prim + TERRTYPE;
+ switch (expr->kind) {
+ case OLPTR:
+ expr->type = expr->lhs->type;
+ return expr;
+
+ case OPLUS: case OMINUS:
+ lhs = typecheck(env, lhs);
+
+ if (arithtuplereorder(env, expr, 1))
+ goto joincomma;
+
+ /*
+ if (!isarithtype(lhs->type)) {
+ error(&lhs->loc, "expression is not of arithmentic type");
+ expr->type = prim + TERRTYPE;
+ break;
}
+ */
- if (c->type && c->type->kind == TERRTYPE)
- continue;
+ expr->type = lhs->type;
+ expr->lhs = conv(lhs);
+ return expr;
- switch (c->kind) {
- case OLPTR:
- c->type = c->lhs->type;
- continue;
+ case OBNOT:
+ lhs = typecheck(env, lhs);
- case OPLUS: case OMINUS:
- lhs = typecheck(env, lhs);
+ if (arithtuplereorder(env, expr, 1))
+ goto joincomma;
- if (arithtuplereorder(env, c, 1))
- goto joincomma;
+ if (!isinttype(lhs->type)) {
+ error(
+ &lhs->loc,
+ "expression is not of integer type"
+ );
- /*
- if (!isarithtype(lhs->type)) {
- error(&lhs->loc, "expression is not of arithmentic type");
- c->type = prim + TERRTYPE;
- break;
- }
- */
+ expr->type = prim + TERRTYPE;
+ return expr;
+ }
- c->type = lhs->type;
- c->lhs = conv(lhs);
- continue;
+ expr->type = lhs->type;
+ expr->lhs = conv(lhs);
+ return expr;
- case OBNOT:
- lhs = typecheck(env, lhs);
+ case OLNOT:
+ lhs = typecheck(env, lhs);
- if (arithtuplereorder(env, c, 1))
- goto joincomma;
+ if (arithtuplereorder(env, expr, 1))
+ goto joincomma;
- if (!isinttype(lhs->type)) {
- error(
- &lhs->loc,
- "expression is not of integer type"
- );
+ if (!isarithtype(lhs->type)) {
+ error(
+ &lhs->loc,
+ "expression is not of arithmentic type"
+ );
- c->type = prim + TERRTYPE;
- continue;
- }
+ expr->type = prim + TERRTYPE;
+ return expr;
+ }
- c->type = lhs->type;
- c->lhs = conv(lhs);
- continue;
+ expr->type = prim + TBOOL;
+ expr->lhs = conv(lhs);
+ return expr;
- case OLNOT:
- lhs = typecheck(env, lhs);
+ case OCAST:
+ /*
+ assert(rhs);
+ assert(lhs->kind == 'T');
+ */
- if (arithtuplereorder(env, c, 1))
- goto joincomma;
+ if (arithtuplereorder(env, expr, 1))
+ goto joincomma;
- if (!isarithtype(lhs->type)) {
- error(
- &lhs->loc,
- "expression is not of arithmentic type"
- );
+ /* expr->type = expr->lhs->type; */
+ return expr;
- c->type = prim + TERRTYPE;
- continue;
- }
+ case OMUL: case ODIV: case OMOD:
+ case OADD: case OSUB:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- c->type = prim + TBOOL;
- c->lhs = conv(lhs);
- continue;
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- case OCAST:
- /*
- assert(rhs);
- assert(lhs->kind == 'T');
- */
+ /* usual arithmetic conversion */
+ if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
+ if (lhs->type->kind < rhs->type->kind)
+ expr->type = rhs->type;
+ else
+ expr->type = lhs->type;
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of arithmentic type"
+ );
- if (arithtuplereorder(env, c, 1))
- goto joincomma;
+ expr->type = prim + TERRTYPE;
+ return expr;
+ }
- /* c->type = c->lhs->type; */
- continue;
+ expr->lhs = wrap(expr->type, lhs);
+ expr->rhs = wrap(expr->type, rhs);
+ return expr;
- case OMUL: case ODIV: case OMOD:
- case OADD: case OSUB:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ case OBAND: case OBOR: case OXOR:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- /* usual arithmetic conversion */
- if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
- if (lhs->type->kind < rhs->type->kind)
- c->type = rhs->type;
- else
- c->type = lhs->type;
+ if (isinttype(lhs->type) && isinttype(rhs->type)) {
+ if (lhs->type->kind < rhs->type->kind) {
+ expr->type = rhs->type;
} else {
- error(
- &c->loc,
- "expression is not of arithmentic type"
- );
-
- c->type = prim + TERRTYPE;
- continue;
+ expr->type = lhs->type;
}
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of integer type"
+ );
- c->lhs = wrap(c->type, lhs);
- c->rhs = wrap(c->type, rhs);
- break;
+ expr->type = prim + TERRTYPE;
+ }
- case OBAND: case OBOR: case OXOR:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ expr->lhs = wrap(expr->type, lhs);
+ expr->rhs = wrap(expr->type, rhs);
+ return expr;
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
+ case OLSH: case ORSH: case OARSH:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- if (isinttype(lhs->type) && isinttype(rhs->type)) {
- if (lhs->type->kind < rhs->type->kind) {
- c->type = rhs->type;
- } else {
- c->type = lhs->type;
- }
- } else {
- error(
- &c->loc,
- "expression is not of integer type"
- );
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- c->type = prim + TERRTYPE;
- }
+ if (isinttype(lhs->type) && isinttype(rhs->type)) {
+ expr->type = lhs->type;
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of integer type"
+ );
- c->lhs = wrap(c->type, lhs);
- c->rhs = wrap(c->type, rhs);
- continue;
+ expr->type = prim + TERRTYPE;
+ }
- case OLSH: case ORSH: case OARSH:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ expr->lhs = wrap(expr->type, lhs); /* this should be unneeded */
+ expr->rhs = wrap(expr->type, rhs);
+ return expr;
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
+ case OEQU: case ONEQ:
+ case OLET: case OLEQ:
+ case OGRT: case OGEQ:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- if (isinttype(lhs->type) && isinttype(rhs->type)) {
- c->type = lhs->type;
- } else {
- error(
- &c->loc,
- "expression is not of integer type"
- );
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- c->type = prim + TERRTYPE;
- }
+ if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
+ expr->type = prim + TBOOL;
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of integer type"
+ );
- c->lhs = wrap(c->type, lhs); /* this should be unneeded */
- c->rhs = wrap(c->type, rhs);
- continue;
+ expr->type = prim + TERRTYPE;
+ }
- case OEQU: case ONEQ:
- case OLET: case OLEQ:
- case OGRT: case OGEQ:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ expr->lhs = conv(lhs);
+ expr->rhs = conv(rhs);
+ return expr;
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
+ case OLAND: case OLOR:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
- c->type = prim + TBOOL;
- } else {
- error(
- &c->loc,
- "expression is not of integer type"
- );
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- c->type = prim + TERRTYPE;
- }
+ if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
+ expr->type = prim + TBOOL;
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of integer type"
+ );
- c->lhs = conv(lhs);
- c->rhs = conv(rhs);
- continue;
+ expr->type = prim + TERRTYPE;
+ }
+
+ expr->lhs = conv(lhs);
+ expr->rhs = conv(rhs);
+ return expr;
+
+ case OASS:
+ case OMULA: case ODIVA: case OMODA:
+ case OLSHA: case ORSHA: case OARSHA:
+ case OADDA: case OSUBA:
+ case OANDA:
+ case OORA: case OXORA:
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- case OLAND: case OLOR:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ if (arithtuplereorder(env, expr, 2))
+ goto joincomma;
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
+ switch ((int) expr->kind) {
+ case OASS:
+ expr->type = lhs->type;
+ return expr;
- if (isarithtype(lhs->type) && isarithtype(rhs->type)) {
- c->type = prim + TBOOL;
+ case OMULA: case ODIVA: case OMODA:
+ case OADDA: case OSUBA:
+ if (isarithtype(lhs->type) &&
+ isarithtype(rhs->type))
+ {
+ expr->type = lhs->type;
} else {
error(
- &c->loc,
- "expression is not of integer type"
+ &expr->loc,
+ "expression is not of arithmetic type"
);
- c->type = prim + TERRTYPE;
+ expr->type = prim + TERRTYPE;
}
- c->lhs = conv(lhs);
- c->rhs = conv(rhs);
- continue;
+ return expr;
- case OASS:
- case OMULA: case ODIVA: case OMODA:
case OLSHA: case ORSHA: case OARSHA:
- case OADDA: case OSUBA:
case OANDA:
case OORA: case OXORA:
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
-
- if (arithtuplereorder(env, c, 2))
- goto joincomma;
-
- switch ((int) c->kind) {
- case OASS:
- c->type = lhs->type;
- continue;
-
- case OMULA: case ODIVA: case OMODA:
- case OADDA: case OSUBA:
- if (isarithtype(lhs->type) &&
- isarithtype(rhs->type))
- {
- c->type = lhs->type;
- } else {
- error(
- &c->loc,
- "expression is not of arithmetic type"
- );
-
- c->type = prim + TERRTYPE;
- }
-
- continue;
-
- case OLSHA: case ORSHA: case OARSHA:
- case OANDA:
- case OORA: case OXORA:
- if (isinttype(lhs->type) &&
- isinttype(rhs->type))
- {
- c->type = lhs->type;
- } else {
- error(
- &c->loc,
- "expression is not of integer type"
- );
-
- c->type = prim + TERRTYPE;
- }
+ if (isinttype(lhs->type) &&
+ isinttype(rhs->type))
+ {
+ expr->type = lhs->type;
+ } else {
+ error(
+ &expr->loc,
+ "expression is not of integer type"
+ );
- continue;
+ expr->type = prim + TERRTYPE;
}
- c->lhs = conv(lhs);
- c->rhs = wrap(c->type, rhs);
- continue;
-
- case ADECL:
- if (c->lhs)
- c->lhs = wrap(c->type, typecheck(env, c->lhs));
-
- continue;
+ return expr;
+ }
- joincomma:
- lhs = c->lhs;
- rhs = c->rhs;
- case ACOMMA:
- assert(lhs);
- assert(rhs);
-
- /* TODO(m21c): make sure that typechecking is done
- * correctly, since comma might be re-
- * ordered:
- * - check that maketype is NOT called
- * multiple times and/or discarded on
- * the same node.
- * - check wether the resulting type
- * does account for nesting on rhs */
-
- if (lhs->type->kind == TERRTYPE || rhs->type->kind == TERRTYPE) {
- c->type = prim + TERRTYPE;
- continue;
- }
+ expr->lhs = conv(lhs);
+ expr->rhs = wrap(expr->type, rhs);
+ return expr;
+
+ case ASTMT:
+ rhs = expr;
+ advancestmt:
+ lhs = typecheck(env, lhs);
+ rhs->lhs = lhs;
+ if (rhs->rhs) {
+ assert(rhs->rhs->kind == ASTMT);
+ rhs = rhs->rhs, lhs = rhs->lhs;
+ goto advancestmt;
+ }
+ return expr;
+
+ case ADECL:
+ if (expr->lhs)
+ expr->lhs = wrap(expr->type, typecheck(env, expr->lhs));
+
+ return expr;
+
+ joincomma:
+ lhs = expr->lhs;
+ rhs = expr->rhs;
+ case ACOMMA:
+ assert(lhs);
+ assert(rhs);
+
+ /* TODO(m21c): make sure that typechecking is done
+ * correctly, since comma might be re-
+ * ordered:
+ * - check that maketype is NOT called
+ * multiple times and/or discarded on
+ * the same node.
+ * - check wether the resulting type
+ * does account for nesting on rhs */
+
+ if (lhs->type->kind == TERRTYPE || rhs->type->kind == TERRTYPE) {
+ expr->type = prim + TERRTYPE;
+ return expr;
+ }
- lhs = typecheck(env, lhs);
- rhs = typecheck(env, rhs);
+ lhs = typecheck(env, lhs);
+ rhs = typecheck(env, rhs);
- /* NOTE(m21c): converting nodes may be uneccessary */
- c->lhs = conv(lhs);
- c->rhs = conv(rhs);
+ /* NOTE(m21c): converting nodes may be uneccessary */
+ expr->lhs = conv(lhs);
+ expr->rhs = conv(rhs);
- c->type = maketype(&c->loc, prim + TTUPLE, lhs->type);
- c->type->u.rtarget = rhs->type;
- continue;
+ expr->type = maketype(&expr->loc, prim + TTUPLE, lhs->type);
+ expr->type->u.rtarget = rhs->type;
+ return expr;
- case ASCOPE:
- assert(c->lhs);
- assert(c->u.env);
+ case ASCOPE:
+ assert(expr->lhs);
+ assert(expr->u.env);
- c->lhs = typecheck(c->u.env, c->lhs);
+ expr->lhs = typecheck(expr->u.env, expr->lhs);
- continue;
+ return expr;
- case AADDR:
- case ADEREF:
- assert(c->lhs);
- c->lhs = typecheck(env, c->lhs);
- c->lhs = conv(c->lhs);
+ case AADDR:
+ case ADEREF:
+ assert(expr->lhs);
+ expr->lhs = typecheck(env, expr->lhs);
+ expr->lhs = conv(expr->lhs);
- continue;
+ return expr;
- default:
- continue;
- }
+ default:
+ return expr;
}
return expr;
@@ -3055,17 +3043,19 @@ typecheck(Env *env, Node *expr) {
Node *
foldexpr(Env *env, Node *expr) {
- Node *c;
+ Node *lhs = expr->lhs, *rhs = expr->rhs;
+ Type *ty = expr->type;
+
#define evalbinary(op) do { \
- c->kind = 'N'; \
+ expr->kind = 'N'; \
if (isfloattype(ty)) \
- c->u.d = maskfloat(ty->size, \
+ expr->u.d = maskfloat(ty->size, \
maskfloat(ty->size, lhs->u.d) op \
maskfloat(ty->size, rhs->u.d) \
); \
else if (isinttype(ty)) \
- c->u.u = maskint(ty->size, \
+ expr->u.u = maskint(ty->size, \
maskint(ty->size, lhs->u.u) op \
maskint(ty->size, rhs->u.u) \
); \
@@ -3076,160 +3066,175 @@ foldexpr(Env *env, Node *expr) {
((expr->u.u == value && isinttype(ty)) || \
(expr->u.d == value && isarithtype(ty))))
- for (c = expr; c; c = c->next) {
- Node *lhs = c->lhs, *rhs = c->rhs;
- Type *ty = c->type;
+ /* TODO(m21c): maybe modify getnumops() in such a way, that it
+ * will behave properly for non-operator nodes too */
+ switch (getnumops(expr->kind)) {
+ case 2:
+ rhs = foldexpr(env, rhs);
+ case 1:
+ lhs = foldexpr(env, lhs);
+ }
+
+ switch ((int) expr->kind) {
+ case IDENT:
+ do {
+ Decl *declref = finddeclaration(env, expr->u.key);
+
+ if (declref) {
+ expr->kind = ADECLREF;
+ expr->u.declref = declref;
+ expr->type = declref->type;
+ } else if (env->kind != STOPLEVEL) {
+ /* TODO(m21c): recreate Env-stack after parsing-pass */
+ error(
+ &expr->loc,
+ "'%s' undeclared",
+ getstring(idents, expr->u.key)
+ );
+ }
+ } while (0);
+
+ break;
- /* TODO(m21c): maybe modify getnumops() in such a way, that it
- * will behave properly for non-operator nodes too */
- switch (getnumops(c->kind)) {
- case 2:
- rhs = foldexpr(env, rhs);
- case 1:
- lhs = foldexpr(env, lhs);
+ case OADD: case OSUB:
+ if (lhs->kind == 'N' && rhs->kind == 'N') {
+ if (expr->kind == OADD) evalbinary(+);
+ else evalbinary(-);
+ } else if (isvalue(lhs, 0)) {
+ if (expr->kind == OADD) {
+ *expr = *rhs;
+ /* delete(lhs); delete(rhs) */
+ } else {
+ expr->kind = OMINUS;
+ expr->lhs = rhs;
+ /* delete(lhs) */
+ }
+ } else if (isvalue(rhs, 0)) {
+ *expr = *lhs;
+ /* delete(lhs); delete(rhs) */
}
- switch ((int) c->kind) {
- case IDENT:
- do {
- Decl *declref = finddeclaration(env, c->u.key);
-
- if (declref) {
- c->kind = ADECLREF;
- c->u.declref = declref;
- c->type = declref->type;
- } else if (env->kind != STOPLEVEL) {
- /* TODO(m21c): recreate Env-stack after parsing-pass */
+ break;
+
+ case OMUL: case ODIV: case OMOD:
+ if (lhs->kind == 'N' && rhs->kind == 'N') {
+ if (expr->kind == OMUL) {
+ evalbinary(*);
+ } else {
+ if (rhs->u.u == 0 && isinttype(ty)) {
error(
- &c->loc,
- "'%s' undeclared",
- getstring(idents, c->u.key)
+ &expr->loc,
+ "division by zero"
);
- }
- } while (0);
-
- break;
-
- case OADD: case OSUB:
- if (lhs->kind == 'N' && rhs->kind == 'N') {
- if (c->kind == OADD) evalbinary(+);
- else evalbinary(-);
- } else if (isvalue(lhs, 0)) {
- if (c->kind == OADD) {
- *c = *rhs;
- /* delete(lhs); delete(rhs) */
+ } else if (expr->kind == ODIV) {
+ evalbinary(/);
} else {
- c->kind = OMINUS;
- c->lhs = rhs;
- /* delete(lhs) */
+ evalbinary(/); /* TODO(m21c): implement modulus for float-types */
}
- } else if (isvalue(rhs, 0)) {
- *c = *lhs;
- /* delete(lhs); delete(rhs) */
}
+ } else if (isvalue(lhs, 0)) {
+ *expr = *lhs;
+ /* delete(lhs); delete(rhs) */
+ } else if (expr->kind == OMUL && isvalue(rhs, 0)) {
+ *expr = *rhs;
+ /* delete(lhs); delete(rhs) */
+ } else if (isvalue(rhs, 0)) {
+ if (rhs->u.u == 0 && isinttype(ty))
+ error(&expr->loc, "division by zero");
+ *expr = *rhs;
+ /* delete(lhs); delete(rhs) */
+ } else if (isvalue(lhs, 1)) {
+ *expr = *rhs;
+ /* delete(lhs); delete(rhs) */
+ } else if (expr->kind == OMUL && isvalue(rhs, 1)) {
+ *expr = *lhs;
+ /* delete(lhs); delete(rhs) */
+ }
- break;
+ break;
- case OMUL: case ODIV: case OMOD:
- if (lhs->kind == 'N' && rhs->kind == 'N') {
- if (c->kind == OMUL) {
- evalbinary(*);
- } else {
- if (rhs->u.u == 0 && isinttype(ty)) {
- error(
- &c->loc,
- "division by zero"
- );
- } else if (c->kind == ODIV) {
- evalbinary(/);
- } else {
- evalbinary(/); /* TODO(m21c): implement modulus for float-types */
- }
- }
- } else if (isvalue(lhs, 0)) {
- *c = *lhs;
- /* delete(lhs); delete(rhs) */
- } else if (c->kind == OMUL && isvalue(rhs, 0)) {
- *c = *rhs;
- /* delete(lhs); delete(rhs) */
- } else if (isvalue(rhs, 0)) {
- if (rhs->u.u == 0 && isinttype(ty))
- error(&c->loc, "division by zero");
- *c = *rhs;
- /* delete(lhs); delete(rhs) */
- } else if (isvalue(lhs, 1)) {
- *c = *rhs;
- /* delete(lhs); delete(rhs) */
- } else if (c->kind == OMUL && isvalue(rhs, 1)) {
- *c = *lhs;
- /* delete(lhs); delete(rhs) */
+ case OPLUS:
+ *expr = *lhs;
+
+ /* delete(lhs) */
+ break;
+
+ case OMINUS:
+ if (lhs->kind == 'N') {
+ if (isfloattype(ty)) {
+ expr->kind = 'N';
+ expr->u.d = maskfloat(ty->size, -lhs->u.d);
+ /* delete(lhs) */
+ } else if (isinttype(ty)) {
+ expr->kind = 'N';
+ expr->u.u = maskint(ty->size, -lhs->u.u);
+ /* delete(lhs) */
}
+ } else if (lhs->kind == OMINUS && lhs->lhs) {
+ *expr = *lhs->lhs;
+ /* delete(lhs) */
+ }
- break;
+ break;
- case OPLUS:
- *c = *lhs;
+ case OBAND: case OBOR: case OXOR:
+ if (lhs->kind == 'N' && rhs->kind == 'N') {
+ assert(
+ isinttype(lhs->type) ||
+ lhs->type->kind == TBOOL
+ );
- /* delete(lhs) */
- break;
+ assert(
+ isinttype(rhs->type) ||
+ rhs->type->kind == TBOOL
+ );
- case OMINUS:
- if (lhs->kind == 'N') {
- if (isfloattype(ty)) {
- c->kind = 'N';
- c->u.d = maskfloat(ty->size, -lhs->u.d);
- /* delete(lhs) */
- } else if (isinttype(ty)) {
- c->kind = 'N';
- c->u.u = maskint(ty->size, -lhs->u.u);
- /* delete(lhs) */
- }
- } else if (lhs->kind == OMINUS && lhs->lhs) {
- *c = *lhs->lhs;
- /* delete(lhs) */
- }
+ lhs->u.u = maskint(ty->size, lhs->u.u);
+ rhs->u.u = maskint(ty->size, rhs->u.u);
+ if (expr->kind == OBAND)
+ expr->u.u = lhs->u.u & rhs->u.u;
+ else if (expr->kind == OBOR)
+ expr->u.u = lhs->u.u | rhs->u.u;
+ else
+ expr->u.u = lhs->u.u ^ rhs->u.u;
+ expr->kind = 'N';
+ expr->u.u = maskint(ty->size, expr->u.u);
+ }
- break;
+ break;
- case OBAND: case OBOR: case OXOR:
- if (lhs->kind == 'N' && rhs->kind == 'N') {
- assert(
- isinttype(lhs->type) ||
- lhs->type->kind == TBOOL
- );
+ case ASTMT:
+ rhs = expr;
+ advancestmt:
+ lhs = foldexpr(env, lhs);
+ rhs->lhs = lhs;
+ if (rhs->rhs) {
+ assert(rhs->rhs->kind == ASTMT);
+ rhs = rhs->rhs, lhs = rhs->lhs;
+ goto advancestmt;
+ }
+ break;
- assert(
- isinttype(rhs->type) ||
- rhs->type->kind == TBOOL
- );
+ case ACOMMA:
+ expr->lhs = foldexpr(env, lhs);
+ expr->rhs = foldexpr(env, rhs);
+ break;
- lhs->u.u = maskint(ty->size, lhs->u.u);
- rhs->u.u = maskint(ty->size, rhs->u.u);
- if (c->kind == OBAND)
- c->u.u = lhs->u.u & rhs->u.u;
- else if (c->kind == OBOR)
- c->u.u = lhs->u.u | rhs->u.u;
- else
- c->u.u = lhs->u.u ^ rhs->u.u;
- c->kind = 'N';
- c->u.u = maskint(ty->size, c->u.u);
- }
+ case ASCOPE:
+ assert(expr->lhs);
+ assert(expr->u.env);
- break;
+ expr->lhs = foldexpr(expr->u.env, expr->lhs);
- case ACONV:
- /* TODO(m21c): implement this properly! */
- lhs = foldexpr(env, lhs);
- if (lhs->type->kind == c->type->kind)
- *c = *lhs /*, delete(lhs) */;
+ return expr;
- break;
+ case ACONV:
+ /* TODO(m21c): implement this properly! */
+ lhs = foldexpr(env, lhs);
+ if (lhs->type->kind == expr->type->kind)
+ *expr = *lhs /*, delete(lhs) */;
- case ACOMMA:
- c->lhs = foldexpr(env, lhs);
- c->rhs = foldexpr(env, rhs);
- break;
- }
+ break;
}
return expr;
@@ -3515,13 +3520,10 @@ printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent)
return 0;
prec = getprec(expr->kind);
- if (expr->next || (
- !isatomnode(expr->kind) && (
- !getnumops(expr->kind) || prec < opprec ||
- (braceequalprec && prec == opprec)
- )
- )
- ) {
+ if (!isatomnode(expr->kind) && (
+ !getnumops(expr->kind) || prec < opprec ||
+ (braceequalprec && prec == opprec)))
+ {
n += highlight(out, HLDELIM);
n += fprintf(out, "(");
n += highlight(out, HLNONE);
@@ -3604,200 +3606,207 @@ printdeclaration(FILE *out, Decl *decl, int indent) {
int
printexpr(FILE *out, Node *expr, int indent) {
- Node *c;
int n = 0;
- for (c = expr; c; c = c->next) {
- if (c->kind == ASTMT) {
- int i;
-
- for (i = 0; i < indent; ++i)
- n += fprintf(out, "\t");
- }
-
- if (getnumops(c->kind) == 2) {
- n += printoperant(out, c->lhs, getprec(c->kind), israssoc(c->kind), indent);
- n += highlight(out, HLDELIM);
- n += printf(" %s ", nodestrings[c->kind]);
- n += printoperant(out, c->rhs, getprec(c->kind), !israssoc(c->kind), indent);
- } else if (getnumops(c->kind) == 1) {
- if (getprec(c->kind) == PUNSUF) {
- printoperant(out, c->lhs, PUNSUF, false, indent);
- switch (c->kind) {
- case OARRAY:
- case OCALL:
- n += highlight(out, HLDELIM);
- n += fprintf(out, "%c", nodestrings[c->kind][0]);
- n += printexpr(out, c->rhs, indent);
- n += highlight(out, HLDELIM);
- n += fprintf(out, "%c", nodestrings[c->kind][1]);
- break;
-
- case ODISP:
- n += highlight(out, HLDELIM);
- n += fprintf(out, ".");
- n += printexpr(out, c->rhs, indent);
- break;
+ if (getnumops(expr->kind) == 2) {
+ n += printoperant(out, expr->lhs, getprec(expr->kind), israssoc(expr->kind), indent);
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, " %s ", nodestrings[expr->kind]);
+ n += printoperant(out, expr->rhs, getprec(expr->kind), !israssoc(expr->kind), indent);
+ } else if (getnumops(expr->kind) == 1) {
+ if (getprec(expr->kind) == PUNSUF) {
+ printoperant(out, expr->lhs, PUNSUF, false, indent);
+ switch (expr->kind) {
+ case OARRAY:
+ case OCALL:
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, "%c", nodestrings[expr->kind][0]);
+ n += printexpr(out, expr->rhs, indent);
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, "%c", nodestrings[expr->kind][1]);
+ break;
- default:
- n += highlight(out, HLDELIM);
- n += fprintf(out, "%s", nodestrings[c->kind]);
- }
- } else {
- switch (c->kind) {
- case OCAST:
- n += highlight(out, HLDELIM);
- putc('(', out), ++n;
- n += highlight(out, HLTYPE);
- n += printtype(out, c->type, indent);
- n += highlight(out, HLDELIM);
- putc(')', out), ++n;
- break;
+ case ODISP:
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, ".");
+ n += printexpr(out, expr->rhs, indent);
+ break;
- default:
- n += highlight(out, HLDELIM);
- n += fprintf(out, "%s", nodestrings[c->kind]);
- if (getprec(c->lhs->kind) == PUNARY &&
- c->kind != OLPTR)
- {
- putc(' ', out), ++n;
- }
- }
- n += printoperant(out, c->lhs, PUNARY, false, indent);
+ default:
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, "%s", nodestrings[expr->kind]);
}
} else {
- switch (c->kind)
- {
- case 'I':
- n += highlight(out, HLUNKNOWN);
- n += fprintf(out, "%s?", getstring(idents, c->u.key));
- n += highlight(out, HLNONE);
- break;
-
- case 'N':
- n += highlight(out, HLNUMBER);
- if (c->type->kind == TFLOAT ||
- c->type->kind == TDOUBLE ||
- c->type->kind == TLDOUBLE)
- n += fprintf(out, "%f", c->u.d);
- else if (expr->type->kind & (TUINT - TINT))
- n += fprintf(out, "%li", c->u.s);
- else
- n += fprintf(out, "%lu", c->u.u);
- n += printtypesuffix(out, c->type, indent);
+ switch (expr->kind) {
+ case OCAST:
+ n += highlight(out, HLDELIM);
+ putc('(', out), ++n;
+ n += highlight(out, HLTYPE);
+ n += printtype(out, expr->type, indent);
+ n += highlight(out, HLDELIM);
+ putc(')', out), ++n;
break;
- case 'S':
- n += highlight(out, HLSTRING);
- n += printstring(out, c);
- break;
+ default:
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, "%s", nodestrings[expr->kind]);
+ if (getprec(expr->lhs->kind) == PUNARY &&
+ expr->kind != OLPTR)
+ {
+ putc(' ', out), ++n;
+ }
+ }
+ n += printoperant(out, expr->lhs, PUNARY, false, indent);
+ }
+ } else {
+ switch (expr->kind)
+ {
+ case 'I':
+ n += highlight(out, HLUNKNOWN);
+ n += fprintf(out, "%s?", getstring(idents, expr->u.key));
+ n += highlight(out, HLNONE);
+ break;
- case ADECLREF:
- n += highlight(out,
- c->u.declref->kind == DFUNCTION ? HLFUNCTION :
- c->u.declref->kind == DPARAM ? HLPARAM :
- HLIDENT);
- n += fprintf(out, "%s", getstring(idents, c->u.declref->key));
- break;
+ case 'N':
+ n += highlight(out, HLNUMBER);
+ if (expr->type->kind == TFLOAT ||
+ expr->type->kind == TDOUBLE ||
+ expr->type->kind == TLDOUBLE)
+ n += fprintf(out, "%f", expr->u.d);
+ else if (expr->type->kind & (TUINT - TINT))
+ n += fprintf(out, "%li", expr->u.s);
+ else
+ n += fprintf(out, "%lu", expr->u.u);
+ n += printtypesuffix(out, expr->type, indent);
+ break;
- case ADECL:
- n += printdeclaration(out, c->u.declref, indent);
- break;
+ case 'S':
+ n += highlight(out, HLSTRING);
+ n += printstring(out, expr);
+ break;
- case ACOMMA:
- n += printsubexpr(out, c->lhs, true, indent);
- n += highlight(out, HLDELIM);
- n += printf(", ");
- n += printsubexpr(out, c->rhs, false, indent);
- break;
+ case ADECLREF:
+ n += highlight(out,
+ expr->u.declref->kind == DFUNCTION ? HLFUNCTION :
+ expr->u.declref->kind == DPARAM ? HLPARAM :
+ HLIDENT);
+ n += fprintf(out, "%s", getstring(idents, expr->u.declref->key));
+ break;
- case ARETURN:
- n += highlight(out, HLKEYWORD);
- n += fprintf(out, "return ");
- n += printexpr(out, c->rhs, indent);
- break;
+ case ADECL:
+ n += printdeclaration(out, expr->u.declref, indent);
+ break;
- case ABREAK:
- n += highlight(out, HLKEYWORD);
- n += fprintf(out, "break");
- break;
+ case ACOMMA:
+ n += printsubexpr(out, expr->lhs, true, indent);
+ n += highlight(out, HLDELIM);
+ n += printf(", ");
+ n += printsubexpr(out, expr->rhs, false, indent);
+ break;
- case ACONTINUE:
- n += highlight(out, HLKEYWORD);
- n += fprintf(out, "continue");
- break;
+ case ARETURN:
+ n += highlight(out, HLKEYWORD);
+ n += fprintf(out, "return ");
+ n += printexpr(out, expr->rhs, indent);
+ break;
- case AIF:
- n += highlight(out, HLKEYWORD);
- n += fprintf(out, "if ");
- n += printexpr(out, c->u.payload, indent);
- n += printclause(out, c->lhs, indent);
- if (c->rhs) {
- int i;
-
- n += fprintf(out, "\n");
- for (i = 0; i < indent; ++i)
- n += fprintf(out, "\t");
- n += highlight(out, HLKEYWORD);
- n += fprintf(out, "else");
- n += printclause(out, c->rhs, indent);
- }
+ case ABREAK:
+ n += highlight(out, HLKEYWORD);
+ n += fprintf(out, "break");
+ break;
- break;
+ case ACONTINUE:
+ n += highlight(out, HLKEYWORD);
+ n += fprintf(out, "continue");
+ break;
- case ADO:
+ case AIF:
+ n += highlight(out, HLKEYWORD);
+ n += fprintf(out, "if ");
+ n += printexpr(out, expr->u.payload, indent);
+ n += printclause(out, expr->lhs, indent);
+ if (expr->rhs) {
+ int i;
+
+ n += fprintf(out, "\n");
+ for (i = 0; i < indent; ++i)
+ n += fprintf(out, "\t");
n += highlight(out, HLKEYWORD);
- n += fprintf(out, "do");
- n += printclause(out, c->lhs, indent);
- break;
+ n += fprintf(out, "else");
+ n += printclause(out, expr->rhs, indent);
+ }
- case ASTMT:
- n += printexpr(out, c->lhs, indent);
- break;
+ break;
- case ASCOPE:
- n += printexpr(out, c->lhs, indent);
- break;
+ case ADO:
+ n += highlight(out, HLKEYWORD);
+ n += fprintf(out, "do");
+ n += printclause(out, expr->lhs, indent);
+ break;
- case ACONV:
- n += highlight(out, HLDELIM);
- n += fprintf(out, "conv(");
- n += highlight(out, HLTYPE);
- n += printtype(out, c->type, indent);
- n += highlight(out, HLDELIM);
- n += fprintf(out, ") ");
- n += printoperant(out, c->lhs, PUNARY, false, indent);
- break;
+ case ASTMT:
+ advancestmt:
+ do {
+ int i;
- case AADDR:
- n += highlight(out, HLDELIM);
- n += fputs("&{", out);
- n += printoperant(out, c->lhs, PUNARY, false, indent);
- n += highlight(out, HLDELIM);
- n += fputs("}", out);
- break;
+ for (i = 0; i < indent; ++i)
+ n += fprintf(out, "\t");
+ } while (0);
- case ADEREF:
- n += highlight(out, HLDELIM);
- n += fputs("*{", out);
- n += printoperant(out, c->lhs, PUNARY, false, indent);
- n += highlight(out, HLDELIM);
- n += fputs("}", out);
- break;
+ n += printexpr(out, expr->lhs, indent);
- default:
- break;
+ if (expr->rhs) {
+ assert(expr->rhs->kind == ASTMT);
+ n += fprintf(out, "\n");
+ expr = expr->rhs;
+ goto advancestmt;
}
- }
+ break;
- if (c->kind == ASTMT && c->next) {
- n += fprintf(out, "\n");
- } else if (c->next) {
+ case ASCOPE:
+ n += printexpr(out, expr->lhs, indent);
+ break;
+
+ case ACONV:
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, "conv(");
+ n += highlight(out, HLTYPE);
+ n += printtype(out, expr->type, indent);
n += highlight(out, HLDELIM);
- n += fprintf(out, ", ");
+ n += fprintf(out, ") ");
+ n += printoperant(out, expr->lhs, PUNARY, false, indent);
+ break;
+
+ case AADDR:
+ n += highlight(out, HLDELIM);
+ n += fputs("&{", out);
+ n += printoperant(out, expr->lhs, PUNARY, false, indent);
+ n += highlight(out, HLDELIM);
+ n += fputs("}", out);
+ break;
+
+ case ADEREF:
+ n += highlight(out, HLDELIM);
+ n += fputs("*{", out);
+ n += printoperant(out, expr->lhs, PUNARY, false, indent);
+ n += highlight(out, HLDELIM);
+ n += fputs("}", out);
+ break;
+
+ default:
+ break;
}
}
+ #if 0
+ if (expr->kind == ASTMT && expr->next) {
+ n += fprintf(out, "\n");
+ } else if (expr->next) {
+ n += highlight(out, HLDELIM);
+ n += fprintf(out, ", ");
+ }
+ #endif
+
return n;
}