hare

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

commit 895c1b3a5344680004cb9e118496c0723374aa4e
parent 33a21bae4493ad82dfb20344cdb68856de06d77f
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon,  3 May 2021 19:11:32 -0400

hare::types: flesh out more type structures

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

Diffstat:
Mhare/types/hash.ha | 47++++++++++++++++++++++++++++++++++++++++++++++-
Mhare/types/store.ha | 3+++
Mhare/types/types.ha | 46+++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/hare/types/hash.ha b/hare/types/hash.ha @@ -12,6 +12,7 @@ type storage = enum u8 { fn type_storage(t: *_type) u8 = match (t._type) { alias => storage::ALIAS, + array => storage::ARRAY, t: builtin => switch (t) { builtin::BOOL => storage::BOOL, builtin::CHAR => storage::CHAR, @@ -34,7 +35,12 @@ fn type_storage(t: *_type) u8 = match (t._type) { builtin::UINTPTR => storage::UINTPTR, builtin::VOID => storage::VOID, }, - p: pointer => storage::POINTER, + pointer => storage::POINTER, + st: _struct => + if (st.kind == struct_union::STRUCT) + storage::STRUCT + else storage::UNION, + tuple => storage::TUPLE, * => abort(), // TODO }; @@ -64,11 +70,27 @@ export fn hash(t: *_type) u32 = { hash::write(id, strings::toutf8(a.id[i - 1])); write8(id, 0); }, + a: array => { + write32(id, hash(a.member)); + // TODO: This would cause [U32_MAX]int and + // [U32_MAX+1]int to have the same hash: + write32(id, a.length: u32); + }, builtin => void, p: pointer => { write8(id, p.flags); write32(id, hash(p.referent)); }, + st: _struct => for (let i = 0z; i < len(st.fields); i += 1) { + const field = st.fields[i]; + hash::write(id, strings::toutf8(field.name)); + write32(id, hash(field._type)); + // XXX: This is also wrong for offsets >U32_MAX + write32(id, field.offs: u32); + }, + tu: tuple => for (let i = 0z; i < len(tu); i += 1) { + write32(id, hash(tu[i]._type)); + }, }; return fnv::sum32(id); @@ -123,4 +145,27 @@ export fn hash(t: *_type) u32 = { }, }; assert(hash(&sample) == 1467299071); + + let sample = _type { + flags = flags::NONE, + _type = _struct { + kind = struct_union::STRUCT, + c_compat = true, + fields = [ + // XXX: Sorted by name per bootstrap harec + // conventions + struct_field { + name = "bar", + offs = 4, + _type = &_int, + }, + struct_field { + name = "foo", + offs = 0, + _type = &_int, + }, + ], + }, + }; + assert(hash(&sample) == 1072721578); }; diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -203,8 +203,11 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { fn type_finish(t: *_type) void = { match (t._type) { a: alias => ast::ident_free(a.id), + array => void, builtin => void, pointer => void, + st: _struct => free(st.fields), + tu: tuple => free(tu), * => abort(), // TODO }; }; diff --git a/hare/types/types.ha b/hare/types/types.ha @@ -7,6 +7,13 @@ export type alias = struct { _type: const nullable *_type, }; +// An array type, e.g. [10]int +export type array = struct { + // [[SIZE_UNDEFINED]] for [*]type + length: size, + member: const *_type, +}; + // A built-in primitive type (int, bool, str, etc). export type builtin = enum u8 { // Keep me consistent with ast::builtin @@ -27,6 +34,43 @@ export type pointer = struct { flags: pointer_flags, }; +// Indicates if a [[_struct]] was declared as a struct or union type. +export type struct_union = enum { + STRUCT, + UNION, +}; + +// struct { ... } or union { ... } +// +// Note that embedded anonymous structs will have been merged into their parent +// type. +export type _struct = struct { + kind: struct_union, + // TODO: Ensure that fields are sorted to match bootstrap harec + fields: []struct_field, + + // True if this struct is compatible with C structs (or unions). This + // will generally only be false if @offset is used to mess with things. + c_compat: bool, +}; + +// A single struct field. +export type struct_field = struct { + // "" for an anonymous field + name: str, + offs: size, + _type: const *_type, +}; + +// A tuple type, e.g. (a, b, c) +export type tuple = []tuple_value; + +// A single value of a tuple type. +export type tuple_value = struct { + offs: size, + _type: const *_type, +}; + // Flags for a Hare type. export type flags = enum u8 { NONE = 0, @@ -42,7 +86,7 @@ export def SIZE_UNDEFINED: size = -1: size; // A Hare type. export type _type = struct { flags: flags, - _type: (alias | builtin | pointer), + _type: (alias | array | builtin | pointer | _struct | tuple), id: u32, sz: size, align: size,