aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-07 17:57:22 +0200
committerlemon <lsof@mailbox.org>2022-08-07 17:57:22 +0200
commit9460f9f14dd68eb59d36f758272be936300a0440 (patch)
treefbc50be52e28c1ad3cc05da58f9d5d4c315d4711 /bootstrap
parent855834ed40250f35fe5de5e304173ec69059e2fc (diff)
fix template accessing future environment
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h6
-rw-r--r--bootstrap/env.c16
-rw-r--r--bootstrap/parse.c19
-rw-r--r--bootstrap/test2.cff8
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, &params);
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<T> {
}
}
+def X = 7 + 2;
+
struct Bit<T> {
- 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<int> = {#null, 0};