aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/env.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
committerlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
commit1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (patch)
treebc5f24811413749b776964c1bbdec13a46dd9768 /bootstrap/env.c
initial
Diffstat (limited to 'bootstrap/env.c')
-rw-r--r--bootstrap/env.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/bootstrap/env.c b/bootstrap/env.c
new file mode 100644
index 0000000..513b4d9
--- /dev/null
+++ b/bootstrap/env.c
@@ -0,0 +1,48 @@
+#include "all.h"
+
+
+struct decl *
+envfind(const struct env *env, const char *name) {
+ if (!env)
+ return NULL;
+ for (struct decls *decls = env->decls; decls; decls = decls->next) {
+ if (!strcmp(decls->decl.name, name))
+ return &decls->decl;
+ }
+ return envfind(env->parent, name);
+}
+
+static bool
+declsshadowable(const struct decl *a, const struct decl *b) {
+ return b->t == Dvar;
+}
+
+static bool
+declscompatible(const struct decl *a, const struct decl *b) {
+ if (a->t != b->t)
+ return 0;
+ if (a->t == Dfn && a->fn.selfty == b->fn.selfty && !a->fn.body)
+ return 1;
+ if (a->t == Dtype && a->ty == b->ty)
+ return 1;
+ return 0;
+}
+
+bool
+envput(struct env *env, const struct decl *decl) {
+ struct decls *decls;
+ struct env env_noparent = {
+ .decls = env->decls
+ };
+ struct decl *decl0;
+ if ((decl0 = envfind(&env_noparent, decl->name))) {
+ if (!declsshadowable(decl0, decl) && !declscompatible(decl0, decl))
+ return 0;
+ }
+
+ decls = xcalloc(1, sizeof *decls);
+ decls->next = env->decls;
+ decls->decl = *decl;
+ env->decls = decls;
+ return 1;
+}