From 9460f9f14dd68eb59d36f758272be936300a0440 Mon Sep 17 00:00:00 2001 From: lemon Date: Sun, 7 Aug 2022 17:57:22 +0200 Subject: fix template accessing future environment --- bootstrap/all.h | 6 +++++- bootstrap/env.c | 16 ++++++++++++---- bootstrap/parse.c | 19 ++++++++++++++----- bootstrap/test2.cff | 8 +++++--- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/bootstrap/all.h b/bootstrap/all.h index 5302a07..fb6bfe6 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -134,6 +134,8 @@ struct parser { const struct type *targty; bool used_targty; bool is_header; + bool save_envage; + int envage; }; enum typetype { @@ -262,8 +264,10 @@ struct decl { const struct type *ty; } *cache; struct toktree toks; + int envage; } tepl; }; + int age; }; struct teplparam { @@ -528,7 +532,7 @@ bool isnumtype(const struct type *a); const struct type *typeof2(const struct type *a, const struct type *b); /** env.c **/ -struct decl *envfind(const struct env *, const char *name); +struct decl *envfind(const struct env *, int age, const char *name); struct decl *envput(struct env *, const struct decl *decl); struct env *mkenv(const struct env *parent); diff --git a/bootstrap/env.c b/bootstrap/env.c index ddd06b2..b3652fa 100644 --- a/bootstrap/env.c +++ b/bootstrap/env.c @@ -2,14 +2,19 @@ struct decl * -envfind(const struct env *env, const char *name) { +envfind(const struct env *env, int age, const char *name) { + int eage = INT_MAX; + +again: if (!env) return NULL; for (struct decls *decls = env->decls; decls; decls = decls->next) { - if (!strcmp(decls->decl.name, name)) + if (eage >= decls->decl.age && !strcmp(decls->decl.name, name)) return &decls->decl; } - return envfind(env->parent, name); + env = env->parent; + eage = env && env->parent ? eage : age; + goto again; } static bool @@ -24,7 +29,9 @@ envput(struct env *env, const struct decl *decl) { .decls = env->decls }; struct decl *d0; - if ((d0 = envfind(&env_noparent, decl->name))) { + static int age; + + if ((d0 = envfind(&env_noparent, INT_MAX, decl->name))) { // modify existing forward declarations? for (int kind = TYstruct; kind <= TYunion; ++kind) { if (d0->t == Dtype && d0->ty->t == kind @@ -58,6 +65,7 @@ envput(struct env *env, const struct decl *decl) { decls = xcalloc(1, sizeof *decls); decls->next = env->decls; decls->decl = *decl; + decls->decl.age = age++; env->decls = decls; return &decls->decl; } diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 7b2e007..99560d8 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -539,20 +539,22 @@ popenv(struct parser *P) { static struct decl * putdecl(struct parser *P, struct span espan, const struct decl *decl) { struct decl *ret; - if (envfind(P->primenv, decl->name)) + if (envfind(P->primenv, INT_MAX, decl->name)) fatal(P, espan, "cannot shadow primitive `%s'", decl->name); if (!(ret = envput(P->curenv, decl))) fatal(P, decl->span, "cannot shadow earlier incompatible declaration of `%s'", decl->name); + if (!P->save_envage) + P->envage = MAX(P->envage, ret->age); return ret; } static const struct decl * finddecl(struct parser *P, const char *name) { const struct decl *decl; - if ((decl = envfind(P->primenv, name))) + if ((decl = envfind(P->primenv, INT_MAX, name))) return decl; - return envfind(P->curenv, name); + return envfind(P->curenv, P->envage, name); } static struct expr parseexpr(struct parser *P); @@ -684,6 +686,7 @@ parseexpandtepl(struct parser *P, struct tepl *tepl) { } struct env env = { tepl->env }; + WITH_TMPCHANGE(struct env *, P->curenv, &env) { struct decl *decl; expan.args.d = args; @@ -691,8 +694,11 @@ parseexpandtepl(struct parser *P, struct tepl *tepl) { expan.toks = tepl->toks; ++P->expanno; P->curexpan = memcpy(xmalloc(sizeof expan), &expan, sizeof expan); - ty = parseagg(P, tepl->name, tepl->tkind, &decl); + WITH_TMPCHANGE(int, P->envage, tepl->envage) + WITH_TMPCHANGE(int, P->save_envage, 1) + ty = parseagg(P, tepl->name, tepl->tkind, &decl); } + free(env.decls); memcpy(&((struct type *)ty)->agg.tpargs, &tpargs, sizeof tpargs); cache = xcalloc(sizeof *cache, 1); cache->next = tepl->cache; @@ -2443,7 +2449,7 @@ parseagg(struct parser *P, const char *name, int kind, struct decl **retdecl) { int iid; struct env env_noparent = *P->curenv; env_noparent.parent = NULL; - struct decl *decl = (struct decl *)envfind(&env_noparent, name); + struct decl *decl = (struct decl *)envfind(&env_noparent, P->envage, name); if (decl && decl->ty->t == kind) iid = decl->ty->agg.id; else @@ -2586,6 +2592,7 @@ parseaggtepl(struct parser *P, int kind, const char *name) { } tepl.env = P->curenv; + tepl.envage = P->envage; vec_slice_cpy(&tepl.params, ¶ms); vec_slice_cpy(&tepl.toks, &toks); return tepl; @@ -2705,6 +2712,8 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { decl.t = Dtype; decl.ty = parseagg(P, decl.name, kind, &decl2); } else { + if (!toplevel) + fatal(P, tok.span, "template definition inside function"); decl.t = Dtepl; decl.tepl = parseaggtepl(P, kind, decl.name); } diff --git a/bootstrap/test2.cff b/bootstrap/test2.cff index 3532f4a..356312c 100644 --- a/bootstrap/test2.cff +++ b/bootstrap/test2.cff @@ -8,12 +8,14 @@ struct Node { } } +def X = 7 + 2; + struct Bit { - fn neg(x T) T { return ~x; } + fn neg(x T) T { return ~x + X; } + !fn neg(x T) T { return ~x + Y; } } -def X = 7 + 2, - Y = 3.3; +def Y = 3.3; extern fn main() void { let n Node = {#null, 0}; -- cgit v1.2.3