diff options
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 2 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 11 | ||||
| -rw-r--r-- | bootstrap/dump.c | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 227 | ||||
| -rw-r--r-- | bootstrap/test.cff | 7 |
5 files changed, 159 insertions, 90 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 3048d99..33ac7e7 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -355,7 +355,7 @@ struct stmt { struct stmt *f; } ifelse; struct { - struct stmt *ini; + slice_t(struct stmt) ini; struct expr test; struct expr *next; struct blockstmt body; diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index b4cea42..9e13e12 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -295,14 +295,16 @@ genstmt(struct stmt *stmt) { genblock(stmt->loop.body); break; case Sfor: - pri("for (\n"); - if (stmt->loop.ini) - genstmt(stmt->loop.ini); + pri("{\n"); + for (int i = 0; i < stmt->loop.ini.n; ++i) + genstmt(&stmt->loop.ini.d[i]); + pri("for (; "); pri("%e;", &stmt->loop.test); if (stmt->loop.next) pri(" %e", stmt->loop.next); pri(")"); genblock(stmt->loop.body); + pri("}\n"); break; case Siswitch: pri("switch (%e) {", &stmt->iswitch.test); @@ -434,7 +436,8 @@ liftnested(struct stmt *stmt) { liftnested(blocktostmt(stmt->loop.body)); break; case Sfor: - liftnested(stmt->loop.ini); + for (int i = 0; i < stmt->loop.ini.n; ++i) + liftnested(&stmt->loop.ini.d[i]); liftnestedex(&stmt->loop.test); liftnestedex(stmt->loop.next); liftnested(blocktostmt(stmt->loop.body)); diff --git a/bootstrap/dump.c b/bootstrap/dump.c index 5d83503..12a5a2a 100644 --- a/bootstrap/dump.c +++ b/bootstrap/dump.c @@ -323,6 +323,7 @@ dumpstmt(const struct stmt *stmt, int ws) { break; case Sfor: epri("%wfor \n", ws); + /* if (stmt->loop.ini) dumpstmt(stmt->loop.ini, ws + 1); epri("%w; %e; ", ws + 1, &stmt->loop.test); @@ -330,6 +331,7 @@ dumpstmt(const struct stmt *stmt, int ws) { epri("%e", stmt->loop.next); epri("\n"); dumpblock(&stmt->loop.body, ws + 1); + */ break; case Siswitch: epri("%wswitch %e {\n", ws, &stmt->iswitch.test); diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 3f854d7..32cd202 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -1366,64 +1366,93 @@ stmtdup(struct stmt st) { return memcpy(xmalloc(sizeof st), &st, sizeof st); } +typedef void (*decl_yielder_t)(struct decl *, void *); +static void parsedecl(decl_yielder_t, void *, struct parser *, bool toplevel); + static void -parsevardecl(struct parser *P, struct decl *decl) { +parsevardecl(decl_yielder_t yield, void *yarg, struct parser *P) { struct tok tok; - const char *name; - const struct type *ty = NULL; - struct expr *ini = NULL; - bool konst = 0; - static int id; + + do { + struct decl decl = {0}; + const char *name; + const struct type *ty = NULL; + struct expr *ini = NULL; + bool konst = 0; + static int id; - if (lexmatch(P, NULL, TKkw_const)) - konst = 1; + if (lexmatch(P, NULL, TKkw_const)) + konst = 1; - tok = lexexpect(P, TKident); - name = tok.str; + tok = lexexpect(P, TKident); + name = tok.str; - if (lexmatch(P, NULL, '=')) { - ini = exprdup(parseexpr(P)); - ty = ini->ty; - } else { - ty = parsetype(P); if (lexmatch(P, NULL, '=')) { - P->targty = ty; ini = exprdup(parseexpr(P)); - } else if (decl->t == Dlet) { - fatal(P, tok.span, "variable %T must be initialized", tok); + ty = ini->ty; + } else { + ty = parsetype(P); + if (lexmatch(P, NULL, '=')) { + P->targty = ty; + ini = exprdup(parseexpr(P)); + } else if (decl.t == Dlet) { + fatal(P, tok.span, "variable %T must be initialized", tok); + } } - } - // TODO static initialzier constants are a superset of folded constants - // if (ini && decl->t == Dstatic && !fold(ini)) - // fatal(P, ini->span, "static initializer isn't constant"); + // TODO static initialzier constants are a superset of folded constants + // if (ini && decl.t == Dstatic && !fold(ini)) + // fatal(P, ini->span, "static initializer isn't constant"); + + if (ini && !typeof2(ty, ini->ty)) + fatal(P, tok.span, "incompatible initializer type (%t, expected %t)", + ini->ty, ty); - if (ini && !typeof2(ty, ini->ty)) - fatal(P, tok.span, "incompatible initializer type (%t, expected %t)", - ini->ty, ty); + if (!completetype(ty)) + fatal(P, tok.span, "let `%s': variable type %t is incomplete", + name, ty); + + if (konst) + ty = constify(ty); + + assert(ty); + decl.name = name; + decl.var.ty = ty; + decl.var.ini = ini; + decl.var.id = id++; + decl.var.fnid = P->curfn ? P->curfn->id : -1; + yield(&decl, yarg); + if (!lexmatch(P, &tok, ',')) { + lexexpect(P, ';'); + break; + } + } while (!lexmatch(P, &tok, ';')); +} - if (!completetype(ty)) - fatal(P, tok.span, "let `%s': variable type %t is incomplete", - name, ty); +typedef void (*stmt_yielder_t)(struct stmt *, void *); - if (konst) - ty = constify(ty); +struct letstmtyarg { + struct parser *P; + void *stmt_yarg; + stmt_yielder_t yield; +}; - assert(ty); - decl->name = name; - decl->var.ty = ty; - decl->var.ini = ini; - decl->var.id = id++; - decl->var.fnid = P->curfn ? P->curfn->id : -1; +static void +letstmtyield(struct decl *decl, void *arg) { + struct letstmtyarg *a = arg; + struct stmt st = { Sdecl }; + decl->t = Dlet; + putdecl(a->P, decl->span, decl); + st.decl = *decl; + a->yield(&st, a->stmt_yarg); } -static struct stmt -pstlet(struct parser *P) { - struct stmt st = {Sdecl}; - st.decl.t = Dlet; - parsevardecl(P, &st.decl); - putdecl(P, st.decl.span, &st.decl); - return st; +static void +pstlet(stmt_yielder_t yield, void *yarg, struct parser *P) { + struct letstmtyarg arg = { + P, yarg, yield + }; + parsevardecl(letstmtyield, &arg, P); } static struct stmt @@ -1449,20 +1478,28 @@ pstifelse(struct parser *P) { return st; } +static void +pstforletyield(struct stmt *st, void *arg) { + vec_t(struct stmt) *sts = arg; + vec_push(sts, *st); +} + static struct stmt pstfor(struct parser *P) { struct stmt st = {Sfor}; struct tok tok; if (lexmatch(P, NULL, TKkw_let)) { - st.loop.ini = stmtdup(pstlet(P)); - lexexpect(P, ';'); + vec_t(struct stmt) sts = {0}; + pstlet(pstforletyield, &sts, P); + vec_slice_cpy(&st.loop.ini, &sts); } else if (lexmatch(P, NULL, ';')) { // pass } else { - st.loop.ini = stmtdup((struct stmt) { + st.loop.ini.d = stmtdup((struct stmt) { Sexpr, .expr = parseexpr(P) }); + st.loop.ini.n = 1; lexexpect(P, ';'); } @@ -1487,7 +1524,7 @@ pstfor(struct parser *P) { return st; } -static struct stmt parsestmt(struct parser *P); +static void parsestmt(stmt_yielder_t yield, void *yarg, struct parser *P); static struct stmt pstiswitch(struct parser *P, const struct expr *test) { @@ -1552,9 +1589,6 @@ pstswitch(struct parser *P) { } } -typedef void (*decl_yielder_t)(const struct decl *, void *); -static void parsedecl(decl_yielder_t, void *, struct parser *, bool toplevel); - static bool isdecltokt(int tokt) { switch (tokt) @@ -1664,13 +1698,25 @@ ok: } static void -yieldstdecl(const struct decl *d0, void *arg) { +yieldstdecl(struct decl *d0, void *arg) { struct decl *decl = arg; *decl = *d0; } -static struct stmt -parsestmt(struct parser *P) { +struct stmtletyarg { + stmt_yielder_t yield; + void *yarg; +}; + +static void +stmtletyield(struct stmt *stmt, void *arg) { + struct stmtletyarg *a = arg; + stmt->t = Sdecl; + a->yield(stmt, a->yarg); +} + +static void +parsestmt(stmt_yielder_t yield, void *yarg, struct parser *P) { struct stmt st = {0}; struct tok tok; @@ -1678,9 +1724,8 @@ parsestmt(struct parser *P) { st.span = tok.span; st = parseblock(P); } else if (lexmatch(P, &tok, TKkw_let)) { - st = pstlet(P); - st.span = tok.span; - lexexpect(P, ';'); + pstlet(stmtletyield, &(struct stmtletyarg) { yield, yarg }, P); + return; } else if (lexmatch(P, &tok, TKkw_if)) { st.span = tok.span; st = pstifelse(P); @@ -1737,7 +1782,7 @@ parsestmt(struct parser *P) { if ((decl = finddecl(P, tok.str)) && decl->t == Dmacro) { lex(P); parseexpandmacro(P, &decl->macro); - return parsestmt(P); + return parsestmt(yield, yarg, P); } } @@ -1747,7 +1792,13 @@ parsestmt(struct parser *P) { st.t = Sexpr; st.expr = ex; } - return st; + yield(&st, yarg); +} + +static void +parseblockstyield(struct stmt *st, void *arg) { + vec_t(struct stmt) *stmts = arg; + vec_push(stmts, *st); } static struct blockstmt @@ -1761,7 +1812,7 @@ parseblock0(struct parser *P) { while ((tokt = lexpeek(P).t) != '}' && tokt != TKkw_case && tokt != ')') { if (lexmatch(P, NULL, ';')) continue; - vec_push(&stmts, parsestmt(P)); + parsestmt(parseblockstyield, &stmts, P); } vec_slice_cpy(&block.stmts, &stmts); @@ -2083,13 +2134,40 @@ doimport(struct parser *P, const char *path) { rpath = xstrdup(rpath); vec_push(&seen, rpath); - P2.primenv = P->primenv; + // P2.primenv = P->primenv; initparser(&P2, path); P2.is_header = 1; parse(&cf, &P2); return cf; } +struct staticvaryarg { + struct parser *P; + bool externp, toplevel; + struct span espan; + decl_yielder_t yield; + void *yarg; +}; + +static void +staticvaryield(struct decl *decl, void *arg) { + struct staticvaryarg *a = arg; + decl->t = Dstatic; + decl->externp = a->externp; + decl->_cname = xcalloc(1, sizeof (char *)); + decl->span = a->espan; + if (!a->toplevel && !a->externp && !decl->var.ini) + fatal(a->P, decl->span, + "static variable inside function cannot be forward-declared"); + if (!a->toplevel && a->externp && decl->var.ini) + fatal(a->P, decl->span, + "extern static variable inside function cannot be initialized"); + if (a->P->is_header && a->externp && decl->var.ini) + fatal(a->P, decl->span, + "cannot define extern variable in header"); + a->yield(decl, a->yarg); +} + static void parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { struct tok tok = { .span = P->tokspan }; @@ -2114,21 +2192,10 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { fatal(P, decl.span, "cannot define extern function in header"); } else if (lexmatch(P, &tok, TKkw_static)) { - decl.t = Dstatic; - decl.externp = externp; - decl._cname = xcalloc(1, sizeof (char *)); - decl.span = tok.span; - parsevardecl(P, &decl); - if (!toplevel && !externp && !decl.var.ini) - fatal(P, decl.span, - "static variable inside function cannot be forward-declared"); - if (!toplevel && externp && decl.var.ini) - fatal(P, decl.span, - "extern static variable inside function cannot be initialized"); - if (P->is_header && externp && decl.var.ini) - fatal(P, decl.span, - "cannot define extern variable in header"); - lexexpect(P, ';'); + parsevardecl(staticvaryield, &(struct staticvaryarg) { + P, externp, toplevel, tok.span, yield, yarg + }, P); + return; } else if (lexmatch(P, &tok, TKkw_typedef)) { if (externp) fatal(P, tok.span, "typedef cannot be `extern'"); decl.t = Dtype; @@ -2195,7 +2262,7 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { } static void -yieldexdecl(const struct decl *decl, void *arg) { +yieldexdecl(struct decl *decl, void *arg) { vec_t(struct decl) *decls = arg; vec_push(decls, *decl); } @@ -2210,18 +2277,14 @@ parse(struct comfile *cf, struct parser *P) { void initparser(struct parser *P, const char *fname) { - struct env *primenv = P->primenv; assert(NUM_KEYWORDS - 1 < '!'); memset(P, 0, sizeof *P); - P->primenv = primenv; P->curfile = fname; if (!(P->fp = fopen(fname, "r"))) perror(fname), exit(1); P->tokspan = P->curspan = (struct span) { addfilepath(fname), 0, 1, 1 }; P->peekchr = -1; P->curenv = P->tlenv = xcalloc(1, sizeof *P->tlenv); - if (!P->primenv) { - P->primenv = xcalloc(1, sizeof *P->primenv); - putprimtypes(P->primenv); - } + P->primenv = xcalloc(1, sizeof *P->primenv); + putprimtypes(P->primenv); } diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 5e74cf1..46e3b8c 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -17,12 +17,13 @@ enum Color { Red, Green, Blue } -static xs *void = {}; +static xs *void = {}, + ok = 6; fn isort(xs *int, n usize) void { fn icmp(lhs *const void, rhs *const void, _ *void) int { - let lhs = *as(*int)lhs; - let rhs = *as(*int)rhs; + let lhs = *as(*int)lhs, + rhs = *as(*int)rhs; return lhs - rhs; } qsort(xs, n, 4, &icmp); |