Aria

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

commit 1fb33ec5cf61759e18ec0f3629fabbe6df8652d8
parent b1543447c96b23e112eee21abfaa132d942ad272
Author: m21c  <ho*******@gmail.com>
Date:   Sat, 10 Jul 2021 17:59:24 +0200

worked on function declaration + output highlighting

Diffstat:
M.gitignore | 2++
Maria.c | 848++++++++++++++++++++++++++++++++++---------------------------------------------
2 files changed, 363 insertions(+), 487 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -7,4 +7,6 @@ test/* debug*.cmd debug*.sh +*.txt + *.exe \ No newline at end of file diff --git a/aria.c b/aria.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <string.h> +/* utility function */ static int mystrncasecmp(const char *str1, const char *str2, size_t max_len) { @@ -72,7 +73,7 @@ struct Env Env; /* - type struct - */ typedef enum { - TERRTYPE = 1, TDUMMY, + TERRTYPE = 1, TUNDEFINED, TVOID, TBOOL, TINFER, TUINFER, @@ -127,30 +128,30 @@ struct Type { }; Type prim[] = { - [TERRTYPE] = {TERRTYPE, 0, 0, {0}, NULL}, - [TDUMMY] = {TDUMMY, 0, 0, {0}, NULL}, + [TERRTYPE] = {TERRTYPE, 0, 0, {0}, NULL}, + [TUNDEFINED] = {TUNDEFINED, 0, 0, {0}, NULL}, - [TVOID] = {TVOID, 0, 0, {0}, NULL}, + [TVOID] = {TVOID, 0, 0, {0}, NULL}, - [TBOOL] = {TBOOL, 1, 1, {0}, NULL}, + [TBOOL] = {TBOOL, 1, 1, {0}, NULL}, - [TINFER] = {TINFER, 4, 4, {0}, NULL}, - [TUINFER] = {TUINFER, 4, 4, {0}, NULL}, + [TINFER] = {TINFER, 4, 4, {0}, NULL}, + [TUINFER] = {TUINFER, 4, 4, {0}, NULL}, - [TS8] = {TS8, 1, 1, {0}, NULL}, - [TU8] = {TU8, 1, 1, {0}, NULL}, - [TS16] = {TS16, 2, 2, {0}, NULL}, - [TU16] = {TU16, 2, 2, {0}, NULL}, - [TS32] = {TS32, 4, 4, {0}, NULL}, - [TU32] = {TU32, 4, 4, {0}, NULL}, - [TS64] = {TS64, 8, 8, {0}, NULL}, - [TU64] = {TU64, 8, 8, {0}, NULL}, + [TS8] = {TS8, 1, 1, {0}, NULL}, + [TU8] = {TU8, 1, 1, {0}, NULL}, + [TS16] = {TS16, 2, 2, {0}, NULL}, + [TU16] = {TU16, 2, 2, {0}, NULL}, + [TS32] = {TS32, 4, 4, {0}, NULL}, + [TU32] = {TU32, 4, 4, {0}, NULL}, + [TS64] = {TS64, 8, 8, {0}, NULL}, + [TU64] = {TU64, 8, 8, {0}, NULL}, - [TF32] = {TF32, 4, 4, {0}, NULL}, - [TF64] = {TF64, 8, 8, {0}, NULL}, + [TF32] = {TF32, 4, 4, {0}, NULL}, + [TF64] = {TF64, 8, 8, {0}, NULL}, - [TPTR] = {TPTR, 8, 8, {0}, NULL}, - [TARRAY] = {TARRAY, 0, 0, {0}, NULL}, + [TPTR] = {TPTR, 8, 8, {0}, NULL}, + [TARRAY] = {TARRAY, 0, 0, {0}, NULL}, }; Type typebuf[4096]; @@ -493,6 +494,8 @@ const uint8_t opinfo[] = { #define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array))) +/* keyword map */ + #define KEYWORD_MAP_SIZE 128 const char *keywordkeys[KEYWORD_MAP_SIZE]; int keywordvals[KEYWORD_MAP_SIZE]; @@ -547,6 +550,8 @@ getkeyword(const char *str, int n) { return -1; } +/* string map */ + typedef struct StringEntry { int len; @@ -664,6 +669,8 @@ getstringkey(StringMap *map, const char *str, int n) { #define getstring(map, key) ((map).vals[(key) - 1].str) #define getlength(map, key) ((map).vals[(key) - 1].len) +/* node-structure & global vars for lexer and subsequent phases */ + struct Node { Kind kind; @@ -693,6 +700,8 @@ char stringbuf[1024]; int currcol, lastcol, lastindent, lastkind; Node tok; +/* error reporting */ + int warn(const char *fmt, ...) { va_list ap; @@ -723,6 +732,8 @@ error(const char *fmt, ...) { return n; } +/* actual lexer ( gettok() ) */ + #define nextindent(indent) \ ((indent) + tabwidth - ((indent) % tabwidth)) @@ -758,7 +769,7 @@ skipwhite: } } - tok.type = prim + TERRTYPE; + tok.type = prim + TUNDEFINED; tok.u.u = 0; tok.lhs = NULL; tok.rhs = NULL; @@ -957,7 +968,7 @@ skipwhite: break; /* TODO(m21c): read more escape sequences */ case 0: - goto stringeof; + goto stringeol; default: error("invalid escape sequence '\\%c'", c0); } @@ -969,9 +980,9 @@ skipwhite: line[j++] = 0; if (c0 == 0) { - stringeof: - error("unexpected end-of-file"); - return tok.kind = 0; + stringeol: + error("unexpected end-of-line"); + return tok.kind = '\n'; } /* TODO(m21c): read '\''-token as character-literal 'C' */ @@ -1082,8 +1093,9 @@ enum DeclKind { DMODULE = 0, DTYPE, /* NOTE(m21c): maybe be the same as void-module ? */ DVAR, - /* + DPARAM, DFUNCTION, + /* DMACRO, DENFOLD */ @@ -1094,8 +1106,8 @@ struct Decl { Type *type; - Env *env; - Node *declnode; + Env *env, *functionenv; + Node *content; /* init or function body */ int key; Decl *prev, *next; @@ -1104,6 +1116,7 @@ struct Decl { typedef enum EnvKind { STOPLEVEL = 0, + SPARAMLIST, SFUNCTION, SSCOPE, /* @@ -1167,6 +1180,7 @@ makedecl(int key, DeclKind kind) { decl->kind = kind; decl->key = key; decl->type = prim + TVOID; + decl->functionenv = NULL; assert(currenv); @@ -1298,149 +1312,6 @@ makenode(Node *lhs) { return node; } -int -printnode(FILE *out, Node *node) { - int n = 0, len, i; - const char *str; - - if (!node) - return fprintf(out, "<null>"); - - switch (node->kind) { - case ADECLREF: - return fprintf(out, "symbol-reference '%s'", getstring(idents, node->u.declref->key)); - case 'T': - return fprintf(out, "type"); - case 'I': - return fprintf(out, "identifier '%s'", getstring(idents, node->u.key)); - case 'N': - if (node->type->kind == TFLOAT || - node->type->kind == TDOUBLE || - node->type->kind == TLDOUBLE) - return fprintf(out, "%f", node->u.d); - else if (node->type->kind & (TUINT - TINT)) - return fprintf(out, "%li", node->u.s); - else - return fprintf(out, "%lu", node->u.u); - case 'S': - str = getstring(strings, node->u.key); - len = getlength(strings, node->u.key); - n += fprintf(out, "\""); - for (i = 0; i < len; ++i) { - switch (str[i]) { - case '\\': - n += printf("\\\\"); - break; - case '\n': - n += printf("\\n"); - break; - case '\r': - n += printf("\\r"); - break; - case '\t': - n += printf("\\t"); - break; - case '\"': - n += printf("\\\""); - break; - case '\'': - n += printf("\\\'"); - break; - case 0: - n += printf("\\0"); - break; - default: - putc(str[i], out); - ++n; - } - } - n += printf("\""); - return n; - default: - if (nodestrings[node->kind]) - return fprintf(out, "%s", nodestrings[node->kind]); - } - - return n; -} - -int -printast(Node *node, int indent) { - int n, i; - bool newline = false; - - assert(node); - - if (node->kind >= OSTART && node->kind != ADECLREF) - 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); - - if ((node->kind == AIF || node->kind == AWHILE || - node->kind == ALOOPUNTIL) && node->u.payload) - { - newline = true; - n += printf("\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printf("cond: "); - n += printast(node->u.payload, indent + 1); - } else if (node->kind == ADECL && node->u.payload) { - newline = true; - n += printf("\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printf("init: "); - n += printast(node->u.payload, indent + 1); - } - - if (node->lhs) { - newline = true; - n += printf("\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printf("lhs: "); - n += printast(node->lhs, indent + 1); - } - - if (node->rhs) { - newline = true; - n += printf("\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printf("rhs: "); - n += printast(node->rhs, indent + 1); - } - - if (newline) { - n += printf("\n"); - for (i = 0; i < indent; ++i) - n += printf(" "); - } - n += printf(")"); - - if (0 && node->prev) { - n += printf("prev:\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printast(node->prev, indent); - } - - if (node->next) { - n += printf("next:\n"); - for (i = 0; i <= indent; ++i) - n += printf(" "); - n += printast(node->next, indent); - } - - return n; -} - /* - parser - */ bool @@ -1529,9 +1400,9 @@ finish: Node * expr(int minprec); -Node * +Type * getbasetype(int flags) { - Node *result; + Type *result; if (tok.kind == 'I') { /* TODO(m21c): check/read type identifier */ @@ -1540,23 +1411,18 @@ getbasetype(int flags) { return NULL; } - result = makenode(NULL); - result->kind = 'T'; + result = tok.type; gettok(false); - return result; } -Node * -gettype(Node *basetype) { +Type * +gettype(Type *basetype) { int flags; - Type *ty; - assert(basetype); - assert(basetype->kind == 'T'); - - ty = basetype->type; + if (!basetype) + return NULL; advance: flags = qualifiers(QTYPE); @@ -1564,10 +1430,10 @@ advance: if (tok.kind == '[') { Type *tmp = maketype(); tmp->kind = TARRAY; - tmp->target = ty, ty = tmp; + tmp->target = basetype, basetype = tmp; gettok(false); if (tok.kind != ']') - ty->u.val = expr(PSTART); + basetype->u.val = expr(PSTART); expect(']', false, "expect ']'"); goto advance; } @@ -1575,35 +1441,52 @@ advance: if (tok.kind == OLPTR) { Type *tmp = maketype(); tmp->kind = TPTR; - tmp->target = ty, ty = tmp; + tmp->target = basetype, basetype = tmp; gettok(false); goto advance; } - basetype->type = ty; return basetype; } Node * -exprlist(bool isparam, Node *paramtype); +exprlist(bool isparam, Type *paramtype); Node * stmtlist(int indent, EnvKind kind); Node * -declaration(Node *typenode) { +declaration(Type *ty) { bool has_self_param = false; - Node *result = typenode; + Decl *decl = NULL; + Node *result = NULL; + + /* + EnvKind context; + */ + + if (!ty) + return NULL; + + /* TODO(m21c): use the currenv->kind as context, whether or how + * certain declarations (like function-declarations) + * are processed */ + + /* + context = currenv->kind; + */ if (tok.kind == 'I') { - Decl *decl = makedecl(tok.u.key, DVAR); - decl->type = typenode->type; - result = makenode(typenode); + decl = makedecl(tok.u.key, DVAR); + decl->type = ty; + + result = makenode(NULL); result->kind = ADECL; - result->rhs = makenode(NULL); + result->type = ty; + result->u.declref = decl; gettok(true); } else if (tok.kind == 'T') { - Node *module = gettype(getbasetype(0)); + Type *module = gettype(getbasetype(0)); if (tok.kind == ODISP || tok.kind == ':') { has_self_param = tok.kind == ':'; gettok(false); @@ -1611,40 +1494,101 @@ declaration(Node *typenode) { error("expected '.' or ':'"); } + /* TODO(m21c): obtain Decl* for + * Type Module:my_decl + * or Type Module.my_decl - declarations */ if (tok.kind == 'I') { + /* module = makenode(module); module->kind = ODISP; module->rhs = makenode(NULL); - result = makenode(typenode); + */ + + result = makenode(NULL); result->kind = ADECL; + /* result->rhs = module; + */ gettok(true); } else { error("expected identifier"); } } else { + result = makenode(NULL); + result->kind = 'T'; + result->type = ty; return result; } if (tok.kind == OCALL) { - Node *params; + Env *functionenv = NULL; + Node *params = NULL; + gettok(false); - params = exprlist(true, NULL); + if (tok.kind != ')') { + Decl *param; + + functionenv = pushenv(SPARAMLIST); + params = exprlist(true, NULL); + + for (param = functionenv->head; param; + param = param->next) + { + assert(param->kind == DVAR); + param->kind = DPARAM; + } + } expect(')', true, "expected ')'"); if (tok.kind != OASS) { Node *stmts; stmts = stmtlist(lastindent, SFUNCTION); - result->u.payload = stmts; + result->lhs = stmts; + } else if (tok.kind == OASS) { + Node *node; + + gettok(false); + + functionenv->kind = SFUNCTION; + node = expr(PSTART); + result->lhs = node; + } else { + result->lhs = NULL; } + + popenv(); + + assert(decl); + assert(decl->functionenv == NULL); + decl->functionenv = functionenv; + + assert(decl->content == NULL); + decl->content = result->lhs; + + assert(decl->kind == DVAR); + decl->kind = DFUNCTION; + + /* TODO(m21c): maybe add function-declaration to its type and + * add the paramlist to the type-info */ + + /* TODO(m21c): store the params-node (its initializations) + * somewhere */ + + return result; } if (tok.kind == OASS) { gettok(false); - result->u.payload = expr(PSTART); + result->lhs = expr(PSTART); + + assert(decl); + decl->content = result->lhs; } else { - result->u.payload = NULL; + result->lhs = NULL; + + assert(decl); + decl->content = NULL; } return result; @@ -1673,10 +1617,9 @@ stmtlist(int indent, EnvKind envkind) { Node *result = NULL, *lhs = NULL; int needindent = nextindent(indent); - Env *env; + Env *env = NULL; /* printf("needident: %d, currindent: %d, lastindent: %d\n", needindent, currindent, lastindent); */ - pushenv(envkind); for (;;) { Node *stmt; @@ -1704,6 +1647,19 @@ stmtlist(int indent, EnvKind envkind) { if (lhs && lastkind != '\n' && lastkind != ';') error("expected line delimiter"); + if (!env) { + /* NOTE(m21c): if there is already a + * paramlist-environment and we want a + * function-environment, we just use + * paramlist as our function-environment. + * Else, push a new environment */ + if (envkind != SFUNCTION || !currenv || + currenv->kind != SPARAMLIST) + { + env = pushenv(envkind); + } + } + stmt = exprlist(false, NULL); stmt = makenode(stmt); @@ -1717,12 +1673,20 @@ stmtlist(int indent, EnvKind envkind) { lhs = lhs->next; } } - env = popenv(); - result = makenode(result); - result->kind = ASCOPE; - result->u.env = env; - env->stmts = result; + /* NOTE(m21c): function: paramlist --> function, see NOTE above */ + if (envkind == SFUNCTION && currenv && currenv->kind == SPARAMLIST) { + assert(env == NULL); + currenv->kind = SFUNCTION; + env = currenv; + } else if (env) { + popenv(); + + result = makenode(result); + result->kind = ASCOPE; + result->u.env = env; + env->stmts = result; + } return result; } @@ -1732,6 +1696,7 @@ Node *lastis; Node * atom(int flags) { Node *lhs = NULL, *savedis = lastis; + Type *ty; int indent; /* int flags; */ @@ -1764,8 +1729,8 @@ atom(int flags) { return lhs; } - if ((lhs = getbasetype(0))) - return declaration(gettype(lhs)); + if ((lhs = declaration(gettype(getbasetype(0))))) + return lhs; if (flags & ~(QINFER | QCONST)) { error("invalid use of qualifiers"); @@ -2054,7 +2019,7 @@ todeclaration(Node *curr, Node **ty) { } Node * -exprlist(bool isparam, Node *paramtype) { +exprlist(bool isparam, Type *paramtype) { Node *head, *tail; bool isdeclaration, typetuple; @@ -2070,7 +2035,7 @@ exprlist(bool isparam, Node *paramtype) { error("expected declaration"); if ((isdeclaration = tail->kind == ADECL)) { - paramtype = tail->lhs; + paramtype = tail->type; } typetuple = tail->kind == 'T'; @@ -2093,7 +2058,7 @@ exprlist(bool isparam, Node *paramtype) { error("expected declaration"); if (curr->kind == ADECL) { - paramtype = tail->lhs; + paramtype = curr->type; isdeclaration = true; } @@ -2325,251 +2290,6 @@ conv(Node *node) { return autoref(NULL, node); } -#if 0 - -typedef -Node *(*RuleFunc)(Node *expr); - -Node * -foldexpr(Node *expr); - -Node * -identrule(Node *ident) { - Decl *declref = finddeclaration(ident->u.key); - - if (declref) { - ident->kind = ADECLREF; - ident->u.declref = declref; - ident->type = declref->type; - } else { - 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); - - /* usual arithmetic conversion */ - if (isarithtype(lhs->type) && isarithtype(rhs->type)) { - if (lhs->type->kind < rhs->type->kind) - tt = rhs->type; - else - tt = lhs->type; - } else { - error("expression is not of arithmentic type"); - binary->type = prim + TVOID; - return binary; - } - - lhs = wrap(tt, lhs); - rhs = wrap(tt, rhs); - binary->lhs = lhs; - binary->rhs = rhs; - binary->type = tt; - - #define evalbinary(op) do { \ - binary->kind = 'N'; \ - if (isfloattype(tt)) \ - binary->u.d = maskfloat(tt->size, \ - maskfloat(tt->size, lhs->u.d) op \ - maskfloat(tt->size, rhs->u.d) \ - ); \ - else if (isinttype(tt)) \ - binary->u.u = maskint(tt->size, \ - maskint(tt->size, lhs->u.u) op \ - maskint(tt->size, rhs->u.u) \ - ); \ - /* delete(lhs); delete(rhs) */ \ - } while (0) - - #define isvalue(expr, value) (expr->kind == 'N' && \ - ((expr->u.u == value && isinttype(tt)) || \ - (expr->u.d == value && isarithtype(tt)))) - - switch (binary->kind) { - case OADD: case OSUB: - if (lhs->kind == 'N' && rhs->kind == 'N') { - if (binary->kind == OADD) evalbinary(+); - else evalbinary(-); - } else if (isvalue(lhs, 0)) { - if (binary->kind == OADD) { - *binary = *rhs; - /* delete(lhs); delete(rhs) */ - } else { - binary->kind = OMINUS; - binary->lhs = rhs; - /* delete(lhs) */ - } - } else if (isvalue(rhs, 0)) { - *binary = *lhs; - /* delete(lhs); delete(rhs) */ - } - break; - case OMUL: case ODIV: case OMOD: - if (lhs->kind == 'N' && rhs->kind == 'N') { - if (binary->kind == OMUL) { - evalbinary(*); - } else { - if (rhs->u.u == 0 && isinttype(tt)) - error("division by zero"); - else if (binary->kind == ODIV) - evalbinary(/); - else - evalbinary(-); - } - } else if (isvalue(lhs, 0)) { - *binary = *lhs; - /* delete(lhs); delete(rhs) */ - } else if (binary->kind == OMUL && isvalue(rhs, 0)) { - *binary = *rhs; - /* delete(lhs); delete(rhs) */ - } else if (isvalue(rhs, 0)) { - if (rhs->u.u == 0 && isinttype(tt)) - error("division by zero"); - *binary = *rhs; - /* delete(lhs); delete(rhs) */ - } else if (isvalue(lhs, 1)) { - *binary = *rhs; - /* delete(lhs); delete(rhs) */ - } else if (binary->kind == OMUL && isvalue(rhs, 1)) { - *binary = *lhs; - /* delete(lhs); delete(rhs) */ - } - } - #undef evalbinary - #undef isvalue - - return binary; -} - -Node * -unaryarithrule(Node *unary) { - Node *lhs = unary->lhs; - Type *tt; - - if (!lhs) return unary; - - lhs = foldexpr(lhs); - - /* usual arithmetic conversion */ - if (!isarithtype(lhs->type)) { - error("expression is not of arithmentic type"); - unary->type = prim + TVOID; - return unary; - } - - lhs = conv(lhs); - unary->lhs = lhs; - unary->type = tt = lhs->type; - - switch (unary->kind) { - case OPLUS: - *unary = *lhs; - /* delete(lhs) */ - break; - case OMINUS: - if (lhs->kind == 'N') { - if (isfloattype(tt)) { - unary->kind = 'N'; - unary->u.d = maskfloat(tt->size, -lhs->u.d); - /* delete(lhs) */ - } else if (isinttype(tt)) { - unary->kind = 'N'; - unary->u.u = maskint(tt->size, -lhs->u.u); - /* delete(lhs) */ - } - } else if (lhs->kind == OMINUS && lhs->lhs) { - *unary = *lhs->lhs; - /* delete(lhs) */ - } - break; - default:; - } - - return unary; -} - -Node * -unarybitwiserule(Node *unary) { - Node *lhs = unary->lhs; - Type *tt; - - if (!lhs) return unary; - - lhs = foldexpr(lhs); - - /* usual arithmetic conversion */ - if (!isarithtype(lhs->type)) { - error("expression is not of arithmentic type"); - unary->type = prim + TVOID; - return unary; - } - - lhs = conv(lhs); - unary->lhs = lhs; - unary->type = tt = lhs->type; - - switch (unary->kind) { - case OPLUS: - *unary = *lhs; - /* delete(lhs) */ - break; - case OMINUS: - if (lhs->kind == 'N') { - if (isfloattype(tt)) { - unary->kind = 'N'; - unary->u.d = maskfloat(tt->size, -lhs->u.d); - /* delete(lhs) */ - } else if (isinttype(tt)) { - unary->kind = 'N'; - unary->u.u = maskint(tt->size, -lhs->u.u); - /* delete(lhs) */ - } - } else if (lhs->kind == OMINUS && lhs->lhs) { - *unary = *lhs->lhs; - /* delete(lhs) */ - } - break; - default:; - } - - return unary; -} - -RuleFunc ruletable[] = { - ['I'] = &identrule, - - /* TODO(m21c): on inc/dec operations: check for lvalue */ - [OSUFINC] = &unaryarithrule, - [OSUFDEC] = &unaryarithrule, - [OINC] = &unaryarithrule, - [ODEC] = &unaryarithrule, - - [OPLUS] = &unaryarithrule, - [OMINUS] = &unaryarithrule, - - [OMUL] = &binaryarithrule, - [ODIV] = &binaryarithrule, - [OMOD] = &binaryarithrule, - [OADD] = &binaryarithrule, - [OSUB] = &binaryarithrule, - - [MAXKINDS] = NULL -}; - -#endif - Node * typecheck(Node *expr) { Node *c; @@ -2772,13 +2492,8 @@ typecheck(Node *expr) { break; case ADECL: - assert(rhs); - assert(lhs); - - c->type = lhs->type; - - if (c->u.payload) - c->u.payload = wrap(c->type, typecheck(c->u.payload)); + if (c->lhs) + c->lhs = wrap(c->type, typecheck(c->lhs)); break; case ASCOPE: @@ -2833,6 +2548,8 @@ foldexpr(Node *expr) { 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(c->kind)) { case 2: rhs = foldexpr(rhs); @@ -2940,12 +2657,89 @@ foldexpr(Node *expr) { c->u.u = maskint(ty->size, c->u.u); } break; + case ACONV: + /* TODO(m21c): implement this properly! */ + lhs = foldexpr(lhs); + if (lhs->type->kind == c->type->kind) + *c = *lhs /*, delete(lhs) */; } } return expr; } -/* - print ast */ +/* - print ast - */ + +typedef enum Highlight { + HLNONE = 0, + HLDELIM = 1, + HLUNKNOWN = 2, + HLKEYWORD = 3, + HLNUMBER = 4, + HLSTRING = 5, + HLTYPE = 6, + HLFUNCTION = 7, + HLPARAM = 8, + HLINFO = 9 +} Highlight; + +#define HLOP HLDELIM +#define HLCHAR HLSTRING +#define HLIDENT HLNONE + +Highlight lasthighlight; + +int +highlight(FILE *out, Highlight kind) { + int n = 0; + + if (out != stdout) + return 0; + + if (lasthighlight == kind) + return 0; + + if (kind == HLNONE) + return lasthighlight = kind, fprintf(out, "\e[0m"); + + if (lasthighlight == HLDELIM || kind == HLDELIM || + lasthighlight == HLFUNCTION || kind == HLFUNCTION || + lasthighlight == HLPARAM || kind == HLPARAM || + lasthighlight == HLUNKNOWN || kind == HLUNKNOWN) + n += fprintf(out, "\e[0m"); + + switch (kind) { + case HLDELIM: + n += fprintf(out, "\e[2m"); + break; + case HLUNKNOWN: + n += fprintf(out, "\e[41;30m"); + break; + case HLKEYWORD: + n += fprintf(out, "\e[35m"); + break; + case HLNUMBER: + n += fprintf(out, "\e[36m"); + break; + case HLSTRING: + n += fprintf(out, "\e[31m"); + break; + case HLTYPE: + n += fprintf(out, "\e[34m"); + break; + case HLFUNCTION: + n += fprintf(out, "\e[1;3m"); + break; + case HLPARAM: + n += fprintf(out, "\e[3m"); + break; + case HLINFO: + n += fprintf(out, "\e[33m"); + break; + } + + lasthighlight = kind; + return n; +} int printexpr(FILE *out, Node *expr, int indent); @@ -2966,16 +2760,16 @@ int printtype(FILE *out, Type *type, int indent) { break; #define typecase(type, str) \ case type: n += fprintf(out, str); break - typecase(TERRTYPE, "<error-type>"); - typecase(TDUMMY, "<not-implemented>"); - typecase(TPTR, "*"); - typecase(TVOID, "void" ); typecase(TBOOL, "bool" ); - typecase(TINFER, "i" ); typecase(TUINFER, "u" ); - typecase(TS8, "s8" ); typecase(TU8, "u8" ); - typecase(TS16, "s16" ); typecase(TU16, "u16" ); - typecase(TS32, "s32" ); typecase(TU32, "u32" ); - typecase(TS64, "s64" ); typecase(TU64, "u64" ); - typecase(TF32, "f32" ); typecase(TF64, "f64" ); + typecase(TERRTYPE, "<error-type>"); + typecase(TUNDEFINED, "<undefined-type>"); + typecase(TPTR, "*"); + typecase(TVOID, "void" ); typecase(TBOOL, "bool" ); + typecase(TINFER, "i" ); typecase(TUINFER, "u" ); + typecase(TS8, "s8" ); typecase(TU8, "u8" ); + typecase(TS16, "s16" ); typecase(TU16, "u16" ); + typecase(TS32, "s32" ); typecase(TU32, "u32" ); + typecase(TS64, "s64" ); typecase(TU64, "u64" ); + typecase(TF32, "f32" ); typecase(TF64, "f64" ); #undef typecase default:; } @@ -3066,9 +2860,13 @@ printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent) ) ) ) { + n += highlight(out, HLDELIM); n += fprintf(out, "("); + n += highlight(out, HLNONE); n += printexpr(out, expr, indent); + n += highlight(out, HLDELIM); n += fprintf(out, ")"); + n += highlight(out, HLNONE); } else { n += printexpr(out, expr, indent); } @@ -3077,6 +2875,57 @@ printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent) } int +printdeclaration(FILE *out, Decl *decl, int indent) { + int n = 0; + + assert(decl); + + n += highlight(out, HLTYPE); + n += printtype(out, decl->type, indent); + + n += highlight(out, + decl->kind == DFUNCTION ? HLFUNCTION : + decl->kind == DPARAM ? HLPARAM : + HLIDENT); + n += fprintf(out, " %s", getstring(idents, decl->key)); + + if (decl->kind == DFUNCTION) { + Decl *param, *head = NULL; + + n += highlight(out, HLDELIM); + n += fprintf(out, "("); + + if (decl->functionenv) { + head = decl->functionenv->head; + } + + for (param = head; param; param = param->next) { + if (param->kind != DPARAM) + break; + + if (param != head) { + n += highlight(out, HLDELIM); + n += fprintf(out, ", "); + } + + n += printdeclaration(out, param, indent + 1); + } + + n += highlight(out, HLDELIM); + n += fprintf(out, ")"); + + if (decl->content) { + n += fprintf(out, "\n"); + n += printexpr(out, decl->content, indent + 1); + } + } else if (decl->content) { + n += highlight(out, HLDELIM); + n += fprintf(out, " = "); + n += printoperant(out, decl->content, PASSIGN, false, indent); + } +} + +int printexpr(FILE *out, Node *expr, int indent) { Node *c; int n = 0; @@ -3091,6 +2940,7 @@ printexpr(FILE *out, Node *expr, int indent) { 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) { @@ -3099,11 +2949,14 @@ printexpr(FILE *out, Node *expr, int 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; @@ -3113,8 +2966,11 @@ printexpr(FILE *out, Node *expr, int indent) { } 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; default: @@ -3131,9 +2987,12 @@ printexpr(FILE *out, Node *expr, int indent) { 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) @@ -3145,33 +3004,34 @@ printexpr(FILE *out, Node *expr, int indent) { n += printtype(out, c->type, indent); break; case 'S': + n += highlight(out, HLSTRING); n += printstring(out, c); 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 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); - } + n += printdeclaration(out, c->u.declref, indent); break; case ARETURN: + n += highlight(out, HLKEYWORD); n += fprintf(out, "return "); - n += printexpr(out, c->lhs, indent); + n += printexpr(out, c->rhs, indent); break; case ABREAK: + n += highlight(out, HLKEYWORD); n += fprintf(out, "break"); break; case ACONTINUE: + n += highlight(out, HLKEYWORD); n += fprintf(out, "continue"); break; case AIF: + n += highlight(out, HLKEYWORD); n += fprintf(out, "if "); n += printexpr(out, c->u.payload, indent); n += printclause(out, c->lhs, indent); @@ -3181,11 +3041,13 @@ printexpr(FILE *out, Node *expr, int indent) { 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); } break; case ADO: + n += highlight(out, HLKEYWORD); n += fprintf(out, "do"); n += printclause(out, c->lhs, indent); break; @@ -3196,19 +3058,26 @@ printexpr(FILE *out, Node *expr, int indent) { n += printexpr(out, c->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 AADDR: + n += highlight(out, HLDELIM); n += fputs("&{", out); n += printoperant(out, c->lhs, PUNARY, false, indent); + n += highlight(out, HLDELIM); n += fputs("}", out); break; 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; default: @@ -3216,10 +3085,12 @@ printexpr(FILE *out, Node *expr, int indent) { } } - if (c->kind == ASTMT && c->next) + if (c->kind == ASTMT && c->next) { n += fprintf(out, "\n"); - else if (c->next) + } else if (c->next) { + n += highlight(out, HLDELIM); n += fprintf(out, ", "); + } } return n; @@ -3263,9 +3134,12 @@ main(int argc, char **argv) { if (ast->kind != ADECL || !ast->u.payload || ast->u.payload->kind != ASCOPE) ast = foldexpr(typecheck(ast)); printexpr(stdout, ast, 0); + highlight(stdout, HLNONE); if (filein == stdin) { + highlight(stdout, HLINFO); fputs(" : ", stdout); printtype(stdout, ast->type, 0); + highlight(stdout, HLNONE); } printf("\n");