Aria

A low-level systems programming language
git clone git://git.m21c.me/Aria.git
Log | Files | Refs | LICENSE

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:
Maria.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; }