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:
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, <)?;
+ 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,