hare

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

commit a79ab2a24937d20e97dc6be79c52574e346ca8f2
parent 9b6817741924a014cb6a7906997fd4beef6801ab
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue,  4 May 2021 16:38:24 -0400

hare::types: implement tuples

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

Diffstat:
Mhare/types/+test.ha | 34+++++++++++++++++++++++++++++++++-
Mhare/types/store.ha | 38++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/hare/types/+test.ha b/hare/types/+test.ha @@ -91,7 +91,7 @@ fn resolve( assert(y.offs == 0); assert(y._type._type as builtin == builtin::INT); - // Alignment + // Padding let atype = parse_type("struct { w: u8, x: u32, y: u8, z: u64 }"); defer ast::type_free(atype); let htype = lookup(st, &atype)!; @@ -195,3 +195,35 @@ fn resolve( assert(stype.fields[2].name == "z"); assert(stype.fields[2].offs == 32); }; + +@test fn tuples() void = { + let st = store(x86_64, &resolve, null); + defer store_free(st); + + // Basic case + let atype = parse_type("(int, int)"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == 8); + assert(htype.align == 4); + let tup = htype._type as tuple; + assert(len(tup) == 2); + + assert(tup[0].offs == 0); + assert(tup[0]._type._type as builtin == builtin::INT); + assert(tup[1].offs == 4); + assert(tup[1]._type._type as builtin == builtin::INT); + + // Padding + let atype = parse_type("(i8, i32, i8, i64)"); + defer ast::type_free(atype); + let htype = lookup(st, &atype)!; + assert(htype.sz == 24); + assert(htype.align == 8); + + let tup = htype._type as tuple; + assert(tup[0].offs == 0); + assert(tup[1].offs == 4); + assert(tup[2].offs == 8); + assert(tup[3].offs == 16); +}; diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -224,6 +224,20 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { }; st; }, + tu: ast::tuple_type => { + let tu = tuple_from_ast(store, tu)?; + sz = 0; align = 0; + for (let i = 0z; i < len(tu); i += 1) { + const value = tu[i]; + if (value.offs + value._type.sz > sz) { + sz = value.offs + value._type.sz; + }; + if (value._type.align > align) { + align = value._type.align; + }; + }; + tu; + }, * => abort(), // TODO }; return _type { @@ -314,6 +328,30 @@ fn struct_from_ast( }; }; +fn tuple_from_ast( + store: *typestore, + membs: ast::tuple_type, +) (tuple | deferred | error) = { + let values: []tuple_value = []; + let offs = 0z; + for (let i = 0z; i < len(membs); i += 1) { + const val = membs[i]; + const vtype = lookup(store, val)?; + + if (offs % vtype.align != 0) { + offs += vtype.align - (offs % vtype.align); + }; + + append(values, tuple_value { + _type = vtype, + offs = offs, + }); + + offs += vtype.sz; + }; + return values; +}; + fn field_cmp(a: const *void, b: const *void) int = { const a = a: const *struct_field, b = b: *const struct_field; return ascii::strcmp(a.name, b.name) as int;