hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit e2d0cd2b3cd312619c29f09ecabee8994e4e4e35
parent 4665cbeee798723f124b45a9814deb055fb06e85
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 30 Apr 2021 09:38:58 -0400

hare::types: refactor type hashmap

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Ahare/types/+test.ha | 35+++++++++++++++++++++++++++++++++++
Mhare/types/store.ha | 47++++++++++++++++++++++++++++-------------------
Mhare/types/types.ha | 1+
Mscripts/gen-stdlib | 14++++++++++++--
Mstdlib.mk | 3++-
5 files changed, 78 insertions(+), 22 deletions(-)

diff --git a/hare/types/+test.ha b/hare/types/+test.ha @@ -0,0 +1,35 @@ +use bufio; +use hare::ast; +use hare::lex; +use hare::parse; +use io; +use strings; + +fn parse_type(in: str) ast::_type = { + let buf = bufio::fixed(strings::toutf8(in), io::mode::READ); + defer io::close(buf); + let lex = lex::init(buf, "<test>"); + return parse::_type(&lex)!; +}; + +@test fn store() void = { + let st = store(x86_64, null, null); + defer store_free(st); + + let atype = parse_type("int"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype._type is builtin); + assert(htype._type as builtin == builtin::INT); + assert(htype.sz == x86_64._int && htype.align == x86_64._int); + + let type2 = lookup(st, &atype)!; + assert(htype == type2, "types should be singletons"); + + let atype = parse_type("*int"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == x86_64._pointer && htype.align == x86_64._pointer); + let htype = htype._type as pointer; + assert(htype.referent._type as builtin == builtin::INT); +}; diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -13,17 +13,18 @@ export type resolver = fn( export type typestore = struct { arch: arch, - map: [BUCKETS][]struct { - hash: u32, - _type: _type, - }, - resolve: *resolver, - rstate: *void, + map: [BUCKETS][]_type, + resolve: nullable *resolver, + rstate: nullable *void, }; // Initializes a new type store. Optionally, provide a function which // type-checks and evaluates an [[ast::expr]]. -export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = { +export fn store( + arch: arch, + resolver: nullable *resolver, + rstate: nullable *void, +) *typestore = { return alloc(typestore { arch = arch, resolve = resolver, @@ -32,6 +33,16 @@ export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = { }); }; +export fn store_free(store: *typestore) void = { + for (let i = 0z; i < len(store.map); i += 1) { + for (let j = 0z; j < len(store.map[i]); j += 1) { + type_finish(&store.map[i][j]); + }; + free(store.map[i]); + }; + free(store); +}; + // Returned from [[lookup]] when we are unable to resolve this type, but it does // not necessarily have an error. This occurs when a type includes an unknown // forward reference. @@ -47,23 +58,21 @@ export type error = (noresolver | errors::opaque)!; // Retrieves a [[_type]] for a given [[ast::_type]]. export fn lookup( store: *typestore, - t: *ast::_type, + ty: *ast::_type, ) (const *_type | deferred | error) = { - const t = fromast(store, t)?; - const h = hash(&t); - let bucket = &store.map[h % BUCKETS]; + const ty = fromast(store, ty)?; + const id = hash(&ty); + let bucket = &store.map[id % BUCKETS]; // XXX: Should not have to dereference bucket for (let i = 0z; i < len(*bucket); i += 1) { - if (bucket[i].hash == h) { - type_finish(&t); - return &bucket[i]._type; + if (bucket[i].id == id) { + type_finish(&ty); + return &bucket[i]; }; }; - append(*bucket, struct { - hash: u32 = h, - _type: _type = t, - }); - return &bucket[len(*bucket) - 1]._type; + ty.id = id; + append(*bucket, ty); + return &bucket[len(*bucket) - 1]; }; fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { diff --git a/hare/types/types.ha b/hare/types/types.ha @@ -43,6 +43,7 @@ export def SIZE_UNDEFINED: size = -1: size; export type _type = struct { flags: flags, _type: (alias | builtin | pointer), + id: u32, sz: size, align: size, }; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -358,12 +358,22 @@ hare_ast() { gen_ssa hare::ast hare::lex strings } -hare_types() { +gensrcs_hare_types() { gen_srcs hare::types \ arch.ha \ hash.ha \ store.ha \ - types.ha + types.ha \ + $* +} + +hare_types() { + if [ $testing -eq 1 ] + then + gensrcs_hare_types +test.ha + else + gensrcs_hare_types + fi gen_ssa hare::types hare::ast hash hash::fnv endian } diff --git a/stdlib.mk b/stdlib.mk @@ -1552,7 +1552,8 @@ testlib_hare_types_srcs= \ $(STDLIB)/hare/types/arch.ha \ $(STDLIB)/hare/types/hash.ha \ $(STDLIB)/hare/types/store.ha \ - $(STDLIB)/hare/types/types.ha + $(STDLIB)/hare/types/types.ha \ + $(STDLIB)/hare/types/+test.ha $(TESTCACHE)/hare/types/hare_types.ssa: $(testlib_hare_types_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hash) $(testlib_hash_fnv) $(testlib_endian) @printf 'HAREC \t$@\n'