Aria

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

commit f7c8c86019559e2033978a962265f31b5681605c
parent 00bb71560fd53de65b63b101118e456b4f7635c2
Author: m21c  <ho*******@gmail.com>
Date:   Tue, 20 Jul 2021 18:12:15 +0200

worked on comma parsing + tuple type-checking

Diffstat:
Maria.c | 267++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 212 insertions(+), 55 deletions(-)

diff --git a/aria.c b/aria.c @@ -83,8 +83,8 @@ typedef enum Kind { OADDA, OSUBA, OORA, OXORA, /* Ast */ - ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE, - ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, + ACOMMA, ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, + ACONTINUE, ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, ACONV, ADEREF, AADDR, @@ -117,6 +117,8 @@ typedef enum { TPTR, TARRAY, + TTUPLE, + TMAX } TypeKind; @@ -229,6 +231,7 @@ struct Type { size_t elemsize; } array; Node *val; + Type *rtarget; } u; Type *target; @@ -331,6 +334,9 @@ Type prim[] = { [TPTR] = {TPTR, defaultloc, 8, 8, {0}, NULL}, [TARRAY] = {TARRAY, defaultloc, 0, 0, {0}, NULL}, + + + [TTUPLE] = {TTUPLE, defaultloc, 0, 0, {0}, NULL}, }; int keywordlengths[OSTART - KSTART]; @@ -402,14 +408,14 @@ const char *nodestrings[] = { [KFOR] = "for", [KLOOP] = "loop", [KWHILE] = "while", [KUNTIL] = "until", /* Operators */ - [OSUFINC] = "++", [OSUFDEC] = "--", - [OARRAY] = "[]", [OCALL] = "()", + [OSUFINC] = "++", [OSUFDEC] = "--", + [OARRAY] = "[]", [OCALL] = "()", [ODISP] = ".", - [OLPTR] = "*", [OINC] = "++", - [ODEC] = "--", [OBNOT] = "~", - [OLNOT] = "!", [OFLIP] = "~=", - /*[ORPTR] = "&",*/ [OPLUS] = "+", - [OMINUS] = "-", [OCAST] = "(type)", + [OLPTR] = "*", [OINC] = "++", + [ODEC] = "--", [OBNOT] = "~", + [OLNOT] = "!", [OFLIP] = "~=", + /*[ORPTR] = "&",*/ [OPLUS] = "+", + [OMINUS] = "-", [OCAST] = "(type)", [OMUL] = "*", [ODIV] = "/", [OMOD] = "%", [OLSH] = "<<", [OARSH] = ">>>", [ORSH] = ">>", @@ -430,6 +436,7 @@ const char *nodestrings[] = { [OADDA] = "+=", [OSUBA] = "-=", [OORA] = "|=", [OXORA] = "^=", /* Ast Nodes */ + [ACOMMA] = ",", [ASTMT] = "statement", [ADO] = "do-clause", [ADECL] = "declaration", [ADECLREF] = "symbol-reference", [ALOOP] = "loop-clause", [ALOOPUNTIL] = "loop-until-clause", @@ -1244,9 +1251,9 @@ skipwhite: /* delimiters */ switch (c0) { + case ',': case ';': case '@': - case ',': case ':': case '{': case '}': @@ -1731,7 +1738,7 @@ advance: gettok(source, false); if (source->tok.kind != ']') - basetype->u.val = expr(source, PSTART); + basetype->u.val = expr(source, PASSIGN); expect(source, ']', false, "expect ']'"); goto advance; @@ -1854,7 +1861,7 @@ declaration(Source *source, Type *ty) { gettok(source, false); functionenv->kind = SFUNCTION; - node = expr(source, PSTART); + node = expr(source, PASSIGN); result->lhs = node; } else { result->lhs = NULL; @@ -1883,7 +1890,7 @@ declaration(Source *source, Type *ty) { if (getkind(source) == OASS) { gettok(source, false); - result->lhs = expr(source, PSTART); + result->lhs = expr(source, PASSIGN); assert(decl); decl->content = result->lhs; @@ -1901,8 +1908,8 @@ bool isatom(Source *source) { switch ((int) getkind(source)) { case 0: - case '\n': case ';': - case ',': case ':': + case '\n': case ',': case ';': + case ':': case ')': case ']': case '}': case KELSE: case KUNTIL: @@ -2366,55 +2373,55 @@ todeclaration(Node *curr, Node **ty) { Node * exprlist(Source *source, bool isparam, Type *paramtype) { - Node *head, *tail; + Node *lhs; bool isdeclaration, typetuple; /* tail = todeclaration(tail, &paramtype); */ if (paramtype && getkind(source) == 'I') { - head = declaration(source, paramtype), tail = head; + lhs = declaration(source, paramtype); } else { - head = expr(source, PSTART), tail = head; + lhs = expr(source, PASSIGN); } - if (isparam && tail->kind != ADECL) + if (isparam && lhs->kind != ADECL) error(getloc(source), "expected declaration"); - if ((isdeclaration = tail->kind == ADECL)) { - paramtype = tail->type; + if ((isdeclaration = lhs->kind == ADECL)) { + paramtype = lhs->type; } - typetuple = tail->kind == 'T'; + typetuple = lhs->kind == 'T'; while (getkind(source) == ',') { - Node *curr; + Node *rhs = NULL; + lhs = makenode(&source->tok, lhs); + lhs->kind = ACOMMA; gettok(source, false); if (getkind(source) == 'I' && isdeclaration) { assert(paramtype); - curr = declaration(source, paramtype); + rhs = declaration(source, paramtype); typetuple = false; } else { - curr = expr(source, PSTART); - typetuple &= curr->kind == 'T'; - /* curr = todeclaration(curr, &paramtype); */ + rhs = expr(source, PASSIGN); + typetuple &= rhs->kind == 'T'; + /* rhs = todeclaration(curr, &paramtype); */ } - if ((paramtype || isparam) && curr->kind != ADECL) + if ((paramtype || isparam) && rhs->kind != ADECL) error(getloc(source), "expected declaration"); - if (curr->kind == ADECL) { - paramtype = curr->type; + if (rhs->kind == ADECL) { + paramtype = rhs->type; isdeclaration = true; } - tail->next = curr; - tail->next->prev = tail; - tail = tail->next; + lhs->rhs = rhs; } source->lastis = NULL; - return head; + return lhs; } @@ -2663,6 +2670,52 @@ conv(Node *node) { return autoref(NULL, node); } + +Node * +typecheck(Env *env, Node *expr); + +bool +arithtuplereorder(Env *env, Node *expr, int numops) { + Node *tmp; + + if (numops == 2) { + if (expr->lhs->kind != ACOMMA) + return false; + + if (expr->rhs->kind != ACOMMA) + return false; + + /* (a, b) OP (x, y) ==> (a OP x, b OP y) */ + expr->lhs->kind = expr->kind; + expr->rhs->kind = expr->kind; + expr->kind = ACOMMA; + + tmp = expr->lhs->rhs; + expr->lhs->rhs = expr->rhs->lhs; + expr->rhs->lhs = tmp; + + return true; + } + + if (numops == 1) { + if (expr->lhs->kind != ACOMMA) + return false; + + /* OP (a, b) ==> (OP a, OP b) */ + expr->lhs->kind = expr->kind; + + tmp = expr->rhs; + expr->rhs = makenode(expr, expr->lhs->rhs); + expr->lhs->rhs = tmp; /* NOTE(m21c): some unary nodes may have a rhs? */ + expr->rhs->rhs = tmp; /* TODO(m21c): make a copy */ + expr->kind = ACOMMA; + + return true; + } + + return false; +} + Node * typecheck(Env *env, Node *expr) { Node *c; @@ -2687,11 +2740,14 @@ typecheck(Env *env, Node *expr) { switch (c->kind) { case OLPTR: c->type = c->lhs->type; - break; + continue; case OPLUS: case OMINUS: lhs = typecheck(env, lhs); + if (arithtuplereorder(env, c, 1)) + goto joincomma; + /* if (!isarithtype(lhs->type)) { error(&lhs->loc, "expression is not of arithmentic type"); @@ -2702,11 +2758,14 @@ typecheck(Env *env, Node *expr) { c->type = lhs->type; c->lhs = conv(lhs); - break; + continue; case OBNOT: lhs = typecheck(env, lhs); + if (arithtuplereorder(env, c, 1)) + goto joincomma; + if (!isinttype(lhs->type)) { error( &lhs->loc, @@ -2714,16 +2773,19 @@ typecheck(Env *env, Node *expr) { ); c->type = prim + TERRTYPE; - break; + continue; } c->type = lhs->type; c->lhs = conv(lhs); - break; + continue; case OLNOT: lhs = typecheck(env, lhs); + if (arithtuplereorder(env, c, 1)) + goto joincomma; + if (!isarithtype(lhs->type)) { error( &lhs->loc, @@ -2731,12 +2793,12 @@ typecheck(Env *env, Node *expr) { ); c->type = prim + TERRTYPE; - break; + continue; } c->type = prim + TBOOL; c->lhs = conv(lhs); - break; + continue; case OCAST: /* @@ -2744,14 +2806,20 @@ typecheck(Env *env, Node *expr) { assert(lhs->kind == 'T'); */ + if (arithtuplereorder(env, c, 1)) + goto joincomma; + /* c->type = c->lhs->type; */ - break; + continue; case OMUL: case ODIV: case OMOD: case OADD: case OSUB: lhs = typecheck(env, lhs); rhs = typecheck(env, rhs); + if (arithtuplereorder(env, c, 2)) + goto joincomma; + /* usual arithmetic conversion */ if (isarithtype(lhs->type) && isarithtype(rhs->type)) { if (lhs->type->kind < rhs->type->kind) @@ -2765,7 +2833,7 @@ typecheck(Env *env, Node *expr) { ); c->type = prim + TERRTYPE; - break; + continue; } c->lhs = wrap(c->type, lhs); @@ -2776,6 +2844,9 @@ typecheck(Env *env, Node *expr) { lhs = typecheck(env, lhs); rhs = typecheck(env, rhs); + if (arithtuplereorder(env, c, 2)) + goto joincomma; + if (isinttype(lhs->type) && isinttype(rhs->type)) { if (lhs->type->kind < rhs->type->kind) { c->type = rhs->type; @@ -2793,12 +2864,15 @@ typecheck(Env *env, Node *expr) { c->lhs = wrap(c->type, lhs); c->rhs = wrap(c->type, rhs); - break; + continue; case OLSH: case ORSH: case OARSH: lhs = typecheck(env, lhs); rhs = typecheck(env, rhs); + if (arithtuplereorder(env, c, 2)) + goto joincomma; + if (isinttype(lhs->type) && isinttype(rhs->type)) { c->type = lhs->type; } else { @@ -2812,7 +2886,7 @@ typecheck(Env *env, Node *expr) { c->lhs = wrap(c->type, lhs); /* this should be unneeded */ c->rhs = wrap(c->type, rhs); - break; + continue; case OEQU: case ONEQ: case OLET: case OLEQ: @@ -2820,6 +2894,9 @@ typecheck(Env *env, Node *expr) { lhs = typecheck(env, lhs); rhs = typecheck(env, rhs); + if (arithtuplereorder(env, c, 2)) + goto joincomma; + if (isarithtype(lhs->type) && isarithtype(rhs->type)) { c->type = prim + TBOOL; } else { @@ -2833,12 +2910,15 @@ typecheck(Env *env, Node *expr) { c->lhs = conv(lhs); c->rhs = conv(rhs); - break; + continue; case OLAND: case OLOR: lhs = typecheck(env, lhs); rhs = typecheck(env, rhs); + if (arithtuplereorder(env, c, 2)) + goto joincomma; + if (isarithtype(lhs->type) && isarithtype(rhs->type)) { c->type = prim + TBOOL; } else { @@ -2852,7 +2932,7 @@ typecheck(Env *env, Node *expr) { c->lhs = conv(lhs); c->rhs = conv(rhs); - break; + continue; case OASS: case OMULA: case ODIVA: case OMODA: @@ -2863,10 +2943,13 @@ typecheck(Env *env, Node *expr) { 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; - break; + continue; case OMULA: case ODIVA: case OMODA: case OADDA: case OSUBA: @@ -2883,7 +2966,7 @@ typecheck(Env *env, Node *expr) { c->type = prim + TERRTYPE; } - break; + continue; case OLSHA: case ORSHA: case OARSHA: case OANDA: @@ -2901,18 +2984,50 @@ typecheck(Env *env, Node *expr) { c->type = prim + TERRTYPE; } - break; + continue; } c->lhs = conv(lhs); c->rhs = wrap(c->type, rhs); - break; + continue; case ADECL: if (c->lhs) c->lhs = wrap(c->type, typecheck(env, c->lhs)); - break; + continue; + + 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; + } + + lhs = typecheck(env, lhs); + rhs = typecheck(env, rhs); + + /* NOTE(m21c): converting nodes may be uneccessary */ + c->lhs = conv(lhs); + c->rhs = conv(rhs); + + c->type = maketype(&c->loc, prim + TTUPLE, lhs->type); + c->type->u.rtarget = rhs->type; + continue; case ASCOPE: assert(c->lhs); @@ -2920,7 +3035,7 @@ typecheck(Env *env, Node *expr) { c->lhs = typecheck(c->u.env, c->lhs); - break; + continue; case AADDR: case ADEREF: @@ -2928,10 +3043,10 @@ typecheck(Env *env, Node *expr) { c->lhs = typecheck(env, c->lhs); c->lhs = conv(c->lhs); - break; + continue; default: - break; + continue; } } @@ -3109,6 +3224,11 @@ foldexpr(Env *env, Node *expr) { *c = *lhs /*, delete(lhs) */; break; + + case ACOMMA: + c->lhs = foldexpr(env, lhs); + c->rhs = foldexpr(env, rhs); + break; } } @@ -3243,7 +3363,16 @@ printtype(FILE *out, Type *type, int indent) { if (!type) return 0; - n += printtype(out, type->target, indent); + if (type->kind != TTUPLE && + type->target && + type->target->kind == TTUPLE) + { + n += fprintf(out, "("); + n += printtype(out, type->target, indent); + n += fprintf(out, ")"); + } else { + n += printtype(out, type->target, indent); + } switch (type->kind) { case TARRAY: @@ -3252,6 +3381,11 @@ printtype(FILE *out, Type *type, int indent) { n += fprintf(out, "]"); break; + case TTUPLE: + n += fprintf(out, ", "); + n += printtype(out, type->u.rtarget, indent); + break; + #define typecase(type, str) \ case type: n += fprintf(out, str); break @@ -3403,6 +3537,21 @@ printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent) } int +printsubexpr(FILE *out, Node *expr, bool islhs, int indent) { + int prec, n = 0; + + if (!expr) + return 0; + + if (islhs && expr->kind == ACOMMA || expr->kind == ADECL) + n += printexpr(out, expr, indent); + else + n += printoperant(out, expr, PSTART, !islhs, indent); + + return n; +} + +int printdeclaration(FILE *out, Decl *decl, int indent) { int n = 0; @@ -3555,6 +3704,13 @@ printexpr(FILE *out, Node *expr, int indent) { n += printdeclaration(out, c->u.declref, indent); 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 ARETURN: n += highlight(out, HLKEYWORD); n += fprintf(out, "return "); @@ -3688,6 +3844,7 @@ main(int argc, char **argv) { Node *ast; ast = exprlist(source, false, NULL); + /* ast = expr(source, PSTART); */ /* printast(ast, 0); printf("\n");