diff options
| author | 2022-08-13 20:53:39 +0200 | |
|---|---|---|
| committer | 2022-08-13 20:53:39 +0200 | |
| commit | ddcca62a276c528a4390c8e3d58403b865f81869 (patch) | |
| tree | 3d563e173a18095501f61f3b30e39cf62b4ff521 | |
| parent | a4ddca68662f4bc0531763357b4bc00b6c50b456 (diff) | |
ok..
| -rwxr-xr-x | bootstrap/bootstrap.sh | 2 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 1 | ||||
| -rw-r--r-- | bootstrap/dump.c | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 4 | ||||
| -rw-r--r-- | bootstrap/types.c | 8 | ||||
| -rw-r--r-- | src/all.hff | 17 | ||||
| -rw-r--r-- | src/env.cff | 28 | ||||
| -rw-r--r-- | src/map.hff | 91 | ||||
| -rw-r--r-- | src/mem.hff | 23 | ||||
| -rw-r--r-- | src/parse.cff | 9 | ||||
| -rw-r--r-- | src/set.hff | 8 | ||||
| -rw-r--r-- | src/type.cff | 1 |
12 files changed, 169 insertions, 25 deletions
diff --git a/bootstrap/bootstrap.sh b/bootstrap/bootstrap.sh index 7ae3c09..c2fd41e 100755 --- a/bootstrap/bootstrap.sh +++ b/bootstrap/bootstrap.sh @@ -7,7 +7,7 @@ cd $(dirname "$0") if [ x"$CC" == x ]; then export CC=cc fi -export CFLAGS="-Wno-builtin-declaration-mismatch -g" +export CFLAGS="-Wno-builtin-declaration-mismatch -Wno-discarded-qualifiers -g" set -euo pipefail diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 8b7b710..5a1180d 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -585,6 +585,7 @@ liftdecl(struct decl *decl) { if (cache->args.d[i].typ) lifttype(cache->args.d[i].ty); } + lifttype(cache->ty); } default: break; diff --git a/bootstrap/dump.c b/bootstrap/dump.c index d4fe7e2..91832fd 100644 --- a/bootstrap/dump.c +++ b/bootstrap/dump.c @@ -54,7 +54,7 @@ pritype(const struct type *ty) { case TYeunion: kind = "tagged union"; agg: - epri("%s", ty->agg.name ? ty->agg.name : "(anonymous %s)", kind); + epri(ty->agg.name ? ty->agg.name : "(anonymous %s)", kind); if (ty->agg.tpargs.n) { epri("<"); int n = ty->agg.tpargs.n; diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 7a35f09..be32985 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -87,7 +87,7 @@ aissep(char c) { case '*': case '/': case '&': case '|': case '^': case '~': case '=': case '\'': case '"': case '<': case '>': case ':': - case '@': case '#': case '\\': + case '@': case '#': case '%': case '\\': case '`': return 1; return 0; @@ -2744,7 +2744,7 @@ aggdeclyield(struct decl *decl, void *arg) { if (decl->t == Dtype && decl->ty == a->aggty) ; - else if ((decl->t == Dfn && !decl->externp) || decl->t == Ddef) + else if ((decl->t == Dfn && !decl->externp) || decl->t == Ddef || decl->t == Dmacro) vec_push(a->decls, decl); else fatal(a->P, decl->span, "this kind of declaration is disallowed inside aggregates"); diff --git a/bootstrap/types.c b/bootstrap/types.c index 37977ea..289f69f 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -10,6 +10,7 @@ static struct { } **buckets; char *tags; } types; +static vec_t(const struct type *) typesvec; void inittypes() { @@ -163,6 +164,7 @@ interntype(struct type ty) { ty._id = id++; ty2 = typesput(&ty); assert(ty2); + vec_push(&typesvec, ty2); return ty2; } @@ -267,9 +269,9 @@ putprimtypes(struct env *env) { void visittypes(void (*visitor)(const struct type *, void *), void *arg) { - for (int i = 0; i < types.nbuckets; ++i) - for (struct typesnode *n = types.buckets[i]; n; n = n->next) - visitor(&n->ty, arg); + int i; const struct type *ty; + vec_foreach(&typesvec, ty, i) + visitor(ty, arg); } const struct type * diff --git a/src/all.hff b/src/all.hff index 63ca996..4ae3e26 100644 --- a/src/all.hff +++ b/src/all.hff @@ -1,3 +1,4 @@ +import "mem.hff"; import "libc.hff"; import "option.hff"; @@ -26,8 +27,6 @@ defmacro foreach(x, i, a, ...body) [ } ] -defmacro ALIGNUP(x,a) [ (((x) + ((a) - 1)) & -(a)) ] - defmacro streq(a,b) [ (strcmp(a,b) == 0) ] /// Types @@ -35,6 +34,7 @@ defmacro streq(a,b) [ (strcmp(a,b) == 0) ] struct Type; struct Decl; struct Expr; +struct Env; struct Loc { fileid i16, @@ -103,13 +103,22 @@ struct Type { struct Parser { fp *FILE, + alloc *Allocator, curfile *const u8, tokloc Loc, curloc Loc, eof bool, peekchr Option<int>, peektok Option<Tok>, +} + +struct Decl { + name *const u8, +} +struct DeclList { + link *DeclList, + decl Decl, } struct Targ { @@ -150,6 +159,10 @@ extern fn efmt(fmt *const u8, ...) void; // type.cff +// env.cff +extern fn mkenv(parent *Env, alloc *Allocator) *Env; +extern fn envput(*Env, *const Decl) *Decl; + // targ.cff extern static g_targ *const Targ; extern fn targ_ini(name *const u8) bool; diff --git a/src/env.cff b/src/env.cff new file mode 100644 index 0000000..8878238 --- /dev/null +++ b/src/env.cff @@ -0,0 +1,28 @@ +import "map.hff"; +import "all.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 envput(env *Env, decl *const Decl) *Decl { + let l **DeclList = env.decls->get_slot(decl.name); + let n *DeclList = env.alloc->alloc(sizeof *DeclList); + n.link = *l; + n.decl = *decl; + *l = n; + return &n.decl; +} diff --git a/src/map.hff b/src/map.hff new file mode 100644 index 0000000..d8bbf52 --- /dev/null +++ b/src/map.hff @@ -0,0 +1,91 @@ +import "all.hff"; + +// KTraits: +// :hash(K) u32 +// :eq(T, T) bool +struct Map<K, V, KTraits> { + keys *K, + vals *V, + bitmap *u8, + N int, + count int, + + fn _iempty(self *Map, i int) bool { + return (self.bitmap[i/8] & (1 << (i%8))) == 0; + } + + fn get(self *Map, key K) *V { + if self.N == 0 { + return #null; + } + let i0 u32 = KTraits:hash(key); + let i = i0 & (self.N - 1); + do { + if self->_iempty(i) { + return #null; + } else if KTraits:eq(self.keys[i], key) { + return &self.vals[i]; + } + i = (i + 1) & (self.N - 1); + } while i != i0; + assert(#f, "unreachable"); + } + + fn put(self *Map, key K, val V) void { + if self.keys == #null { + assert(self.vals == #null and self.bitmap == #null and self.N == 0 and self.count == 0, + "?"); + self.keys = xcalloc(self.N = 16, sizeof K); + self.vals = xcalloc(self.N, sizeof V); + self.bitmap = xcalloc(self.N / 8, 1); + } + + if self.count == self.N / 2 { + // rehash + } + let i0 u32 = KTraits:hash(key); + let i = i0 & (self.N - 1); + do { + if self->_iempty(i) { + self.bitmap[i/8] |= (1 << (i%8)); + ++self.count; + self.vals[i] = val; + return; + } else if KTraits:eq(self.keys[i], key) { + self.vals[i] = val; + return; + } + i = (i + 1) & (self.N - 1); + } while i != i0; + assert(#f, "unreachable"); + } + + fn get_slot(self *Map, key K) *V { + if self.keys == #null { + assert(self.vals == #null and self.bitmap == #null and self.N == 0 and self.count == 0, + "?"); + self.keys = xcalloc(self.N = 16, sizeof K); + self.vals = xcalloc(self.N, sizeof V); + self.bitmap = xcalloc(self.N / 8, 1); + } + + if self.count == self.N / 2 { + // rehash + } + let i0 u32 = KTraits:hash(key); + let i = i0 & (self.N - 1); + do { + if self->_iempty(i) { + self.bitmap[i/8] |= (1 << (i%8)); + ++self.count; + self.vals[i] = {}; + return &self.vals[i]; + } else if KTraits:eq(self.keys[i], key) { + return &self.vals[i]; + } + i = (i + 1) & (self.N - 1); + } while i != i0; + assert(#f, "unreachable"); + } + +} diff --git a/src/mem.hff b/src/mem.hff index 9fee910..84064f3 100644 --- a/src/mem.hff +++ b/src/mem.hff @@ -1,6 +1,11 @@ +import "libc.hff"; import "all.hff"; def ARENA_SIZE = 16 * 1024; +defmacro ALIGNUP(x,a) [ (((x) + ((a) - 1)) & -(a)) ] +extern fn xmalloc(n usize) *void; +extern fn xcalloc(n usize, m usize) *void; +extern fn xrealloc(p *void, n usize) *void; struct ArenaRegion { prev *ArenaRegion, @@ -24,28 +29,18 @@ struct Arena { a.r.idx += n; return ptr; } else { - let rp = xmalloc(sizeof ArenaRegion); - *rp = a.r; + let rp *ArenaRegion = xmalloc(sizeof ArenaRegion); + *rp = *a.r; let r = ArenaRegion { .prev: rp }; return allocf(a, n); } } } -struct Mallocator { - fn allocf(*void, n usize) *void { - return xmalloc(n); - } - - fn freef(*void, ptr *void) void { - free(ptr); - } -} - struct Allocator { a *void, - allocf *fn(a *void, n usize) *void, - freef *fn(a *void, ptr *void) void, + allocf *fn(*void, usize) *void, + freef *fn(*void, *void) void, fn alloc(self *Allocator, n usize) *void { if self.allocf { diff --git a/src/parse.cff b/src/parse.cff index ef01da5..ba8e35d 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -415,6 +415,15 @@ fn lex(P *Parser) Tok { } extern fn parse(P *Parser) [#]Decl { + fn mallocator_allocf(*void, n usize) *void { + return xmalloc(n); + } + + fn mallocator_freef(*void, ptr *void) void { + free(ptr); + } + + let alloc = Allocator { #null, &mallocator_allocf, &mallocator_freef }; while not P.eof { let tok = lex(P); if tok.t == :eof { break; } diff --git a/src/set.hff b/src/set.hff index 955eac3..28e67be 100644 --- a/src/set.hff +++ b/src/set.hff @@ -1,6 +1,10 @@ import "vec.hff"; import "all.hff"; +// KTraits: +// :hash(K) u32 +// :eq(T, T) bool +// :dup(T) T struct Set<T, Traits> { buf Vec<T>, set **const T, @@ -27,7 +31,7 @@ struct Set<T, Traits> { ) } - let i0 = Traits:hash(x) & (self.N - 1); + let i0 u32 = Traits:hash(x) & (self.N - 1); let i int = i0; do { if self.set[i] == #null { @@ -43,7 +47,7 @@ struct Set<T, Traits> { } fn contains(self *Set, x T) bool { - let i0 = Traits:hash(x) & (self.N - 1); + let i0 u32 = Traits:hash(x) & (self.N - 1); let i int = i0; do { if self.set[i] == #null { diff --git a/src/type.cff b/src/type.cff index bd56503..a6987b7 100644 --- a/src/type.cff +++ b/src/type.cff @@ -3,6 +3,7 @@ import "all.hff"; fn hashtype(ty *const Type) u32 { let h = FNV1A_INI; h = fnv1a_i(h, ty.konst ? 1 : 0); + switch ty.u { case Void; case Bool; |