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 | ++ |
| M | aria.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");