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:
| M | aria.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, ¶mtype); */
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, ¶mtype); */
+ rhs = expr(source, PASSIGN);
+ typetuple &= rhs->kind == 'T';
+ /* rhs = todeclaration(curr, ¶mtype); */
}
- 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");