1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import "cffc.hff";
import "map.hff";
import "util.hff";
import "common.hff";
struct StringKeyTraits {
fn hash(s *const u8) u32 { return fnv1a_s(FNV1A_INI, s); }
fn eq(a *const u8, b *const u8) bool { return streq(a, b); }
}
struct Env {
parent *Env,
alloc *Allocator,
decls Map<*const u8, *DeclList, StringKeyTraits>,
}
extern fn mkenv(parent *Env, alloc *Allocator) *Env {
let env *Env = xmalloc(sizeof Env);
*env = { parent, alloc };
return env;
}
extern fn envparent(env *Env) *Env {
return env.parent;
}
extern fn envput(env *Env, decl Decl, old **const Decl) *Decl {
let l **DeclList = env.decls->get_slot(decl.name);
let n *DeclList = anew(env.alloc, DeclList);
if *l { // decl with this name exists
*old = &(*l).decl;
return #null;
}
n.link = *l;
n.decl = decl;
*l = n;
return &n.decl;
}
extern fn envfind(env *Env, name *const u8) *Decl {
let l **DeclList = env.decls->get(name);
if l == #null {
if env.parent == #null {
return #null;
}
return envfind(env.parent, name);
}
let l = *l;
assert(l != #null, "l?");
return &l.decl;
}
extern fn envfind_noparent(env *Env, name *const u8) *Decl {
let l **DeclList = env.decls->get(name);
return l ? &(*l).decl : #null;
}
extern fn envfree(env *Env) void {
env.decls->clear();
free(env);
}
|