Aria

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

commit 917733ec3da6966cc2962d6194ba7716347d3b6d
parent 0521d59eb791de93d2d95650d229f28d324c15e7
Author: m21c  <ho*******@gmail.com>
Date:   Mon, 12 Jul 2021 22:08:50 +0200

re-organized source-code

Diffstat:
M.gitignore | 1+
Maria.c | 827+++++++++++++++++++++++++++++++++++++++++--------------------------------------
2 files changed, 428 insertions(+), 400 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -8,5 +8,6 @@ debug*.cmd debug*.sh *.txt +*.todo *.exe \ No newline at end of file diff --git a/aria.c b/aria.c @@ -7,70 +7,102 @@ #include <stdbool.h> #include <string.h> -/* utility function */ -static int -mystrncasecmp(const char *str1, const char *str2, size_t max_len) { - char tmp1[] = {'\0', '\0'}; - char tmp2[] = {'\0', '\0'}; - char c1, c2; - int result; - size_t i; +/* - forward declarations - */ +typedef +struct Node Node; - if (max_len == 0) { - size_t len1 = strlen(str1); - size_t len2 = strlen(str2); - max_len = len1 > len2 ? len1 : len2; - } +typedef +struct Type Type; - for (i = 0; i < max_len; ++i) { - c1 = tolower(str1[i]); - c2 = tolower(str2[i]); - if (c1 == '\0' && c2 == '\0') return 0; - tmp1[0] = c1; - tmp2[0] = c2; - result = strcmp(tmp1, tmp2); - if (result != 0) return result; - } +typedef +struct Decl Decl; - return 0; -} +typedef +struct Env Env; -static int -mystrcasecmp(const char *str1, const char *str2) { - char tmp1[] = {'\0', '\0'}; - char tmp2[] = {'\0', '\0'}; - char c1, c2; - int result; - size_t i; - for (i = 0;; ++i) { - c1 = tolower(str1[i]); - c2 = tolower(str2[i]); - if (c1 == '\0' && c2 == '\0') return 0; - tmp1[0] = c1; - tmp2[0] = c2; - result = strcmp(tmp1, tmp2); - if (result != 0) return result; - } +/* - enumerations & constants - */ - return 0; -} +enum { + PUNSUF = 10, + PUNARY = 9, + PMUL = 8, + PADD = 7, + PRANGE = 6, + PRELAT = 5, + PAND = 4, + POR = 3, + PASSIGN = 2, -/* - forward declarations - */ + PSTART = 1 +}; -typedef -struct Node Node; +typedef enum Kind { + ANNOT = '@', + SEMIDELIM = ';', COMMADELIM = ',', COLONDELIM = ':', + LCURLDELIM = '{', /*LSQRDELIM = '[',*/ LPARDELIM = '(', + RCURLDELIM = '}', RSQRDELIM = ']', RPARDELIM = ')', + CHAR = 'C', + IDENT = 'I', + NUMBER = 'N', + STRING = 'S', + TYPE = 'T', -typedef -struct Decl Decl; + LASTCHAR = '~', -typedef -struct Env Env; + /* Keywords */ + KVOID, KBOOL, + KU8, KS8, KU16, KS16, KU32, KS32, KU64, KS64, + KF32, KF64, + KUCHAR, KCHAR, KUSHORT, KSHORT, KUINT, KINT, \ + KULONG, KLONG, KULLONG, KLLONG, + KFLOAT, KDOUBLE, KLDOUBLE, + KUSIZE, KSSIZE, + KUSE, KNOT, KAND, KOR, KIS, + KEXTERN, KINTERN, KSTATIC, KCONST, KVAR, + KBREAK, KCONTINUE, KGOTO, KRETURN, + KIF, KELSE, KCASE, KOF, KDO, + KFOR, KLOOP, KWHILE, KUNTIL, + + /* Operators */ + OSUFINC, OSUFDEC, OARRAY, OCALL, ODISP, + OLPTR, OINC, ODEC, OBNOT, OLNOT, OFLIP, /*ORPTR,*/ 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, + + /* Ast */ + ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE, + ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, + ACONV, + ADEREF, AADDR, + + MAXKINDS +} Kind; + +#define KSTART KVOID +#define OSTART OSUFINC +#define ASTART ASTMT + +#define iskeyword(kind) ((kind) >= KSTART && (kind) < OSTART) +#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'; +} -/* - type struct - */ typedef enum { TERRTYPE = 1, TUNDEFINED, @@ -106,225 +138,149 @@ typedef enum { /* TODO(m21c): maybe add long double type ? */ typedef -struct Type Type; - -struct Type { - TypeKind kind; - - size_t size, align; - - union { - struct { - int offset, size; - } bit; - struct { - size_t length; - size_t elemsize; - } array; - Node *val; - } u; - - Type *target; -}; - -Type prim[] = { - [TERRTYPE] = {TERRTYPE, 0, 0, {0}, NULL}, - [TUNDEFINED] = {TUNDEFINED, 0, 0, {0}, NULL}, +enum DeclKind { + DMODULE = 0, + DTYPE, /* NOTE(m21c): maybe be the same as void-module ? */ + DVAR, + DPARAM, + DFUNCTION, + /* + DMACRO, + DENFOLD + */ +} DeclKind; - [TVOID] = {TVOID, 0, 0, {0}, NULL}, +typedef +enum EnvKind { + STOPLEVEL = 0, + SPARAMLIST, + SFUNCTION, + SSCOPE, + /* + SUNION, + SSTRUCT, + SENUM, + */ +} EnvKind; - [TBOOL] = {TBOOL, 1, 1, {0}, NULL}, +enum { + QINTERN = 0x0001, + QEXTERN = 0x0002, - [TINFER] = {TINFER, 4, 4, {0}, NULL}, - [TUINFER] = {TUINFER, 4, 4, {0}, NULL}, + QSTATIC = 0x0010, - [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}, + QCONST = 0x0200, - [TF32] = {TF32, 4, 4, {0}, NULL}, - [TF64] = {TF64, 8, 8, {0}, NULL}, + QVAR = 0x1000, - [TPTR] = {TPTR, 8, 8, {0}, NULL}, - [TARRAY] = {TARRAY, 0, 0, {0}, NULL}, + /* masks */ + QALL = QINTERN | QEXTERN | QSTATIC | QCONST | QVAR, + QVISIB = QEXTERN | QINTERN, + QSTORAGE = QSTATIC, + QTYPE = QCONST, + QINFER = QVAR, }; -Type typebuf[4096]; -int typetop; -Type * -maketype(void) { - return typebuf + typetop++; -} - -/* - pre-lexer - */ - -char line[4096]; -int currline, lastline; -long linepos; -bool handlereplprompt; +/* - type definitions - */ -void -tryprompt(FILE *in, const char ch) { - if (handlereplprompt) { - fprintf(stdout, "\e[35m%c \e[0m", ch); - } else if (in == stdin) { - handlereplprompt = true; - } -} - -bool -mygetline(FILE *in) { - int i, l, c; - - tryprompt(in, '.'); - c = getc(in); - - linepos = ftell(in); - -advance: - ++currline; +struct Node { + Kind kind; - i = 0, l = 0; - while (c == '\r' || c == '\n') { - tryprompt(in, '.'); - l = c, c = getc(in); + Type *type; - if (l == '\r' && c == '\n') - c = getc(in); + union { + int key; - ++currline; - } + double d; + uint64_t u; + int64_t s; - lastline = currline; + Node *payload; + Decl *declref; + Env *env; + } u; - while (c != EOF && c != '\n' && c != '\r') { - line[i++] = c; - c = getc(in); + Node *lhs, *rhs; + Node *prev, *next; +}; - if (c == '\\') { - int x = getc(in); - if (x == '\n') { - tryprompt(in, '\\'); - c = getc(in); +struct Type { + TypeKind kind; - ++currline; - } else if (x == '\r') { - int y; + size_t size, align; - tryprompt(in, '\\'); - y = getc(in); + union { + struct { + int offset, size; + } bit; + struct { + size_t length; + size_t elemsize; + } array; + Node *val; + } u; - c = (y == '\n') ? getc(in) : y; - ++currline; - } else if (x == EOF) { - c = x; - } else { - ungetc(x, in); - } - } - } + Type *target; +}; - if (c == '\r') { - int x; +struct Decl { + DeclKind kind; - tryprompt(in, '.'); - x = getc(in); - if (x != '\n') - ungetc(x, in); - } + Type *type; - if (c != EOF && i == 0) - goto advance; + Env *env, *functionenv; + Node *content; /* init or function body */ - line[i] = 0; - return c != EOF || i; -} + int key; + Decl *prev, *next; +}; -/* - lexer - */ +struct Env { + EnvKind kind; -enum { - PUNSUF = 10, - PUNARY = 9, - PMUL = 8, - PADD = 7, - PRANGE = 6, - PRELAT = 5, - PAND = 4, - POR = 3, - PASSIGN = 2, + uint8_t keycache[64]; - PSTART = 1 -}; + Decl *head, *tail; -typedef enum Kind { - ANNOT = '@', - SEMIDELIM = ';', COMMADELIM = ',', COLONDELIM = ':', - LCURLDELIM = '{', /*LSQRDELIM = '[',*/ LPARDELIM = '(', - RCURLDELIM = '}', RSQRDELIM = ']', RPARDELIM = ')', - CHAR = 'C', - IDENT = 'I', - NUMBER = 'N', - STRING = 'S', - TYPE = 'T', + Node *stmts; + Decl *funcdecl; /* for SFUNCTION */ - LASTCHAR = '~', + Env *below; - /* Keywords */ - KVOID, KBOOL, - KU8, KS8, KU16, KS16, KU32, KS32, KU64, KS64, - KF32, KF64, - KUCHAR, KCHAR, KUSHORT, KSHORT, KUINT, KINT, \ - KULONG, KLONG, KULLONG, KLLONG, - KFLOAT, KDOUBLE, KLDOUBLE, - KUSIZE, KSSIZE, - KUSE, KNOT, KAND, KOR, KIS, - KEXTERN, KINTERN, KSTATIC, KCONST, KVAR, - KBREAK, KCONTINUE, KGOTO, KRETURN, - KIF, KELSE, KCASE, KOF, KDO, - KFOR, KLOOP, KWHILE, KUNTIL, + bool pending; + Env *pendingnext, *pendingprev; +}; - /* Operators */ - OSUFINC, OSUFDEC, OARRAY, OCALL, ODISP, - OLPTR, OINC, ODEC, OBNOT, OLNOT, OFLIP, /*ORPTR,*/ 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, +/* - look-up tables - */ - /* Ast */ - ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE, - ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE, - ACONV, - ADEREF, AADDR, +Type prim[] = { + [TERRTYPE] = {TERRTYPE, 0, 0, {0}, NULL}, + [TUNDEFINED] = {TUNDEFINED, 0, 0, {0}, NULL}, - MAXKINDS -} Kind; + [TVOID] = {TVOID, 0, 0, {0}, NULL}, -#define KSTART KVOID -#define OSTART OSUFINC -#define ASTART ASTMT + [TBOOL] = {TBOOL, 1, 1, {0}, NULL}, -#define iskeyword(kind) ((kind) >= KSTART && (kind) < OSTART) -#define isoperator(kind) ((kind) >= OSTART && (kind) < ASTART) -#define isastnode(kind) ((kind) >= ASTART && (kind) < MAXKINDS) + [TINFER] = {TINFER, 4, 4, {0}, NULL}, + [TUINFER] = {TUINFER, 4, 4, {0}, NULL}, -bool isatomnode(Kind kind) -{ - return kind == 'I' || kind == ADECLREF || kind == 'N' || kind == 'S' || - kind == 'C'; -} + [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}, + + [TPTR] = {TPTR, 8, 8, {0}, NULL}, + [TARRAY] = {TARRAY, 0, 0, {0}, NULL}, +}; int keywordlengths[OSTART - KSTART]; @@ -478,48 +434,189 @@ const uint8_t opinfo[] = { [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), + [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] & 0x1f)) + + + +/* utility function */ + +#define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array))) + +static int +mystrncasecmp(const char *str1, const char *str2, size_t max_len) { + char tmp1[] = {'\0', '\0'}; + char tmp2[] = {'\0', '\0'}; + char c1, c2; + int result; + + size_t i; + + if (max_len == 0) { + size_t len1 = strlen(str1); + size_t len2 = strlen(str2); + max_len = len1 > len2 ? len1 : len2; + } + + for (i = 0; i < max_len; ++i) { + c1 = tolower(str1[i]); + c2 = tolower(str2[i]); + if (c1 == '\0' && c2 == '\0') return 0; + tmp1[0] = c1; + tmp2[0] = c2; + result = strcmp(tmp1, tmp2); + if (result != 0) return result; + } + + return 0; +} + +static int +mystrcasecmp(const char *str1, const char *str2) { + char tmp1[] = {'\0', '\0'}; + char tmp2[] = {'\0', '\0'}; + char c1, c2; + int result; + + size_t i; + + for (i = 0;; ++i) { + c1 = tolower(str1[i]); + c2 = tolower(str2[i]); + if (c1 == '\0' && c2 == '\0') return 0; + tmp1[0] = c1; + tmp2[0] = c2; + result = strcmp(tmp1, tmp2); + if (result != 0) return result; + } + + return 0; +} + + + +/* - pre-lexer - */ + +char line[4096]; +int currline, lastline; +long linepos; + +bool handlereplprompt; + +void +tryprompt(FILE *in, const char ch) { + if (handlereplprompt) { + fprintf(stdout, "\e[35m%c \e[0m", ch); + } else if (in == stdin) { + handlereplprompt = true; + } +} + +bool +mygetline(FILE *in) { + int i, l, c; + + tryprompt(in, '.'); + c = getc(in); + + linepos = ftell(in); + +advance: + ++currline; + + i = 0, l = 0; + while (c == '\r' || c == '\n') { + tryprompt(in, '.'); + l = c, c = getc(in); + + if (l == '\r' && c == '\n') + c = getc(in); + + ++currline; + } + + lastline = currline; - [ORANGE] = opentry(2, false, PRANGE), + while (c != EOF && c != '\n' && c != '\r') { + line[i++] = c; + c = getc(in); - [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), + if (c == '\\') { + int x = getc(in); + if (x == '\n') { + tryprompt(in, '\\'); + c = getc(in); - [OLAND] = opentry(2, false, PAND), + ++currline; + } else if (x == '\r') { + int y; - [OLOR] = opentry(2, false, POR), + tryprompt(in, '\\'); + y = getc(in); - [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), + c = (y == '\n') ? getc(in) : y; + ++currline; + } else if (x == EOF) { + c = x; + } else { + ungetc(x, in); + } + } + } - [MAXKINDS] = 0 -}; + if (c == '\r') { + int x; -#define getnumops(kind) (opinfo[kind] >> 6) -#define israssoc(kind) ((opinfo[kind] >> 5) & 0x01) -#define getprec(kind) ((opinfo[kind] & 0x1f)) + tryprompt(in, '.'); + x = getc(in); + if (x != '\n') + ungetc(x, in); + } -#define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array))) + if (c != EOF && i == 0) + goto advance; + + line[i] = 0; + return c != EOF || i; +} -/* keyword map */ +/* - keyword map - */ #define KEYWORD_MAP_SIZE 128 const char *keywordkeys[KEYWORD_MAP_SIZE]; @@ -575,7 +672,7 @@ getkeyword(const char *str, int n) { return -1; } -/* string map */ +/* - string map - */ typedef struct StringEntry { @@ -696,27 +793,6 @@ getstringkey(StringMap *map, const char *str, int n) { /* node-structure & global vars for lexer and subsequent phases */ -struct Node { - Kind kind; - - Type *type; - - union { - int key; - - double d; - uint64_t u; - int64_t s; - - Node *payload; - Decl *declref; - Env *env; - } u; - - Node *lhs, *rhs; - Node *prev, *next; -}; - FILE *filein; const char *filename; const int tabwidth = 8; @@ -725,7 +801,7 @@ char stringbuf[1024]; int currcol, lastcol, lastindent, lastkind; Node tok; -/* error reporting */ +/* - error reporting - */ int warn(const char *fmt, ...) { @@ -757,7 +833,7 @@ error(const char *fmt, ...) { return n; } -/* actual lexer ( gettok() ) */ +/* - lexer - */ #define nextindent(indent) \ ((indent) + tabwidth - ((indent) % tabwidth)) @@ -1111,64 +1187,37 @@ skipwhite: #define skipnewline() \ (tok.kind == '\n' ? (void) gettok(false) : (void) 0) -/* - environment & declaration */ -typedef -enum DeclKind { - DMODULE = 0, - DTYPE, /* NOTE(m21c): maybe be the same as void-module ? */ - DVAR, - DPARAM, - DFUNCTION, - /* - DMACRO, - DENFOLD - */ -} DeclKind; -struct Decl { - DeclKind kind; +/* - ast-node - */ - Type *type; +Node nodebuf[4096]; +int nodetop; - Env *env, *functionenv; - Node *content; /* init or function body */ +Node * +makenode(Node *lhs) { + Node *node = nodebuf + nodetop++; + *node = tok; + node->lhs = lhs; - int key; - Decl *prev, *next; -}; + return node; +} -typedef -enum EnvKind { - STOPLEVEL = 0, - SPARAMLIST, - SFUNCTION, - SSCOPE, - /* - SUNION, - SSTRUCT, - SENUM, - */ -} EnvKind; -struct Env { - EnvKind kind; - uint8_t keycache[64]; +/* - type-strcut - */ - Decl *head, *tail; +Type typebuf[4096]; +int typetop; - Node *stmts; - Decl *funcdecl; /* for SFUNCTION */ +Type * +maketype(void) { + return typebuf + typetop++; +} - Env *below; - bool pending; - Env *pendingnext, *pendingprev; -}; -Decl declbuf[4096]; -int decltop; +/* - environment - */ Env envbuf[4096]; int envtop; @@ -1196,43 +1245,6 @@ finddeclinenv(int key, Env *env) { } Decl * -makedecl(int key, DeclKind kind) { - const int cacheindex = (key >> 3) & 0x3f; - const int cachebit = 1 << (key & 0x03); - - Decl *probe, *decl = declbuf + decltop++; - - decl->kind = kind; - decl->key = key; - decl->type = prim + TVOID; - decl->functionenv = NULL; - - assert(currenv); - - probe = finddeclinenv(key, currenv); - - if (probe) { - error("'%s' already declared", getstring(idents, key)); - } - - currenv->keycache[cacheindex] |= cachebit; - - decl->env = currenv; - - if (currenv->tail) { - currenv->tail->next = decl; - decl->prev = currenv->tail; - } else { - assert(currenv->head == NULL); - currenv->head = decl; - } - - currenv->tail = decl; - - return decl; -} - -Decl * finddeclaration(int key) { const int cacheindex = (key >> 3) & 0x3f; const int cachebit = 1 << (key & 0x03); @@ -1323,20 +1335,52 @@ getfuncenv(void) { return NULL; } -/* - ast-node - */ -Node nodebuf[4096]; -int nodetop; -Node * -makenode(Node *lhs) { - Node *node = nodebuf + nodetop++; - *node = tok; - node->lhs = lhs; +/* - declaration - */ - return node; +Decl declbuf[4096]; +int decltop; + +Decl * +makedecl(int key, DeclKind kind) { + const int cacheindex = (key >> 3) & 0x3f; + const int cachebit = 1 << (key & 0x03); + + Decl *probe, *decl = declbuf + decltop++; + + decl->kind = kind; + decl->key = key; + decl->type = prim + TVOID; + decl->functionenv = NULL; + + assert(currenv); + + probe = finddeclinenv(key, currenv); + + if (probe) { + error("'%s' already declared", getstring(idents, key)); + } + + currenv->keycache[cacheindex] |= cachebit; + + decl->env = currenv; + + if (currenv->tail) { + currenv->tail->next = decl; + decl->prev = currenv->tail; + } else { + assert(currenv->head == NULL); + currenv->head = decl; + } + + currenv->tail = decl; + + return decl; } + + /* - parser - */ bool @@ -1357,24 +1401,6 @@ expect(int kind, bool nexthaslhs, const char *fmt, ...) { return true; } -enum { - QINTERN = 0x0001, - QEXTERN = 0x0002, - - QSTATIC = 0x0010, - - QCONST = 0x0200, - - QVAR = 0x1000, - - /* masks */ - QALL = QINTERN | QEXTERN | QSTATIC | QCONST | QVAR, - QVISIB = QEXTERN | QINTERN, - QSTORAGE = QSTATIC, - QTYPE = QCONST, - QINFER = QVAR, -}; - int qualifiers(int allowmask) { int flags = 0, mask = allowmask; @@ -2694,7 +2720,8 @@ foldexpr(Node *expr) { /* - print ast - */ -typedef enum Highlight { +typedef +enum Highlight { HLNONE = 0, HLDELIM = 1, HLUNKNOWN = 2,