hare

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

commit c0ff68fb1c7e6d303fc16dfb4f8b8d8e9b57b9ff
parent fa4ac1140043f747b7c179cfa9fd1388636bf3d7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  6 May 2021 08:49:14 -0400

hare::types: implement lookup for list types

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

Diffstat:
Mhare/types/+test.ha | 44++++++++++++++++++++++++++++++++++++++++++++
Mhare/types/store.ha | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/hare/types/+test.ha b/hare/types/+test.ha @@ -227,3 +227,47 @@ fn resolve( assert(tup[2].offs == 8); assert(tup[3].offs == 16); }; + +@test fn lists() void = { + let st = store(x86_64, &resolve, null); + defer store_free(st); + + // Slice + let atype = parse_type("[]int"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == 24); + assert(htype.align == 8); + let slice = htype._type as slice; + assert(slice._type as builtin == builtin::INT); + + // Normal array + let atype = parse_type("[5]i32"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == 4 * 5); + assert(htype.align == 4); + let array = htype._type as array; + assert(array.member._type as builtin == builtin::I32); + assert(array.length == 5); + + // Unbounded array + let atype = parse_type("[*]i32"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == SIZE_UNDEFINED); + assert(htype.align == 4); + let array = htype._type as array; + assert(array.member._type as builtin == builtin::I32); + assert(array.length == SIZE_UNDEFINED); + + // Contextual array (equivalent to unbounded at this compilation stage) + let atype = parse_type("[_]i32"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == SIZE_UNDEFINED); + assert(htype.align == 4); + let array = htype._type as array; + assert(array.member._type as builtin == builtin::I32); + assert(array.length == SIZE_UNDEFINED); +}; diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -236,8 +236,15 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { }; tu; }, + lt: ast::list_type => { + let r = list_from_ast(store, &lt)?; + sz = r.0; + align = r.1; + r.2; + }, ta: ast::tagged_type => abort(), // TODO - * => abort(), // TODO + func: ast::func_type => abort(), // TODO + et: ast::enum_type => abort(), // TODO }; return _type { flags = atype.flags: flags, @@ -247,6 +254,57 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { }; }; +fn list_from_ast( + store: *typestore, + lt: *ast::list_type +) ((size, size, (slice | array)) | deferred | error) = { + let sz = SIZE_UNDEFINED, align = SIZE_UNDEFINED; + let memb = lookup(store, lt.members)?; + let t = match (lt.length) { + ast::len_slice => { + sz = store.arch._pointer; + if (sz % store.arch._size != 0) { + sz += store.arch._size - (sz % store.arch._size); + }; + sz += store.arch._size * 2; + align = if (store.arch._pointer > store.arch._size) + store.arch._pointer + else store.arch._size; + memb: slice; + }, + // Note: contextual length is handled by hare::unit when + // initializing bindings. We treat it like unbounded here and + // it's fixed up later on. + (ast::len_unbounded | ast::len_contextual) => { + align = memb.align; + array { + length = SIZE_UNDEFINED, + member = memb, + }; + }, + ex: *ast::expr => { + const resolv = match (store.resolve) { + null => return noresolver, + r: *resolver => r, + }; + const length = match (resolv(store.rstate, store, ex)) { + sz: size => sz, + // TODO: Why can't I propagate this? + deferred => return deferred, + err: errors::opaque => return err, + }; + sz = memb.sz * length; + assert(sz / length == memb.sz, "overflow"); + align = memb.align; + array { + length = length, + member = memb, + }; + }, + }; + return (sz, align, t); +}; + fn _struct_from_ast( store: *typestore, membs: []ast::struct_member,