Aria

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

commit 810119b44fdb4cff269d676d4bd5ca4061b94c28
parent 3ffc6b6c22cbaac8f8d11d344e13fbd195551dc9
Author: m21c  <ho*******@gmail.com>
Date:   Thu, 15 Jul 2021 13:35:44 +0200

minor code cleanup + changed SrcLoc in makedecl

Diffstat:
Maria.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 166 insertions(+), 3 deletions(-)

diff --git a/aria.c b/aria.c @@ -904,12 +904,14 @@ skipwhite: source->lastindent = 0; return source->tok.kind = 0; } + c0 = source->line[(source->currloc.column = 0)]; } if (source->currloc.column) { while (isspace(c0)) c0 = source->line[++source->currloc.column]; + } else { source->lastindent = 0; while (isspace(c0)) { @@ -1057,9 +1059,9 @@ skipwhite: } else if (*end == 'l' || *end == 'L') { source->tok.type = prim + TDOUBLE; + if (end[1]) goto errorfloat; - } else if (!mystrcasecmp(end, "f32") || !mystrcasecmp(end, "r32")) { @@ -1108,31 +1110,39 @@ skipwhite: ++end; if (*end == 0) { typeid += TINFER; + break; } else if (*end == '8') { typeid += TS8; + if (end[1]) goto errorint; break; } else if (!strcmp(end, "16")) { typeid += TS16; + break; } else if (!strcmp(end, "32")) { typeid += TS32; + break; } else if (!strcmp(end, "64")) { typeid += TS64; + break; } else if (!mystrcasecmp(end, "sz")) { typeid += TSSIZE; + break; } default: if (!mystrcasecmp(end, "ll")) { typeid += TLLONG; + } else if (*end == 'l' || *end == 'L') { typeid += TLONG; + if (end[1]) goto errorint; } else { @@ -1141,6 +1151,7 @@ skipwhite: &source->currloc, "invalid integer format" ); + typeid = TINT; } } @@ -1154,6 +1165,7 @@ skipwhite: /* string & character-literal */ if (c0 == '"' || c0 == '\'') { int delim = c0, j; + c0 = source->line[++source->currloc.column]; source->tok.loc.column = source->currloc.column; @@ -1161,28 +1173,36 @@ skipwhite: while (c0 != delim && c0 != 0) { if (c0 == '\\') { c0 = source->line[++source->currloc.column]; + switch (c0) { case '\\': c0 = '\\'; break; + case 'n': c0 = '\n'; break; + case 'r': c0 = '\r'; break; + case 't': c0 = '\t'; break; + case '\'': c0 = '\''; break; + case '"': c0 = '"'; break; + /* TODO(m21c): read more escape sequences */ case 0: goto stringeol; + default: error( &source->currloc, @@ -1191,9 +1211,11 @@ skipwhite: ); } } + source->line[j++] = c0; c0 = source->line[++source->currloc.column]; } + ++source->currloc.column; source->line[j++] = 0; @@ -1203,6 +1225,7 @@ skipwhite: &source->currloc, "unexpected end-of-line" ); + return source->tok.kind = '\n'; } @@ -1212,6 +1235,7 @@ skipwhite: source->line + source->tok.loc.column, j - source->tok.loc.column ); + return source->tok.kind = 'S'; } @@ -1226,10 +1250,12 @@ skipwhite: case ']': case ')': goto joindelim; + case '[': if (haslhs) c0 = OARRAY; goto joindelim; + case '(': if (haslhs) c0 = OCALL; @@ -1249,21 +1275,26 @@ skipwhite: /* tok.kind = select('.', ORANGE, ODISP); */ source->tok.kind = ODISP; goto joinop; + case '*': source->tok.kind = select('=', OMULA, (haslhs ? OMUL : OLPTR)); goto joinop; + case '/': source->tok.kind = select('=', ODIVA, ODIV); goto joinop; + case '%': source->tok.kind = select('=', OMODA, OMOD); goto joinop; + case '<': source->tok.kind = select('=', OLEQ, select('<', select('=', OLSHA, OLSH), OLET)); goto joinop; + case '>': source->tok.kind = select('=', OGEQ, select('>', @@ -1272,32 +1303,40 @@ skipwhite: select('=', ORSHA, ORSH)), OGRT)); goto joinop; + case '&': source->tok.kind = select('=', OANDA, select('&', OLAND, /*(haslhs ? OBAND : ORPTR)*/ OBAND)); goto joinop; + case '+': source->tok.kind = select('=', OADDA, select('+', (haslhs ? OSUFINC : OINC), (haslhs ? OADD : OPLUS))); goto joinop; + case '-': source->tok.kind = select('=', OSUBA, select('-', (haslhs ? OSUFDEC : ODEC), (haslhs ? OSUB : OMINUS))); goto joinop; + case '|': source->tok.kind = select('=', OORA, select('|', OLOR, OBOR)); goto joinop; + case '^': source->tok.kind = select('=', OXORA, OXOR); goto joinop; + case '!': source->tok.kind = select('=', ONEQ, OLNOT); goto joinop; + case '~': source->tok.kind = select('=', OFLIP, OBNOT); goto joinop; + case '=': source->tok.kind = select('=', select('=', OIDENT, OEQU), OASS); joinop: @@ -1477,6 +1516,7 @@ makedecl(Source *source, int key, DeclKind kind) { Decl *probe, *decl = declbuf + decltop++; decl->kind = kind; + decl->loc = source->tok.loc; decl->key = key; decl->type = prim + TVOID; decl->functionenv = NULL; @@ -1486,9 +1526,8 @@ makedecl(Source *source, int key, DeclKind kind) { probe = finddeclinenv(key, currenv); if (probe) { - /* TODO(m21c): obtain SrcLoc properly */ error( - &probe->loc, + &source->tok.loc, "'%s' already declared", getstring(idents, key) ); @@ -1536,6 +1575,7 @@ expect(Source *source, int kind, bool nexthaslhs, const char *fmt, ...) { vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); + return false; } @@ -1554,30 +1594,38 @@ qualifiers(Source *source, int allowmask) { case KEXTERN: f = QEXTERN, m = ~QVISIB; break; + case KINTERN: f = QINTERN, m = ~QVISIB; break; + case KSTATIC: f = QSTATIC, m = ~QSTORAGE; break; + case KCONST: f = QCONST; break; + case KVAR: f = QVAR, m = ~(QTYPE | QINFER); break; + default: goto finish; } if (f & ~allowmask) { const char *str = nodestrings[getkind(source)]; + error(getloc(source), "invalid qualifier '%s'", str); } else if (f & flags & QTYPE) { const char *str = nodestrings[getkind(source)]; + warn(getloc(source), "redundant qualifier '%s'", str); } else if (f & ~mask) { const char *str = nodestrings[getkind(source)]; + error(getloc(source), "redundant qualifier '%s'", str); } @@ -1625,8 +1673,10 @@ advance: tmp->kind = TARRAY; tmp->target = basetype, basetype = tmp; gettok(source, false); + if (source->tok.kind != ']') basetype->u.val = expr(source, PSTART); + expect(source, ']', false, "expect ']'"); goto advance; } @@ -1635,6 +1685,7 @@ advance: Type *tmp = maketype(); tmp->kind = TPTR; tmp->target = basetype, basetype = tmp; + gettok(source, false); goto advance; } @@ -1678,8 +1729,10 @@ declaration(Source *source, Type *ty) { result->type = ty; result->u.declref = decl; gettok(source, true); + } else if (getkind(source) == 'T') { Type *module = gettype(source, getbasetype(source, 0)); + if (getkind(source) == ODISP || getkind(source) == ':') { has_self_param = getkind(source) == ':'; gettok(source, false); @@ -1706,10 +1759,12 @@ declaration(Source *source, Type *ty) { } else { error(getloc(source), "expected identifier"); } + } else { result = makenode(&source->tok, NULL); result->kind = 'T'; result->type = ty; + return result; } @@ -1924,6 +1979,7 @@ atom(Source *source, int flags) { lhs = makenode(&source->tok, NULL); gettok(source, false); lhs->lhs = atom(source, 0); + return lhs; } @@ -1948,6 +2004,7 @@ atom(Source *source, int flags) { gettok(source, false); skipnewline(source); lhs = exprlist(source, false, NULL), source->lastis = savedis; + if (lhs->kind == 'T') { /* NOTE(m21c): expecting that the type is also set in lhs->type */ lhs->kind = OCAST; @@ -1957,10 +2014,12 @@ atom(Source *source, int flags) { lhs->lhs = atom(source, 0); break; } + skipnewline(source); expect(source, ')', true, "expected ')'"); #else gettok(source, false); + if (getkind(source) == '\n') { lhs = stmtlist(source, source->lastindent, SSCOPE); source->lastis = savedis; @@ -1977,8 +2036,10 @@ atom(Source *source, int flags) { lhs->lhs = atom(source, 0); break; } + skipnewline(source); } + expect(source, ')', true, "expected ')'"); #endif break; @@ -2021,28 +2082,36 @@ atom(Source *source, int flags) { if (flags & QCONST) { /* TODO(m21c): const - conversion */ } + break; + case 'T': case 'N': case 'S': case 'C': lhs = makenode(&source->tok, NULL); gettok(source, true); + if (flags & QCONST) { /* TODO(m21c): const - conversion */ } + break; + case KNOT: lhs = makenode(&source->tok, NULL); gettok(source, false); lhs->kind = OLNOT; lhs->lhs = expr(source, PRELAT); + break; + case KBREAK: case KCONTINUE: lhs = makenode(&source->tok, NULL); lhs->kind = getkind(source) == KBREAK ? ABREAK : ACONTINUE; gettok(source, true); + if (getkind(source) == ':') { gettok(source, false); skipnewline(source); @@ -2053,11 +2122,14 @@ atom(Source *source, int flags) { error(getloc(source), "expected identifier"); } } + break; + case KRETURN: lhs = makenode(&source->tok, NULL); gettok(source, true); lhs->kind = ARETURN; + if (getkind(source) == ':') { gettok(source, false); skipnewline(source); @@ -2068,16 +2140,20 @@ atom(Source *source, int flags) { error(getloc(source), "expected identifier"); } } + if (isatom(source)) lhs->rhs = exprlist(source, false, NULL); break; + case KDO: indent = source->lastindent; lhs = makenode(&source->tok, NULL); gettok(source, false); lhs->kind = ADO; lhs->lhs = stmtlist(source, indent, SSCOPE); + break; + case KLOOP: indent = source->lastindent; lhs = makenode(&source->tok, NULL); @@ -2090,10 +2166,12 @@ atom(Source *source, int flags) { gettok(source, false); lhs->u.payload = expr(source, POR); } + if (lhs->kind != ALOOP) goto joinelse; else break; + case KWHILE: indent = source->lastindent; lhs = makenode(&source->tok, NULL); @@ -2101,7 +2179,9 @@ atom(Source *source, int flags) { lhs->kind = AWHILE; lhs->u.payload = expr(source, POR); lhs->lhs = stmtlist(source, indent, SSCOPE); + goto joinelse; + case KIF: indent = source->lastindent; lhs = makenode(&source->tok, NULL); @@ -2109,15 +2189,19 @@ atom(Source *source, int flags) { lhs->kind = AIF; lhs->u.payload = expr(source, POR); skipnewline(source); + if (getkind(source) == 'I' && source->tok.u.key == auxthen) gettok(source, false); + lhs->lhs = stmtlist(source, indent, SSCOPE); joinelse: if (getkind(source) == KELSE && source->lastindent >= indent) { gettok(source, false); lhs->rhs = stmtlist(source, indent, SSCOPE); } + break; + default: joinerror: error(getloc(source), "expected expression"); @@ -2156,6 +2240,7 @@ atom(Source *source, int flags) { expect(source, ']', true, "expected ']'"); continue; } + gettok(source, true); } @@ -2206,7 +2291,9 @@ expr(Source *source, int minprec) { } else { last = lhs; } + break; + default: last = NULL; break; @@ -2307,6 +2394,7 @@ isinttype(Type *ty) { case TS32: case TU32: case TS64: case TU64: return true; + default: return false; } @@ -2317,6 +2405,7 @@ isfloattype(Type *ty) { switch (ty->kind) { case TF32: case TF64: return true; + default: return false; } @@ -2333,6 +2422,7 @@ isarithtype(Type *ty) { case TS64: case TU64: case TF32: case TF64: return true; + default: return false; } @@ -2345,6 +2435,7 @@ isunsignedtype(Type *ty) { case TU8: case TU16: case TU32: case TU64: return true; + default: return false; } @@ -2356,12 +2447,14 @@ maskint(int size, uint64_t value) { if (size == 1) return value & 0xfful; if (size == 2) return value & 0xfffful; if (size == 4) return value & 0xfffffffful; + return value; } double maskfloat(int size, double value) { if (size == 4) return (double) (float) value; + return value; } @@ -2371,6 +2464,7 @@ convint(int srcsize, bool srcsigned, uint64_t value) { if (srcsize == 1) return (uint64_t) (int8_t ) value; if (srcsize == 2) return (uint64_t) (int16_t) value; if (srcsize == 4) return (uint64_t) (int32_t) value; + return value; } @@ -2451,6 +2545,7 @@ autoref(Type *ty, Node *node) } else if (numderefs < -1) { error(&node->loc, "double referencing"); /* TODO(m21c): ERROR: double referencing */ + return node; } @@ -2477,6 +2572,7 @@ wrap(Type *ty, Node *node) { ty->size, node->u.d ); + } else if (isinttype(ty)) { node->u.u = maskint( ty->size, @@ -2492,6 +2588,7 @@ wrap(Type *ty, Node *node) { node->u.u ) ); + } else if (isinttype(ty)) { node->u.u = maskint( ty->size, @@ -2514,6 +2611,7 @@ wrap(Type *ty, Node *node) { node->kind = ACONV; node->type = ty; relinknodes(node, node->lhs); + return node; } @@ -2527,6 +2625,7 @@ conv(Node *node) { return wrap(prim + TINT, node); if (ty->kind == TUINFER) return wrap(prim + TUINT, node); + return autoref(NULL, node); } @@ -2734,6 +2833,7 @@ typecheck(Env *env, Node *expr) { case OASS: c->type = lhs->type; break; + case OMULA: case ODIVA: case OMODA: case OADDA: case OSUBA: if (isarithtype(lhs->type) && @@ -2748,7 +2848,9 @@ typecheck(Env *env, Node *expr) { c->type = prim + TERRTYPE; } + break; + case OLSHA: case ORSHA: case OARSHA: case OANDA: case OORA: case OXORA: @@ -2764,6 +2866,7 @@ typecheck(Env *env, Node *expr) { c->type = prim + TERRTYPE; } + break; } @@ -2774,6 +2877,7 @@ typecheck(Env *env, Node *expr) { case ADECL: if (c->lhs) c->lhs = wrap(c->type, typecheck(env, c->lhs)); + break; case ASCOPE: @@ -2789,6 +2893,7 @@ typecheck(Env *env, Node *expr) { assert(c->lhs); c->lhs = typecheck(env, c->lhs); c->lhs = conv(c->lhs); + break; default: @@ -2853,7 +2958,9 @@ foldexpr(Env *env, Node *expr) { ); } } while (0); + break; + case OADD: case OSUB: if (lhs->kind == 'N' && rhs->kind == 'N') { if (c->kind == OADD) evalbinary(+); @@ -2871,7 +2978,9 @@ foldexpr(Env *env, Node *expr) { *c = *lhs; /* delete(lhs); delete(rhs) */ } + break; + case OMUL: case ODIV: case OMOD: if (lhs->kind == 'N' && rhs->kind == 'N') { if (c->kind == OMUL) { @@ -2906,11 +3015,15 @@ foldexpr(Env *env, Node *expr) { *c = *lhs; /* delete(lhs); delete(rhs) */ } + break; + case OPLUS: *c = *lhs; + /* delete(lhs) */ break; + case OMINUS: if (lhs->kind == 'N') { if (isfloattype(ty)) { @@ -2926,7 +3039,9 @@ foldexpr(Env *env, Node *expr) { *c = *lhs->lhs; /* delete(lhs) */ } + break; + case OBAND: case OBOR: case OXOR: if (lhs->kind == 'N' && rhs->kind == 'N') { assert( @@ -2950,14 +3065,19 @@ foldexpr(Env *env, Node *expr) { c->kind = 'N'; c->u.u = maskint(ty->size, c->u.u); } + break; + case ACONV: /* TODO(m21c): implement this properly! */ lhs = foldexpr(env, lhs); if (lhs->type->kind == c->type->kind) *c = *lhs /*, delete(lhs) */; + + break; } } + return expr; } @@ -3023,41 +3143,53 @@ highlight(FILE *out, Highlight 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; + #if 0 case HLFUNCTIONDECL: n += fprintf(out, "\e[1;4;3m"); break; + case HLPARAMDECL: n += fprintf(out, "\e[4;3m"); break; + case HLDECL: n += fprintf(out, "\e[4m"); break; #endif + case HLINFO: n += fprintf(out, "\e[33m"); break; + case HLPROMPT: n += fprintf(out, "\e[35m"); break; @@ -3085,8 +3217,10 @@ printtype(FILE *out, Type *type, int indent) { n += printexpr(out, type->u.val, indent); n += fprintf(out, "]"); break; + #define typecase(type, str) \ case type: n += fprintf(out, str); break + typecase(TERRTYPE, "<error-type>"); typecase(TUNDEFINED, "<undefined-type>"); typecase(TPTR, "*"); @@ -3097,6 +3231,7 @@ printtype(FILE *out, Type *type, int indent) { typecase(TS32, "int" ); typecase(TU32, "uint" ); typecase(TS64, "s64" ); typecase(TU64, "u64" ); typecase(TF32, "float"); typecase(TF64, "double"); + #undef typecase default:; } @@ -3114,12 +3249,14 @@ printtypesuffix(FILE *out, Type *type, int indent) { switch (type->kind) { #define typecase(type, str) \ case type: n += fprintf(out, str); break + 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:; } @@ -3168,24 +3305,31 @@ printstring(FILE *out, Node *string) { case '\\': n += fprintf(out, "\\\\"); break; + case '\n': n += fprintf(out, "\\n"); break; + case '\r': n += fprintf(out, "\\r"); break; + case '\t': n += fprintf(out, "\\t"); break; + case '\"': n += fprintf(out, "\\\""); break; + case '\'': n += fprintf(out, "\\\'"); break; + case 0: n += fprintf(out, "\\0"); break; + default: putc(str[i], out); ++n; @@ -3305,11 +3449,13 @@ printexpr(FILE *out, Node *expr, int 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; + default: n += highlight(out, HLDELIM); n += fprintf(out, "%s", nodestrings[c->kind]); @@ -3324,6 +3470,7 @@ printexpr(FILE *out, Node *expr, int indent) { n += highlight(out, HLDELIM); putc(')', out), ++n; break; + default: n += highlight(out, HLDELIM); n += fprintf(out, "%s", nodestrings[c->kind]); @@ -3343,6 +3490,7 @@ printexpr(FILE *out, Node *expr, int indent) { 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 || @@ -3355,10 +3503,12 @@ printexpr(FILE *out, Node *expr, int indent) { n += fprintf(out, "%lu", c->u.u); n += printtypesuffix(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 : @@ -3366,22 +3516,27 @@ printexpr(FILE *out, Node *expr, int indent) { HLIDENT); n += fprintf(out, "%s", getstring(idents, c->u.declref->key)); break; + case ADECL: n += printdeclaration(out, c->u.declref, indent); break; + case ARETURN: n += highlight(out, HLKEYWORD); n += fprintf(out, "return "); 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 "); @@ -3397,18 +3552,23 @@ printexpr(FILE *out, Node *expr, int indent) { 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; + case ASTMT: n += printexpr(out, c->lhs, indent); break; + case ASCOPE: n += printexpr(out, c->lhs, indent); break; + case ACONV: n += highlight(out, HLDELIM); n += fprintf(out, "conv("); @@ -3418,6 +3578,7 @@ printexpr(FILE *out, Node *expr, int indent) { n += fprintf(out, ") "); n += printoperant(out, c->lhs, PUNARY, false, indent); break; + case AADDR: n += highlight(out, HLDELIM); n += fputs("&{", out); @@ -3425,6 +3586,7 @@ printexpr(FILE *out, Node *expr, int indent) { n += highlight(out, HLDELIM); n += fputs("}", out); break; + case ADEREF: n += highlight(out, HLDELIM); n += fputs("*{", out); @@ -3432,6 +3594,7 @@ printexpr(FILE *out, Node *expr, int indent) { n += highlight(out, HLDELIM); n += fputs("}", out); break; + default: break; }