hare

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

commit 4665cbeee798723f124b45a9814deb055fb06e85
parent 4a7f2fddd1dc27db747d598d0b89e23cc2e8a845
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 30 Apr 2021 09:18:39 -0400

hare::types: store type size & align

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

Diffstat:
Ahare/types/arch.ha | 20++++++++++++++++++++
Mhare/types/hash.ha | 14++++++++++----
Mhare/types/store.ha | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mhare/types/types.ha | 12+++++++++++-
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 2++
6 files changed, 157 insertions(+), 13 deletions(-)

diff --git a/hare/types/arch.ha b/hare/types/arch.ha @@ -0,0 +1,20 @@ +// Configuration for a specific architecture. +export type arch = struct { + _int: size, + _pointer: size, + _size: size, +}; + +// [[arch]] configuration for x86_64. +export const x86_64: arch = arch { + _int = 4, + _pointer = 8, + _size = 8, +}; + +// [[arch]] configuration for aarch64. +export const aarch64: arch = arch { + _int = 4, + _pointer = 8, + _size = 8, +}; diff --git a/hare/types/hash.ha b/hare/types/hash.ha @@ -60,8 +60,8 @@ export fn hash(t: *_type) u32 = { write8(id, t.flags); match (t._type) { - a: alias => for (let i = len(a); i > 0; i -= 1) { - hash::write(id, strings::toutf8(a[i - 1])); + a: alias => for (let i = len(a.id); i > 0; i -= 1) { + hash::write(id, strings::toutf8(a.id[i - 1])); write8(id, 0); }, builtin => void, @@ -84,13 +84,19 @@ export fn hash(t: *_type) u32 = { let sample = _type { flags = flags::NONE, - _type = ["foo", "bar"]: alias, + _type = alias { + id = ["foo", "bar"], + ... + }, }; assert(hash(&sample) == 1488828140); let sample = _type { flags = flags::ERROR, - _type = ["foo", "bar"]: alias, + _type = alias { + id = ["foo", "bar"], + ... + }, }; assert(hash(&sample) == 4003927486); diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -12,6 +12,7 @@ export type resolver = fn( ) (size | errors::opaque); export type typestore = struct { + arch: arch, map: [BUCKETS][]struct { hash: u32, _type: _type, @@ -22,8 +23,9 @@ export type typestore = struct { // Initializes a new type store. Optionally, provide a function which // type-checks and evaluates an [[ast::expr]]. -export fn store(resolver: *resolver, rstate: *void) *typestore = { +export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = { return alloc(typestore { + arch = arch, resolve = resolver, rstate = rstate, ... @@ -65,27 +67,130 @@ export fn lookup( }; fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { + let sz = SIZE_UNDEFINED, align = SIZE_UNDEFINED; let underlying = match (atype._type) { a: ast::alias_type => { - assert(!a.unwrap); // TODO - ast::ident_dup(a.ident): alias; + // TODO: This is incomplete + assert(!a.unwrap); + alias { + id = ast::ident_dup(a.ident), + _type = null, + }; }, - b: ast::builtin_type => b: builtin, - p: ast::pointer_type => pointer { - referent = lookup(store, p.referent)?, - flags = p.flags: pointer_flags, + // TODO: Tuple unpacking could improve this + b: ast::builtin_type => switch (b) { + ast::builtin_type::BOOL => { + sz = store.arch._int; + align = store.arch._int; + builtin::BOOL; + }, + ast::builtin_type::CHAR => { + sz = 1; align = 1; + builtin::CHAR; + }, + ast::builtin_type::F32 => { + sz = 4; align = 4; + builtin::F32; + }, + ast::builtin_type::F64 => { + sz = 8; align = 8; + builtin::F64; + }, + ast::builtin_type::I16 => { + sz = 2; align = 2; + builtin::I16; + }, + ast::builtin_type::I32 => { + sz = 4; align = 4; + builtin::I32; + }, + ast::builtin_type::I64 => { + sz = 8; align = 8; + builtin::I64; + }, + ast::builtin_type::I8 => { + sz = 1; align = 1; + builtin::I8; + }, + ast::builtin_type::INT => { + sz = store.arch._int; + align = store.arch._int; + builtin::INT; + }, + ast::builtin_type::RUNE => { + sz = 4; align = 4; + builtin::RUNE; + }, + ast::builtin_type::SIZE => { + sz = store.arch._size; + align = store.arch._size; + builtin::SIZE; + }, + ast::builtin_type::STR => { + sz += store.arch._pointer; + sz += sz % store.arch._size + store.arch._size; + sz += store.arch._size; + align = if (store.arch._size > store.arch._pointer) + store.arch._size + else + store.arch._pointer; + builtin::STR; + }, + ast::builtin_type::U16 => { + sz = 2; align = 2; + builtin::U16; + }, + ast::builtin_type::U32 => { + sz = 4; align = 4; + builtin::U32; + }, + ast::builtin_type::U64 => { + sz = 8; align = 8; + builtin::U64; + }, + ast::builtin_type::U8 => { + sz = 1; align = 1; + builtin::U8; + }, + ast::builtin_type::UINT => { + sz = store.arch._int; + align = store.arch._int; + builtin::UINT; + }, + ast::builtin_type::UINTPTR => { + sz = store.arch._pointer; + align = store.arch._pointer; + builtin::UINTPTR; + }, + ast::builtin_type::VOID => { + sz = 0; align = 0; + builtin::VOID; + }, + ast::builtin_type::NULL => builtin::NULL, + ast::builtin_type::ICONST, + ast::builtin_type::FCONST => abort(), // TODO? + }, + p: ast::pointer_type => { + sz = store.arch._pointer; + align = store.arch._pointer; + pointer { + referent = lookup(store, p.referent)?, + flags = p.flags: pointer_flags, + }; }, * => abort(), // TODO }; return _type { flags = atype.flags: flags, _type = underlying, + sz = sz, + align = align, }; }; fn type_finish(t: *_type) void = { match (t._type) { - a: alias => ast::ident_free(a), + a: alias => ast::ident_free(a.id), builtin => void, pointer => void, * => abort(), // TODO diff --git a/hare/types/types.ha b/hare/types/types.ha @@ -1,7 +1,11 @@ use hare::ast; // A type alias. -export type alias = ast::ident; +export type alias = struct { + id: ast::ident, + // null for forward referenced types + _type: const nullable *_type, +}; // A built-in primitive type (int, bool, str, etc). export type builtin = enum u8 { @@ -31,8 +35,14 @@ export type flags = enum u8 { ERROR = 1 << 1, }; +// The sz field of [[_type]] is set to this value to indicate that the size of +// the type is undefined. +export def SIZE_UNDEFINED: size = -1: size; + // A Hare type. export type _type = struct { flags: flags, _type: (alias | builtin | pointer), + sz: size, + align: size, }; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -360,6 +360,7 @@ hare_ast() { hare_types() { gen_srcs hare::types \ + arch.ha \ hash.ha \ store.ha \ types.ha diff --git a/stdlib.mk b/stdlib.mk @@ -578,6 +578,7 @@ $(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $ # hare::types stdlib_hare_types_srcs= \ + $(STDLIB)/hare/types/arch.ha \ $(STDLIB)/hare/types/hash.ha \ $(STDLIB)/hare/types/store.ha \ $(STDLIB)/hare/types/types.ha @@ -1548,6 +1549,7 @@ $(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt) # hare::types testlib_hare_types_srcs= \ + $(STDLIB)/hare/types/arch.ha \ $(STDLIB)/hare/types/hash.ha \ $(STDLIB)/hare/types/store.ha \ $(STDLIB)/hare/types/types.ha