Aria

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

commit 503dcb4b282301c142050c5bbcfe955d29fe8bcf
parent 18f42c96e78f5b8ee31e00d09f244892bf4bb009
Author: m21c <ho*******@gmail.com>
Date:   Thu,  1 Apr 2021 20:44:28 +0200

changed node kind - layout + improved .gitignore

Diffstat:
M.gitignore | 3+++
Maria.c | 824++++++++++++++++++++++++++++++++++++++++---------------------------------------
2 files changed, 418 insertions(+), 409 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -5,3 +5,5 @@ test/* debug*.cmd debug*.sh + +*.exe +\ No newline at end of file diff --git a/aria.c b/aria.c @@ -211,43 +211,6 @@ advance: /* - lexer - */ -enum { - OSUFINC, OSUFDEC, OARRAY, OCALL, ODISP, - - ODEREF, OINC, ODEC, OBNOT, OLNOT, OFLIP, OADDR, OPLUS, OMINUS, - OCAST, - - OMUL, ODIV, OMOD, OLSH, OARSH, ORSH, OBAND, - - OADD, OSUB, OBOR, OXOR, - - ORANGE, - - OLEQ, OLET, OGEQ, OGRT, ONEQ, OEQU, OIDENT, - - OLAND, - - OLOR, - - OASS, - OMULA, ODIVA, OMODA, OLSHA, OARSHA, ORSHA, OANDA, - OADDA, OSUBA, OORA, OXORA, -}; - -enum { - PUNSUF = 9, - PUNARY = 8, - PMUL = 7, - PADD = 6, - PRANGE = 5, - PRELAT = 4, - PAND = 3, - POR = 2, - PASSIGN = 1, - - PSTART = 0 -}; - typedef struct Op { const char *debugstr; @@ -258,67 +221,6 @@ struct Op { bool rassoc; } Op; -const Op ops[] = { - [OSUFINC] = {"unary++", "++", 1, PUNSUF, false}, - [OSUFDEC] = {"unary--", "++", 1, PUNSUF, false}, - [OARRAY] = {"unary[]", "", 1, PUNSUF, false}, - [OCALL] = {"unary()", "", 1, PUNSUF, false}, - [ODISP] = {"unary._", ".", 1, PUNSUF, false}, - - [ODEREF] = {"*unary", "*", 1, PUNARY, true}, - [OINC] = {"++unary", "++", 1, PUNARY, true}, - [ODEC] = {"--unary", "--", 1, PUNARY, true}, - [OBNOT] = {"~unary", "~", 1, PUNARY, true}, - [OLNOT] = {"!unary", "!", 1, PUNARY, true}, - [OFLIP] = {"~=unary", "~=", 1, PUNARY, true}, - [OADDR] = {"&unary", "&", 1, PUNARY, true}, - [OPLUS] = {"+unary", "+", 1, PUNARY, true}, - [OMINUS] = {"-unary", "-", 1, PUNARY, true}, - [OCAST] = {"(type) unary", "", 1, PUNARY, true}, - - [OMUL] = {"*", "*", 2, PMUL, false}, - [ODIV] = {"/", "/", 2, PMUL, false}, - [OMOD] = {"%", "%", 2, PMUL, false}, - [OLSH] = {"<<", "<<", 2, PMUL, false}, - [OARSH] = {">>>", ">>>", 2, PMUL, false}, - [ORSH] = {">>", ">>", 2, PMUL, false}, - [OBAND] = {"&", "&", 2, PMUL, false}, - - [OADD] = {"+", "+", 2, PADD, false}, - [OSUB] = {"-", "-", 2, PADD, false}, - [OBOR] = {"|", "|", 2, PADD, false}, - [OXOR] = {"^", "^", 2, PADD, false}, - - [ORANGE] = {"..", "..", 2, PRANGE, false}, - - [OLEQ] = {"<=", "<=", 2, PRELAT, false}, - [OLET] = {"<", "<", 2, PRELAT, false}, - [OGEQ] = {">=", ">=", 2, PRELAT, false}, - [OGRT] = {">", ">", 2, PRELAT, false}, - [ONEQ] = {"!=", "!=", 2, PRELAT, false}, - [OEQU] = {"==", "==", 2, PRELAT, false}, - [OIDENT] = {"===", "===", 2, PRELAT, false}, - - [OLAND] = {"&&", "&&", 2, PAND, false}, - - [OLOR] = {"||", "||", 2, POR, false}, - - [OASS] = {"=", "=", 2, PASSIGN, true}, - [OMULA] = {"*=", "*=", 2, PASSIGN, true}, - [ODIVA] = {"/=", "/=", 2, PASSIGN, true}, - [OMODA] = {"%=", "%=", 2, PASSIGN, true}, - [OLSHA] = {"<<=", "<<=", 2, PASSIGN, true}, - [OARSHA] = {">>>=", ">>>=", 2, PASSIGN, true}, - [ORSHA] = {">>=", ">>=", 2, PASSIGN, true}, - [OANDA] = {"&=", "&=", 2, PASSIGN, true}, - [OADDA] = {"+=", "+=", 2, PASSIGN, true}, - [OSUBA] = {"-=", "-=", 2, PASSIGN, true}, - [OORA] = {"|=", "|=", 2, PASSIGN, true}, - [OXORA] = {"^=", "^=", 2, PASSIGN, true} -}; - -#define lengthof(array) ((int) sizeof(array) / (int) sizeof (*(array))) - typedef struct Keyword { const char *str; @@ -332,7 +234,33 @@ struct Keyword { } Keyword; enum { - KVOID, KBOOL, + PUNSUF = 10, + PUNARY = 9, + PMUL = 8, + PADD = 7, + PRANGE = 6, + PRELAT = 5, + PAND = 4, + POR = 3, + PASSIGN = 2, + + PSTART = 1 +}; + +#define KSTART 0x100 +#define OSTART 0x200 +#define ASTART 0x300 + +typedef enum Kind { + ANNOT = '@', + SEMIDELIM = ';', COMMADELIM = ',', COLONDELIM = ':', LCURLDELIM = '{', + RCURLDELIM = ']', RSQRDELIM = ']', RPARDELIM = ')', + IDENT = 'I', + NUMBER = 'N', + STRING = 'S', + + KVOID = KSTART, + KBOOL, KU8, KS8, KU16, KS16, KU32, KS32, KU64, KS64, @@ -354,7 +282,196 @@ enum { KBREAK, KCONTINUE, KGOTO, KRETURN, KIF, KELSE, KCASE, KOF, KDO, - KFOR, KLOOP, KWHILE, KUNTIL + KFOR, KLOOP, KWHILE, KUNTIL, + + OSUFINC = OSTART, + OSUFDEC, OARRAY, OCALL, ODISP, + + ODEREF, OINC, ODEC, OBNOT, OLNOT, OFLIP, OADDR, OPLUS, OMINUS, + OCAST, + + OMUL, ODIV, OMOD, OLSH, OARSH, ORSH, OBAND, + + OADD, OSUB, OBOR, OXOR, + + ORANGE, + + OLEQ, OLET, OGEQ, OGRT, ONEQ, OEQU, OIDENT, + + OLAND, + + OLOR, + + OASS, + OMULA, ODIVA, OMODA, OLSHA, OARSHA, ORSHA, OANDA, + OADDA, OSUBA, OORA, OXORA, + + ASTMT = ASTART, + ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE, + ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, + + MAXKINDS +} Kind; + +const char *astnames[] = { + "Statement", + "Do", + "Declaration", + "Declaration Reference", + "Loop", + "Loop-Until", + "While", + "For", + "Continue", + "Break", + "Scope", + "Return", + "Goto", + "Label", + "If", + "Switch", + "Case" +}; + +/* +Node kinds: + '@' - Annotation + ';' ',' ':' '{' '}' ']' ')' - Delimiters + 'A' - Statement + 'I' - Identifier + 'K' - Keyword + 'N' - Number-literal + 'O' - Operator + 'S' - String-literal +*/ + +#define opentry(numops, rassoc, prec) \ + ((uint8_t) ( ((numops) << 6) | ((rassoc) << 5) | (prec) )) + +const uint8_t opinfo[] = { + [0] = 0, + + [OSUFINC] = opentry(1, false, PUNSUF), + [OSUFDEC] = opentry(1, false, PUNSUF), + [OARRAY] = opentry(1, false, PUNSUF), + [OCALL] = opentry(1, false, PUNSUF), + [ODISP] = opentry(1, false, PUNSUF), + + [ODEREF] = opentry(1, true, PUNARY), + [OINC] = opentry(1, true, PUNARY), + [ODEC] = opentry(1, true, PUNARY), + [OBNOT] = opentry(1, true, PUNARY), + [OLNOT] = opentry(1, true, PUNARY), + [OFLIP] = opentry(1, true, PUNARY), + [OADDR] = opentry(1, true, PUNARY), + [OPLUS] = opentry(1, true, PUNARY), + [OMINUS] = opentry(1, true, PUNARY), + [OCAST] = opentry(1, true, PUNARY), + + [OMUL] = opentry(2, false, PMUL), + [ODIV] = opentry(2, false, PMUL), + [OMOD] = opentry(2, false, PMUL), + [OLSH] = opentry(2, false, PMUL), + [OARSH] = opentry(2, false, PMUL), + [ORSH] = opentry(2, false, PMUL), + [OBAND] = opentry(2, false, PMUL), + + [OADD] = opentry(2, false, PADD), + [OSUB] = opentry(2, false, PADD), + [OBOR] = opentry(2, false, PADD), + [OXOR] = opentry(2, false, PADD), + + [ORANGE] = opentry(2, false, PRANGE), + + [OLEQ] = opentry(2, false, PRELAT), + [OLET] = opentry(2, false, PRELAT), + [OGEQ] = opentry(2, false, PRELAT), + [OGRT] = opentry(2, false, PRELAT), + [ONEQ] = opentry(2, false, PRELAT), + [OEQU] = opentry(2, false, PRELAT), + [OIDENT] = opentry(2, false, PRELAT), + + [OLAND] = opentry(2, false, PAND), + + [OLOR] = opentry(2, false, POR), + + [OASS] = opentry(2, true, PASSIGN), + [OMULA] = opentry(2, true, PASSIGN), + [ODIVA] = opentry(2, true, PASSIGN), + [OMODA] = opentry(2, true, PASSIGN), + [OLSHA] = opentry(2, true, PASSIGN), + [OARSHA] = opentry(2, true, PASSIGN), + [ORSHA] = opentry(2, true, PASSIGN), + [OANDA] = opentry(2, true, PASSIGN), + [OADDA] = opentry(2, true, PASSIGN), + [OSUBA] = opentry(2, true, PASSIGN), + [OORA] = opentry(2, true, PASSIGN), + [OXORA] = opentry(2, true, PASSIGN), + + [MAXKINDS] = 0 +}; + +#define getnumops(kind) (opinfo[kind] >> 6) +#define israssoc(kind) ((opinfo[kind] >> 5) & 0x01) +#define getprec(kind) ((opinfo[kind] & 0x2f)) + +const Op ops[] = { + [OSUFINC - OSTART] = {"unary++", "++", 1, PUNSUF, false}, + [OSUFDEC - OSTART] = {"unary--", "++", 1, PUNSUF, false}, + [OARRAY - OSTART] = {"unary[]", "", 1, PUNSUF, false}, + [OCALL - OSTART] = {"unary()", "", 1, PUNSUF, false}, + [ODISP - OSTART] = {"unary._", ".", 1, PUNSUF, false}, + + [ODEREF - OSTART] = {"*unary", "*", 1, PUNARY, true}, + [OINC - OSTART] = {"++unary", "++", 1, PUNARY, true}, + [ODEC - OSTART] = {"--unary", "--", 1, PUNARY, true}, + [OBNOT - OSTART] = {"~unary", "~", 1, PUNARY, true}, + [OLNOT - OSTART] = {"!unary", "!", 1, PUNARY, true}, + [OFLIP - OSTART] = {"~=unary", "~=", 1, PUNARY, true}, + [OADDR - OSTART] = {"&unary", "&", 1, PUNARY, true}, + [OPLUS - OSTART] = {"+unary", "+", 1, PUNARY, true}, + [OMINUS - OSTART] = {"-unary", "-", 1, PUNARY, true}, + [OCAST - OSTART] = {"(type) unary", "", 1, PUNARY, true}, + + [OMUL - OSTART] = {"*", "*", 2, PMUL, false}, + [ODIV - OSTART] = {"/", "/", 2, PMUL, false}, + [OMOD - OSTART] = {"%", "%", 2, PMUL, false}, + [OLSH - OSTART] = {"<<", "<<", 2, PMUL, false}, + [OARSH - OSTART] = {">>>", ">>>", 2, PMUL, false}, + [ORSH - OSTART] = {">>", ">>", 2, PMUL, false}, + [OBAND - OSTART] = {"&", "&", 2, PMUL, false}, + + [OADD - OSTART] = {"+", "+", 2, PADD, false}, + [OSUB - OSTART] = {"-", "-", 2, PADD, false}, + [OBOR - OSTART] = {"|", "|", 2, PADD, false}, + [OXOR - OSTART] = {"^", "^", 2, PADD, false}, + + [ORANGE - OSTART] = {"..", "..", 2, PRANGE, false}, + + [OLEQ - OSTART] = {"<=", "<=", 2, PRELAT, false}, + [OLET - OSTART] = {"<", "<", 2, PRELAT, false}, + [OGEQ - OSTART] = {">=", ">=", 2, PRELAT, false}, + [OGRT - OSTART] = {">", ">", 2, PRELAT, false}, + [ONEQ - OSTART] = {"!=", "!=", 2, PRELAT, false}, + [OEQU - OSTART] = {"==", "==", 2, PRELAT, false}, + [OIDENT - OSTART] = {"===", "===", 2, PRELAT, false}, + + [OLAND - OSTART] = {"&&", "&&", 2, PAND, false}, + + [OLOR - OSTART] = {"||", "||", 2, POR, false}, + + [OASS - OSTART] = {"=", "=", 2, PASSIGN, true}, + [OMULA - OSTART] = {"*=", "*=", 2, PASSIGN, true}, + [ODIVA - OSTART] = {"/=", "/=", 2, PASSIGN, true}, + [OMODA - OSTART] = {"%=", "%=", 2, PASSIGN, true}, + [OLSHA - OSTART] = {"<<=", "<<=", 2, PASSIGN, true}, + [OARSHA - OSTART] = {">>>=", ">>>=", 2, PASSIGN, true}, + [ORSHA - OSTART] = {">>=", ">>=", 2, PASSIGN, true}, + [OANDA - OSTART] = {"&=", "&=", 2, PASSIGN, true}, + [OADDA - OSTART] = {"+=", "+=", 2, PASSIGN, true}, + [OSUBA - OSTART] = {"-=", "-=", 2, PASSIGN, true}, + [OORA - OSTART] = {"|=", "|=", 2, PASSIGN, true}, + [OXORA - OSTART] = {"^=", "^=", 2, PASSIGN, true} }; Keyword keywords[] = { @@ -416,6 +533,8 @@ Keyword keywords[] = { {"until", 0, false, 0, false, 0}, }; +#define lengthof(array) ((int) sizeof(array) / (int) sizeof (*(array))) + #define KEYWORD_MAP_SIZE 128 const char *keywordkeys[KEYWORD_MAP_SIZE]; int keywordvals[KEYWORD_MAP_SIZE]; @@ -587,88 +706,21 @@ 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) -enum { - ASTMT, - ADO, - ADECL, - ADECLREF, - ALOOP, - ALOOPUNTIL, - AWHILE, - AFOR, - ACONTINUE, - ABREAK, - ASCOPE, - ARETURN, - AGOTO, - ALABEL, - AIF, - ASWITCH, - ACASE -}; - -const char *astnames[] = { - "Statement", - "Do", - "Declaration", - "Declaration Reference", - "Loop", - "Loop-Until", - "While", - "For", - "Continue", - "Break", - "Scope", - "Return", - "Goto", - "Label", - "If", - "Switch", - "Case" -}; - -/* -Node kinds: - '@' - Annotation - ';' ',' ':' '{' '}' ']' ')' - Delimiters - 'A' - Statement - 'I' - Identifier - 'K' - Keyword - 'N' - Number-literal - 'O' - Operator - 'S' - String-literal -*/ struct Node { - char kind; + Kind kind; Type *type; union { - int id; + int key; double d; uint64_t u; int64_t s; - struct { - int id; - Node *cond; - } cond; - - struct { - int id; - Node *init; - } decl; - - struct { - int id; - Decl *ref; - } declref; - - struct { - int id; - Env *env; - } scope; + Node *payload; + Decl *declref; + Env *env; } u; Node *lhs, *rhs; @@ -776,21 +828,20 @@ skipwhite: c0 = line[++currcol]; keyword = getkeyword(line + lastcol, currcol - lastcol); - if (tok.kind != '@' && keyword >= 0 && - (tok.kind != 'O' || tok.u.id != ODISP)) { + if (tok.kind != '@' && keyword >= 0 && tok.kind != ODISP) { if (keywords[keyword].isop) { - tok.u.id = keywords[keyword].opid; - return tok.kind = 'O'; + return tok.kind = keywords[keyword].opid; } else if (keywords[keyword].istype) { + /* tok.u.id = keywords[keyword].typeid; tok.type = prim + tok.u.id; + */ return tok.kind = 'T'; } - tok.u.id = keyword; - return tok.kind = 'K'; + return tok.kind = keyword + KSTART; } - tok.u.id = getstringkey(&idents, + tok.u.key = getstringkey(&idents, line + lastcol, currcol - lastcol); return tok.kind = 'I'; } @@ -969,7 +1020,7 @@ skipwhite: /* TODO(m21c): read '\''-token as character-literal 'C' */ - tok.u.id = getstringkey(&strings, line + lastcol, j - lastcol); + tok.u.key = getstringkey(&strings, line + lastcol, j - lastcol); return tok.kind = 'S'; } @@ -986,11 +1037,11 @@ skipwhite: goto joindelim; case '[': if (haslhs) - c0 = 'O', tok.u.id = OARRAY; + c0 = OARRAY; goto joindelim; case '(': if (haslhs) - c0 = 'O', tok.u.id = OCALL; + c0 = OCALL; joindelim: ++currcol; return tok.kind = c0; @@ -1001,26 +1052,26 @@ skipwhite: (line[currcol] == (ch) ? ++currcol, (then) : (otherwise)) switch (line[currcol++]) { case '.': - /* tok.u.id = select('.', ORANGE, ODISP); */ - tok.u.id = ODISP; + /* tok.kind = select('.', ORANGE, ODISP); */ + tok.kind = ODISP; goto joinop; case '*': - tok.u.id = select('=', OMULA, (haslhs ? OMUL : ODEREF)); + tok.kind = select('=', OMULA, (haslhs ? OMUL : ODEREF)); goto joinop; case '/': - tok.u.id = select('=', ODIVA, ODIV); + tok.kind = select('=', ODIVA, ODIV); goto joinop; case '%': - tok.u.id = select('=', OMODA, OMOD); + tok.kind = select('=', OMODA, OMOD); goto joinop; case '<': - tok.u.id = select('=', OLEQ, + tok.kind = select('=', OLEQ, select('<', select('=', OLSHA, OLSH), OLET)); goto joinop; case '>': - tok.u.id = select('=', OGEQ, + tok.kind = select('=', OGEQ, select('>', select('>', select('=', OARSHA, OARSH), @@ -1028,35 +1079,35 @@ skipwhite: OGRT)); goto joinop; case '&': - tok.u.id = select('=', OANDA, select('&', OLAND, + tok.kind = select('=', OANDA, select('&', OLAND, (haslhs ? OBAND : OADDR))); goto joinop; case '+': - tok.u.id = select('=', OADDA, select('+', + tok.kind = select('=', OADDA, select('+', (haslhs ? OSUFINC : OINC), (haslhs ? OADD : OPLUS))); goto joinop; case '-': - tok.u.id = select('=', OSUBA, select('-', + tok.kind = select('=', OSUBA, select('-', (haslhs ? OSUFDEC : ODEC), (haslhs ? OSUB : OMINUS))); goto joinop; case '|': - tok.u.id = select('=', OORA, select('|', OLOR, OBOR)); + tok.kind = select('=', OORA, select('|', OLOR, OBOR)); goto joinop; case '^': - tok.u.id = select('=', OXORA, OXOR); + tok.kind = select('=', OXORA, OXOR); goto joinop; case '!': - tok.u.id = select('=', ONEQ, OLNOT); + tok.kind = select('=', ONEQ, OLNOT); goto joinop; case '~': - tok.u.id = select('=', OFLIP, OBNOT); + tok.kind = select('=', OFLIP, OBNOT); goto joinop; case '=': - tok.u.id = select('=', select('=', OIDENT, OEQU), OASS); + tok.kind = select('=', select('=', OIDENT, OEQU), OASS); joinop: - return tok.kind = 'O'; + return tok.kind; default: error("invalid input character '%c'", c0); @@ -1288,11 +1339,7 @@ printnode(FILE *out, Node *node) { case 'T': return fprintf(out, "Type"); case 'I': - return fprintf(out, "%s", getstring(idents, node->u.id)); - case 'O': - return fprintf(out, "%s", ops[node->u.id].str); - case 'K': - return fprintf(out, "%s", keywords[node->u.id].str); + return fprintf(out, "%s", getstring(idents, node->u.key)); case 'N': if (node->type->kind == TFLOAT || node->type->kind == TDOUBLE || @@ -1303,8 +1350,8 @@ printnode(FILE *out, Node *node) { else return fprintf(out, "%lu", node->u.u); case 'S': - str = getstring(strings, node->u.id); - len = getlength(strings, node->u.id); + str = getstring(strings, node->u.key); + len = getlength(strings, node->u.key); n += fprintf(out, "\""); for (i = 0; i < len; ++i) { switch (str[i]) { @@ -1335,6 +1382,12 @@ printnode(FILE *out, Node *node) { } } n += printf("\""); + return n; + default: + if (node->kind >= KSTART && node->kind < OSTART) + return fprintf(out, "%s", keywords[node->kind - KSTART].str); + if (node->kind >= OSTART && node->kind < ASTART) + return fprintf(out, "%s", ops[node->kind - OSTART].str); } return n; @@ -1347,32 +1400,29 @@ printast(Node *node, int indent) { assert(node); - if (node->kind == 'O') - n += printf("%s(", ops[node->u.id].debugstr); - else if (node->kind == 'A') - n += printf("%s(", astnames[node->u.id]); + if (node->kind >= OSTART && node->kind < ASTART) + n += printf("%s(", ops[node->kind - OSTART].debugstr); + else if (node->kind >= ASTART && node->kind < MAXKINDS) + n += printf("%s(", astnames[node->kind - ASTART]); else printnode(stdout, node); - if (node->kind == 'A' && ( - node->u.id == AIF || - node->u.id == AWHILE || - node->u.id == ALOOPUNTIL - ) && node->u.cond.cond) + 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.cond.cond, indent + 1); - } else if (node->kind == 'A' && node->u.id == ADECL && node->u.decl.init) { + 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.decl.init, indent + 1); + n += printast(node->u.payload, indent + 1); } if (node->lhs) { @@ -1459,10 +1509,10 @@ int qualifiers(int allowmask) { int flags = 0, mask = allowmask; - while (tok.kind == 'K') { + while (tok.kind >= KSTART && tok.kind < OSTART) { int f, m; - switch (tok.u.id) { + switch (tok.kind) { case KEXTERN: f = QEXTERN, m = ~QVISIB; break; @@ -1483,13 +1533,13 @@ qualifiers(int allowmask) { } if (f & ~allowmask) { - const char *str = keywords[tok.u.id].str; + const char *str = keywords[tok.kind - KSTART].str; error("invalid qualifier '%s'", str); } else if (f & flags & QTYPE) { - const char *str = keywords[tok.u.id].str; + const char *str = keywords[tok.kind - KSTART].str; warn("redundant qualifier '%s'", str); } else if (f & ~mask) { - const char *str = keywords[tok.u.id].str; + const char *str = keywords[tok.kind - KSTART].str; error("redundant qualifier '%s'", str); } @@ -1548,14 +1598,12 @@ advance: goto advance; } - if (tok.kind == 'O') { - if (tok.u.id == ODEREF) { - Type *tmp = maketype(); - tmp->kind = TPTR; - tmp->target = ty, ty = tmp; - gettok(false); - goto advance; - } + if (tok.kind == ODEREF) { + Type *tmp = maketype(); + tmp->kind = TPTR; + tmp->target = ty, ty = tmp; + gettok(false); + goto advance; } basetype->type = ty; @@ -1574,15 +1622,14 @@ declaration(Node *typenode) { Node *result = typenode; if (tok.kind == 'I') { - Decl *decl = makedecl(tok.u.id, DVAR); + Decl *decl = makedecl(tok.u.key, DVAR); result = makenode(typenode); - result->kind = 'A'; - result->u.decl.id = ADECL; + result->kind = ADECL; result->rhs = makenode(NULL); gettok(true); } else if (tok.kind == 'T') { Node *module = gettype(getbasetype(0)); - if (tok.kind == 'O' && tok.u.id == ODISP || tok.kind == ':') { + if (tok.kind == ODISP || tok.kind == ':') { has_self_param = tok.kind == ':'; gettok(false); } else { @@ -1591,12 +1638,10 @@ declaration(Node *typenode) { if (tok.kind == 'I') { module = makenode(module); - module->kind = 'O'; - module->u.id = ODISP; + module->kind = ODISP; module->rhs = makenode(NULL); result = makenode(typenode); - result->kind = 'A'; - result->u.decl.id = ADECL; + result->kind = ADECL; result->rhs = module; gettok(true); } else { @@ -1606,25 +1651,25 @@ declaration(Node *typenode) { return result; } - if (tok.kind == 'O' && tok.u.id == OCALL) { + if (tok.kind == OCALL) { Node *params; gettok(false); params = exprlist(true, NULL); expect(')', true, "expected ')'"); - if (tok.kind != 'O' || tok.u.id != OASS) { + if (tok.kind != OASS) { Node *stmts; stmts = stmtlist(lastindent, SFUNCTION); - result->u.decl.init = stmts; + result->u.payload = stmts; } } - if (tok.kind == 'O' && tok.u.id == OASS) { + if (tok.kind == OASS) { gettok(false); - result->u.decl.init = expr(PSTART); + result->u.payload = expr(PSTART); } else { - result->u.decl.init = NULL; + result->u.payload = NULL; } return result; @@ -1637,20 +1682,14 @@ isatom(void) { case '\n': case ';': case ',': case ':': case ')': case ']': case '}': + case KELSE: + case KUNTIL: return false; - case 'O': - if (ops[tok.u.id].prec != PUNARY) - return false; - return true; - case 'K': - switch (tok.u.id) { - case KELSE: - case KUNTIL: - return false; - } - return true; } + if (getnumops(tok.kind) && getprec(tok.kind) != PUNARY) + return false; + return true; } @@ -1693,8 +1732,7 @@ stmtlist(int indent, EnvKind envkind) { stmt = exprlist(false, NULL); stmt = makenode(stmt); - stmt->kind = 'A'; - stmt->u.id = ASTMT; + stmt->kind = ASTMT; if (!lhs) { result = lhs = stmt; @@ -1707,9 +1745,8 @@ stmtlist(int indent, EnvKind envkind) { env = popenv(); result = makenode(result); - result->kind = 'A'; - result->u.scope.id = ASCOPE; - result->u.scope.env = env; + result->kind = ASCOPE; + result->u.env = env; env->stmts = result; return result; @@ -1724,7 +1761,7 @@ atom(int flags) { /* int flags; */ /* unary 'is'-operator */ - if (tok.kind == 'K' && tok.u.id == KIS) { + if (tok.kind == KIS) { if (!lastis) { error("there is no left-hand-side for 'is'"); lhs = makenode(NULL); @@ -1735,17 +1772,17 @@ atom(int flags) { gettok(false); lhs->kind = 'O'; - if (tok.kind == 'K' && tok.u.id == KNOT) - gettok(false), lhs->u.id = ONEQ; + if (tok.kind == KNOT) + gettok(false), lhs->kind = ONEQ; else - lhs->u.id = OEQU; + lhs->kind = OEQU; lhs->rhs = expr(PRELAT); return lhs; } /* unary prefix operators */ - if (tok.kind == 'O' && ops[tok.u.id].prec == PUNARY) { + if (getprec(tok.kind) == PUNARY) { lhs = makenode(NULL); gettok(false); lhs->lhs = atom(0); @@ -1774,8 +1811,7 @@ atom(int flags) { lhs = exprlist(false, NULL), lastis = savedis; if (lhs->kind == 'T') { /* NOTE(m21c): expecting that the type is also set in lhs->type */ - lhs->kind = 'O'; - lhs->u.id = OCAST; + lhs->kind = OCAST; skipnewline(); expect(')', true, "expected ')'"); @@ -1792,8 +1828,7 @@ atom(int flags) { lhs = exprlist(false, NULL), lastis = savedis; if (lhs->kind == 'T') { /* NOTE(m21c): expecting that the type is also set in lhs->type */ - lhs->kind = 'O'; - lhs->u.id = OCAST; + lhs->kind = OCAST; skipnewline(); expect(')', true, "expected ')'"); @@ -1808,11 +1843,10 @@ atom(int flags) { case 'I': lhs = makenode(NULL); - lhs->u.declref.ref = finddeclaration(lhs->u.id); + lhs->u.declref = finddeclaration(tok.u.key); - if (lhs->u.declref.ref) { - lhs->kind = 'A'; - lhs->u.declref.id = ADECLREF; + if (lhs->u.declref) { + lhs->kind = ADECLREF; } else { Env *funcenv = getfuncenv(); if (funcenv) { @@ -1828,8 +1862,9 @@ atom(int flags) { } } } else { - error("'%s' undeclared", getstring(idents, lhs->u.id)); + error("'%s' undeclared", getstring(idents, tok.u.key)); } + lhs->u.key = tok.u.key; } gettok(true); @@ -1847,110 +1882,92 @@ atom(int flags) { /* TODO(m21c): const - conversion */ } break; - case 'K': - switch (tok.u.id) { - case KNOT: - lhs = makenode(NULL); + case KNOT: + lhs = makenode(NULL); + gettok(false); + lhs->kind = OLNOT; + lhs->lhs = expr(PRELAT); + break; + case KBREAK: + case KCONTINUE: + lhs = makenode(NULL); + lhs->kind = tok.kind == KBREAK ? ABREAK : ACONTINUE; + gettok(true); + if (tok.kind == ':') { gettok(false); - lhs->kind = 'O'; - lhs->u.id = OLNOT; - lhs->lhs = expr(PRELAT); - break; - case KBREAK: - case KCONTINUE: - lhs = makenode(NULL); - lhs->kind = 'A'; - lhs->u.id = tok.u.id == KBREAK ? ABREAK : ACONTINUE; - gettok(true); - if (tok.kind == ':') { - gettok(false); - skipnewline(); - if (tok.kind == 'I') { - lhs->lhs = makenode(NULL); - gettok(false); - } else { - error("expected identifier"); - } - } - break; - case KRETURN: - lhs = makenode(NULL); - gettok(true); - lhs->kind = 'A'; - lhs->u.id = ARETURN; - if (tok.kind == ':') { + skipnewline(); + if (tok.kind == 'I') { + lhs->lhs = makenode(NULL); gettok(false); - skipnewline(); - if (tok.kind == 'I') { - lhs->lhs = makenode(NULL); - gettok(false); - } else { - error("expected identifier"); - } + } else { + error("expected identifier"); } - if (isatom()) - lhs->rhs = exprlist(false, NULL); - break; - case KDO: - indent = lastindent; - lhs = makenode(NULL); - gettok(false); - lhs->kind = 'A'; - lhs->u.id = ADO; - lhs->lhs = stmtlist(indent, SSCOPE); - break; - case KLOOP: - indent = lastindent; - lhs = makenode(NULL); + } + break; + case KRETURN: + lhs = makenode(NULL); + gettok(true); + lhs->kind = ARETURN; + if (tok.kind == ':') { gettok(false); - lhs->kind = 'A'; - lhs->u.id = ALOOP; - lhs->lhs = stmtlist(indent, SSCOPE); - - if (tok.kind == 'K' && tok.u.id == KUNTIL && - lastindent >= indent) - { - lhs->u.cond.id = ALOOPUNTIL; + skipnewline(); + if (tok.kind == 'I') { + lhs->lhs = makenode(NULL); gettok(false); - lhs->u.cond.cond = expr(POR); + } else { + error("expected identifier"); } - if (lhs->u.id != ALOOP) - goto joinelse; - else - break; - case KWHILE: - indent = lastindent; - lhs = makenode(NULL); + } + if (isatom()) + lhs->rhs = exprlist(false, NULL); + break; + case KDO: + indent = lastindent; + lhs = makenode(NULL); + gettok(false); + lhs->kind = ADO; + lhs->lhs = stmtlist(indent, SSCOPE); + break; + case KLOOP: + indent = lastindent; + lhs = makenode(NULL); + gettok(false); + lhs->kind = ALOOP; + lhs->lhs = stmtlist(indent, SSCOPE); + + if (tok.kind == KUNTIL && lastindent >= indent) { + lhs->kind = ALOOPUNTIL; gettok(false); - lhs->kind = 'A'; - lhs->u.cond.id = AWHILE; - lhs->u.cond.cond = expr(POR); - lhs->lhs = stmtlist(indent, SSCOPE); + lhs->u.payload = expr(POR); + } + if (lhs->kind != ALOOP) goto joinelse; - case KIF: - indent = lastindent; - lhs = makenode(NULL); - gettok(false); - lhs->kind = 'A'; - lhs->u.cond.id = AIF; - lhs->u.cond.cond = expr(POR); - skipnewline(); - if (tok.kind == 'I' && tok.u.id == auxthen) - gettok(false); - lhs->lhs = stmtlist(indent, SSCOPE); - joinelse: - if (tok.kind == 'K' && tok.u.id == KELSE && - lastindent >= indent) - { - gettok(false); - lhs->rhs = stmtlist(indent, SSCOPE); - } + else break; - default: - goto joinerror; + case KWHILE: + indent = lastindent; + lhs = makenode(NULL); + gettok(false); + lhs->kind = AWHILE; + lhs->u.payload = expr(POR); + lhs->lhs = stmtlist(indent, SSCOPE); + goto joinelse; + case KIF: + indent = lastindent; + lhs = makenode(NULL); + gettok(false); + lhs->kind = AIF; + lhs->u.payload = expr(POR); + skipnewline(); + if (tok.kind == 'I' && tok.u.key == auxthen) + gettok(false); + lhs->lhs = stmtlist(indent, SSCOPE); + joinelse: + if (tok.kind == KELSE && lastindent >= indent) { + gettok(false); + lhs->rhs = stmtlist(indent, SSCOPE); } break; - case 'O': default: joinerror: error("expected expression"); @@ -1959,21 +1976,21 @@ atom(int flags) { } /* unary postfix operators */ - while (tok.kind == 'O' && ops[tok.u.id].prec == PUNSUF) { + while (getprec(tok.kind) == PUNSUF) { lhs = makenode(lhs); - if (tok.u.id == ODISP) { + if (tok.kind == ODISP) { gettok(false); skipnewline(); if (tok.kind != 'I') error("expected identifier"); lhs->rhs = makenode(NULL); - } else if (tok.u.id == OCALL) { + } else if (tok.kind == OCALL) { gettok(false); if (tok.kind != ')') lhs->rhs = exprlist(false, NULL), lastis = savedis; expect(')', true, "expected ')'"); continue; - } else if (tok.u.id == OARRAY) { + } else if (tok.kind == OARRAY) { gettok(false); lhs->rhs = exprlist(false, NULL), lastis = savedis; expect(']', true, "expected ']'"); @@ -1983,15 +2000,15 @@ atom(int flags) { } /* 'not'-suffix for the binary 'is'-operator (i.e. 'is not') */ - while (tok.kind == 'K' && tok.u.id == KIS) { + while (tok.kind == KIS) { lhs = makenode(lhs); gettok(false); lhs->kind = 'O'; - if (tok.kind == 'K' && tok.u.id == KNOT) - gettok(false), lhs->u.id = ONEQ; + if (tok.kind == KNOT) + gettok(false), lhs->kind = ONEQ; else - lhs->u.id = OEQU; + lhs->kind = OEQU; lastis = lhs; lhs->rhs = expr(PRELAT); @@ -2005,23 +2022,19 @@ expr(int minprec) { Node *lhs = atom(0), *last = NULL; /* only binary expr */ - while (tok.kind == 'O' && ops[tok.u.id].prec >= minprec) { + while (getprec(tok.kind) >= minprec) { lhs = makenode(lhs); gettok(false); skipnewline(); - if (ops[lhs->u.id].rassoc) - lhs->rhs = expr(ops[lhs->u.id].prec); - else - lhs->rhs = expr(ops[lhs->u.id].prec + 1); + lhs->rhs = expr(getprec(lhs->kind) + !israssoc(lhs->kind)); - switch (ops[lhs->u.id].prec) { + switch (getprec(lhs->kind)) { case PRELAT: if (last) { lhs = makenode(lhs); lhs->rhs = lhs->lhs; - lhs->kind = 'O'; - lhs->u.id = OLAND; + lhs->kind = OLAND; lhs->lhs = lhs->rhs->lhs; lhs->rhs->lhs = last->rhs; /* copy */ @@ -2044,22 +2057,21 @@ todeclaration(Node *curr, Node **ty) { if (*ty) { if (curr->kind == 'I') { Node *decl = makenode(*ty); - curr->kind = 'A'; - curr->u.decl.id = ADECL; + curr->kind = ADECL; decl->rhs = curr; curr = decl; - } else if (curr->kind == 'O' && curr->u.id == OASS && + } else if (curr->kind == OASS && curr->lhs && curr->lhs->kind == 'I') { curr->kind = 'A'; - curr->u.decl.id = ADECL; - curr->u.decl.init = curr->rhs; + curr->kind = ADECL; + curr->u.payload = curr->rhs; curr->rhs = curr->lhs; curr->lhs = *ty; } } - if (curr->kind == 'A' && curr->u.id == ADECL) + if (curr->kind == ADECL) *ty = curr->lhs; return curr; @@ -2078,10 +2090,10 @@ exprlist(bool isparam, Node *paramtype) { head = expr(PSTART), tail = head; } - if (isparam && (tail->kind != 'A' || tail->u.id != ADECL)) + if (isparam && tail->kind != ADECL) error("expected declaration"); - if ((isdeclaration = tail->kind == 'A' && tail->u.id == ADECL)) { + if ((isdeclaration = tail->kind == ADECL)) { paramtype = tail->lhs; } @@ -2101,11 +2113,10 @@ exprlist(bool isparam, Node *paramtype) { /* curr = todeclaration(curr, &paramtype); */ } - if ((paramtype || isparam) && - (curr->kind != 'A' || curr->u.id != ADECL)) + if ((paramtype || isparam) && curr->kind != ADECL) error("expected declaration"); - if (curr->kind == 'A' && curr->u.id == ADECL) { + if (curr->kind == ADECL) { paramtype = tail->lhs; isdeclaration = true; } @@ -2252,24 +2263,19 @@ Node *foldexpr(Node *expr) for (c = expr; c; c = c->next) { #if 1 - switch (c->kind) - { - case 'I': - c->u.declref.ref = finddeclaration(c->u.id); - if (c->u.declref.ref) { - c->kind = 'A'; - c->u.declref.id = ADECLREF; + if (c->kind == 'I') { + Decl *declref = finddeclaration(c->u.key); + if (declref) { + c->kind = ADECLREF; + c->u.declref = declref; } else { - error("'%s' undeclared", getstring(idents, c->u.id)); + error("'%s' undeclared", getstring(idents, c->u.key)); } continue; - case 'A': - if (c->u.id == AIF && c->u.cond.cond) { - c->u.cond.cond = foldexpr(c->u.cond.cond); - } - break; - default: - break; + } + + if (c->kind == AIF && c->u.payload) { + c->u.payload = foldexpr(c->u.payload); } if (c->lhs)