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:
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,