Aria

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

commit 33306912a82cb2efdc93b2e25d84704c085100e3
parent 55b25c1c04fc252550bfdb1dc5da808f8fb14fab
Author: m21c <ho*******@gmail.com>
Date:   Fri,  2 Apr 2021 23:17:36 +0200

implemented printexpr() + worked on type-checking

Diffstat:
Maria.c | 378++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 347 insertions(+), 31 deletions(-)

diff --git a/aria.c b/aria.c @@ -267,6 +267,7 @@ typedef enum Kind { /* Ast */ ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE, ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, + ACONV, MAXKINDS } Kind; @@ -279,6 +280,12 @@ typedef enum Kind { #define isoperator(kind) ((kind) >= OSTART && (kind) < ASTART) #define isastnode(kind) ((kind) >= ASTART && (kind) < MAXKINDS) +bool isatomnode(Kind kind) +{ + return kind == 'I' || kind == ADECLREF || kind == 'N' || kind == 'S' || + kind == 'C'; +} + int keywordlengths[OSTART - KSTART]; const int keywordtypeids[] = { @@ -348,14 +355,14 @@ const char *nodestrings[] = { [KFOR] = "for", [KLOOP] = "loop", [KWHILE] = "while", [KUNTIL] = "until", /* Operators */ - [OSUFINC] = "unary++", [OSUFDEC] = "unary--", - [OARRAY] = "unary[]", [OCALL] = "unary()", - [ODISP] = "unary._", - [ODEREF] = "*unary", [OINC] = "++unary", - [ODEC] = "--unary", [OBNOT] = "~unary", - [OLNOT] = "!unary", [OFLIP] = "~=unary", - [OADDR] = "&unary", [OPLUS] = "+unary", - [OMINUS] = "-unary", [OCAST] = "(type) unary", + [OSUFINC] = "++", [OSUFDEC] = "--", + [OARRAY] = "[]", [OCALL] = "()", + [ODISP] = ".", + [ODEREF] = "*", [OINC] = "++", + [ODEC] = "--", [OBNOT] = "~", + [OLNOT] = "!", [OFLIP] = "~=", + [OADDR] = "&", [OPLUS] = "+", + [OMINUS] = "-", [OCAST] = "(type)", [OMUL] = "*", [ODIV] = "/", [OMOD] = "%", [OLSH] = "<<", [OARSH] = ">>>", [ORSH] = ">>", @@ -385,6 +392,7 @@ const char *nodestrings[] = { [AGOTO] = "goto-statement", [ALABEL] = "label", [AIF] = "if-clause", [ASWITCH] = "case-clause", [ACASE] = "of-clause", + [ACONV] = "conversion", [MAXKINDS] = NULL }; @@ -467,7 +475,7 @@ const uint8_t opinfo[] = { #define getnumops(kind) (opinfo[kind] >> 6) #define israssoc(kind) ((opinfo[kind] >> 5) & 0x01) -#define getprec(kind) ((opinfo[kind] & 0x2f)) +#define getprec(kind) ((opinfo[kind] & 0x1f)) #define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array))) @@ -1335,7 +1343,12 @@ printast(Node *node, int indent) { assert(node); if (node->kind >= OSTART && node->kind != ADECLREF) - n += printf("%s(", nodestrings[node->kind]); + if (getprec(node->kind) == PUNSUF) + n += printf("unary%s(", nodestrings[node->kind]); + else if (getprec(node->kind) == PUNARY) + n += printf("%sunary(", nodestrings[node->kind]); + else + n += printf("%s(", nodestrings[node->kind]); else printnode(stdout, node); @@ -2073,6 +2086,13 @@ conv(Node *node) Node * wrap(Type *ty, Node *node) { + if (node->type && ty->kind == node->type->kind) + return node; + if (node->kind == 'N') + return node->type = ty, node; + node = makenode(node); + node->kind = ACONV; + node->type = ty; return node; } @@ -2082,31 +2102,63 @@ usualarithconv(Type *lt, Type *rt) return lt; } -#if 0 - typedef Node *(*RuleFunc)(Node *expr); Node * -emptyrule(Node *expr) -{ - return expr; -} +foldexpr(Node *expr); Node * identrule(Node *ident) { - ident->u.declref.ref = finddeclaration(ident->u.id); - if (ident->u.declref.ref) { - ident->kind = 'A'; - ident->u.declref.id = ADECLREF; + Decl *declref = finddeclaration(ident->u.key); + + if (declref) { + ident->kind = ADECLREF; + ident->u.declref = declref; } else { - error("'%s' undeclared", getstring(idents, ident->u.id)); + error("'%s' undeclared", getstring(idents, ident->u.key)); } return ident; } +Node * +binaryarithrule(Node *binary) +{ + Node *lhs = binary->lhs; + Node *rhs = binary->rhs; + Type *tt; + + if (!lhs) return binary; + if (!rhs) return binary; + + lhs = foldexpr(lhs); + rhs = foldexpr(rhs); + tt = usualarithconv(lhs->type, rhs->type); + lhs = wrap(tt, lhs); + rhs = wrap(tt, rhs); + binary->type = tt; + + binary->lhs = lhs; + binary->rhs = rhs; + return binary; +} + +RuleFunc ruletable[] = { + ['I'] = &identrule, + + [OMUL] = &binaryarithrule, + [ODIV] = &binaryarithrule, + [OMOD] = &binaryarithrule, + [OADD] = &binaryarithrule, + [OSUB] = &binaryarithrule, + + [MAXKINDS] = NULL +}; + +#if 0 + RuleFunc opfunctable[] = { [OSUFINC] = &emptyrule, [OSUFDEC] = &emptyrule, [OARRAY] = &emptyrule, [OCALL] = &emptyrule, @@ -2179,22 +2231,18 @@ astrules(Node *expr) return astfunctable[expr->u.id](expr); } -RuleFunc ruletable[] = { - ['A'] = &astrules, - ['I'] = &identrule, - ['O'] = &oprules, - - [127] = NULL -}; - #endif -Node *foldexpr(Node *expr) +Node * +foldexpr(Node *expr) { Node *c, *n; for (c = expr; c; c = c->next) { -#if 1 +#if 0 + if (c->kind == ADECL) + continue; + if (c->kind == 'I') { Decl *declref = finddeclaration(c->u.key); if (declref) { @@ -2231,6 +2279,267 @@ Node *foldexpr(Node *expr) return expr; } +/* - print ast */ + +int +printexpr(FILE *out, Node *expr, int indent); + +int printtype(FILE *out, Type *type, int indent) +{ + int n = 0; + + if (!type) + return 0; + + n += printtype(out, type->target, indent); + + switch (type->kind) { + case TARRAY: + n += fprintf(out, "["); + n += printexpr(out, type->u.val, indent); + n += fprintf(out, "]"); + break; + #define typecase(type, str) \ + case type: n += fprintf(out, str); break + typecase(TPTR, "*"); + typecase(TVOID, "void"); typecase(TBOOL, "bool"); + typecase(TU8, "u8" ); typecase(TS8, "s8" ); + typecase(TU16, "u16" ); typecase(TS16, "s16" ); + typecase(TU32, "u32" ); typecase(TS32, "s32" ); + typecase(TU64, "u64" ); typecase(TS64, "s64" ); + typecase(TF32, "f32" ); typecase(TF64, "f64" ); + #undef typecase + default:; + } +} + +bool +isclauseorempty(Node *expr) +{ + Kind kind; + + while (expr && (expr->kind == ASCOPE || expr->kind == ASTMT)) + expr = expr->lhs; + + if (!expr) + return true; + + kind = expr->kind; + return kind == ADO || kind == AIF || kind == AFOR || kind == AGOTO || + kind == ARETURN || kind == ABREAK || kind == ACONTINUE; +} + +int +printclause(FILE *out, Node *expr, int indent) +{ + int n = 0; + + if (isclauseorempty(expr)) { + n += fprintf(out, " "); + n += printexpr(out, expr, indent); + } else { + n += fprintf(out, "\n"); + n += printexpr(out, expr, indent + 1); + } + + return n; +} + +int +printstring(FILE *out, Node *string) +{ + const char *str = getstring(strings, string->u.key); + int len = getlength(strings, string->u.key); + int i, n = fprintf(out, "\""); + for (i = 0; i < len; ++i) { + switch (str[i]) { + case '\\': + n += fprintf(out, "\\\\"); + break; + case '\n': + n += fprintf(out, "\\n"); + break; + case '\r': + n += fprintf(out, "\\r"); + break; + case '\t': + n += fprintf(out, "\\t"); + break; + case '\"': + n += fprintf(out, "\\\""); + break; + case '\'': + n += fprintf(out, "\\\'"); + break; + case 0: + n += fprintf(out, "\\0"); + break; + default: + putc(str[i], out); + ++n; + } + } + n += fprintf(out, "\""); + +} + +int +printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent) +{ + int prec, n = 0; + + if (!expr) + return 0; + + prec = getprec(expr->kind); + if (expr->next || ( + !isatomnode(expr->kind) && ( + !getnumops(expr->kind) || prec < opprec || + (braceequalprec && prec == prec) + ) + ) + ) { + n += fprintf(out, "("); + n += printexpr(out, expr, indent); + n += fprintf(out, ")"); + } else { + n += printexpr(out, expr, indent); + } + + return n; +} + +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 += 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 += fprintf(out, "%c", nodestrings[c->kind][0]); + n += printexpr(out, c->rhs, indent); + n += fprintf(out, "%c", nodestrings[c->kind][1]); + break; + case ODISP: + n += fprintf(out, "."); + n += printexpr(out, c->rhs, indent); + break; + default: + n += fprintf(out, "%s", nodestrings[c->kind]); + } + } else { + switch (c->kind) { + case OCAST: + default: + n += fprintf(out, "%s", nodestrings[c->kind]); + } + n += printoperant(out, c->lhs, PUNARY, false, indent); + } + } else { + switch (c->kind) + { + case 'I': + n += fprintf(out, "%s?", getstring(idents, c->u.key)); + break; + case 'N': + 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 += printtype(out, c->type, indent); + break; + case 'S': + n += printstring(out, c); + break; + case ADECLREF: + n += fprintf(out, "%s", getstring(idents, c->u.declref->key)); + break; + case ADECL: + assert(c->lhs); + n += printtype(out, c->lhs->type, indent); + assert(c->rhs); + assert(c->rhs->kind == 'I'); + n += fprintf(out, " %s", getstring(idents, c->rhs->u.key)); + if (c->u.payload) { + n += fprintf(out, " = "); + n += printoperant(out, c->u.payload, PASSIGN, false, indent); + } + break; + case ARETURN: + n += fprintf(out, "return "); + n += printexpr(out, c->lhs, indent); + break; + case ABREAK: + n += fprintf(out, "break"); + break; + case ACONTINUE: + n += fprintf(out, "continue"); + break; + case AIF: + 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 += fprintf(out, "else"); + n += printclause(out, c->rhs, indent); + } + break; + case ADO: + n += fprintf(out, "do"); + n += printclause(out, c->lhs, indent); + break; + case ASTMT: + n += printexpr(out, c->lhs, indent); + break; + case ASCOPE: + n += printexpr(out, c->lhs, indent); + break; + case ACONV: + n += fprintf(out, "conv("); + n += printtype(out, c->type, indent); + n += fprintf(out, ") "); + n += printoperant(out, c->lhs, PUNARY, false, indent); + break; + default: + break; + } + } + + if (c->kind == ASTMT && c->next) + n += fprintf(out, "\n"); + else if (c->next) + n += fprintf(out, ", "); + } + + return n; +} + /* - main-routine - */ int @@ -2262,8 +2571,15 @@ main(int argc, char **argv) { Node *ast; ast = exprlist(false, NULL); + /* printast(ast, 0); printf("\n"); + */ + if (ast->kind != ADECL || !ast->u.payload || ast->u.payload->kind != ASCOPE) + ast = foldexpr(ast); + printexpr(stdout, ast, 0); + printf("\n"); + if (tok.kind == '\n') { if (filein == stdin)