aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-13 20:53:39 +0200
committerlemon <lsof@mailbox.org>2022-08-13 20:53:39 +0200
commitddcca62a276c528a4390c8e3d58403b865f81869 (patch)
tree3d563e173a18095501f61f3b30e39cf62b4ff521
parenta4ddca68662f4bc0531763357b4bc00b6c50b456 (diff)
ok..
-rwxr-xr-xbootstrap/bootstrap.sh2
-rw-r--r--bootstrap/cgen.c1
-rw-r--r--bootstrap/dump.c2
-rw-r--r--bootstrap/parse.c4
-rw-r--r--bootstrap/types.c8
-rw-r--r--src/all.hff17
-rw-r--r--src/env.cff28
-rw-r--r--src/map.hff91
-rw-r--r--src/mem.hff23
-rw-r--r--src/parse.cff9
-rw-r--r--src/set.hff8
-rw-r--r--src/type.cff1
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;