hare

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

commit fa4ac1140043f747b7c179cfa9fd1388636bf3d7
parent 12dfb39fa74ede4502755d1b48319aa441d0547f
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Thu,  6 May 2021 03:44:23 -0400

hare::types: finish data structures and hashing

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Mhare/types/hash.ha | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mhare/types/store.ha | 14++++++++++++++
Mhare/types/types.ha | 32+++++++++++++++++++++++++++++++-
3 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/hare/types/hash.ha b/hare/types/hash.ha @@ -10,32 +10,37 @@ type storage = enum u8 { FUNCTION, POINTER, SLICE, STRING, STRUCT, TAGGED, TUPLE, UNION, }; +fn builtin_storage(b: builtin) u8 = switch (b) { + builtin::BOOL => storage::BOOL, + builtin::CHAR => storage::CHAR, + builtin::F32 => storage::F32, + builtin::F64 => storage::F64, + builtin::I16 => storage::I16, + builtin::I32 => storage::I32, + builtin::I64 => storage::I64, + builtin::I8 => storage::I8, + builtin::INT => storage::INT, + builtin::NULL => storage::NULL, + builtin::RUNE => storage::RUNE, + builtin::SIZE => storage::SIZE, + builtin::STR => storage::STRING, + builtin::U16 => storage::U16, + builtin::U32 => storage::U32, + builtin::U64 => storage::U64, + builtin::U8 => storage::U8, + builtin::UINT => storage::UINT, + builtin::UINTPTR => storage::UINTPTR, + builtin::VOID => storage::VOID, +}; + 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, - builtin::F32 => storage::F32, - builtin::F64 => storage::F64, - builtin::I16 => storage::I16, - builtin::I32 => storage::I32, - builtin::I64 => storage::I64, - builtin::I8 => storage::I8, - builtin::INT => storage::INT, - builtin::NULL => storage::NULL, - builtin::RUNE => storage::RUNE, - builtin::SIZE => storage::SIZE, - builtin::STR => storage::STRING, - builtin::U16 => storage::U16, - builtin::U32 => storage::U32, - builtin::U64 => storage::U64, - builtin::U8 => storage::U8, - builtin::UINT => storage::UINT, - builtin::UINTPTR => storage::UINTPTR, - builtin::VOID => storage::VOID, - }, + b: builtin => builtin_storage(b), + _enum => storage::ENUM, + func => storage::FUNCTION, pointer => storage::POINTER, + slice => storage::SLICE, st: _struct => if (st.kind == struct_union::STRUCT) storage::STRUCT @@ -82,10 +87,26 @@ export fn hash(t: *_type) u32 = { write64(id, a.length); }, builtin => void, + e: _enum => { + write8(id, builtin_storage(e.storage)); + for (let i = 0z; i < len(e.values); i += 1) { + hash::write(id, strings::toutf8(e.values[i].0)); + write64(id, e.values[i].1); + }; + }, + f: func => { + write32(id, hash(f.result)); + write8(id, f.variadism: u8); + write8(id, f.flags: u8); + for (let i = 0z; i < len(f.params); i += 1) { + write32(id, hash(f.params[i])); + }; + }, p: pointer => { write8(id, p.flags); write32(id, hash(p.referent)); }, + s: slice => write32(id, hash(s)), st: _struct => for (let i = 0z; i < len(st.fields); i += 1) { const field = st.fields[i]; hash::write(id, strings::toutf8(field.name)); @@ -220,4 +241,34 @@ export fn hash(t: *_type) u32 = { ]: tagged, }; assert(hash(&sample) == 3951208153); + + let sample = _type { + flags = flags::NONE, + _type = _enum { + storage = builtin::INT, + values = [ + ("FOO", 0), + ("BAR", 42), + ("BAZ", 69), + ], + }, + }; + assert(hash(&sample) == 1838699449); + + let sample = _type { + flags = flags::NONE, + _type = func { + result = &_void, + variadism = variadism::C, + flags = func_flags::NORETURN, + params = [&_uint, &_int], + }, + }; + assert(hash(&sample) == 1706980510); + + let sample = _type { + flags = flags::NONE, + _type = &_void: slice, + }; + assert(hash(&sample) == 3143795781); }; diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -361,7 +361,21 @@ fn type_finish(t: *_type) void = { a: alias => ast::ident_free(a.id), array => void, builtin => void, + e: _enum => { + for (let i = 0z; i < len(e.values); i += 1) { + free(e.values[i].0); + }; + free(e.values); + }, + f: func => { + type_finish(f.result); + for (let i = 0z; i < len(f.params); i += 1) { + type_finish(f.params[i]); + }; + free(f.params); + }, pointer => void, + s: slice => type_finish(s), st: _struct => free(st.fields), tu: tuple => free(tu), ta: tagged => free(ta), diff --git a/hare/types/types.ha b/hare/types/types.ha @@ -21,6 +21,32 @@ export type builtin = enum u8 { U16, U32, U64, U8, UINT, UINTPTR, VOID, }; +// An enum type, e.g. enum { FOO = 0 } +export type _enum = struct { + storage: builtin, + values: [](str, u64), +}; + +// Indicates the variadism of a [[func]] +export type variadism = enum { + NONE, + C, + HARE, +}; + +// Indicats if a [[func]] has the @noreturn attribute +export type func_flags = enum uint { + NORETURN = 1 << 0, +}; + +// A function type, e.g. fn(x: int, y: int) int +export type func = struct { + result: const *_type, + variadism: variadism, + flags: func_flags, + params: []const *_type, +}; + // Flags which apply to a pointer type. export type pointer_flags = enum u8 { NONE = 0, @@ -34,6 +60,9 @@ export type pointer = struct { flags: pointer_flags, }; +// []int +export type slice = const *_type; + // Indicates if a [[_struct]] was declared as a struct or union type. export type struct_union = enum { STRUCT, @@ -84,7 +113,8 @@ export def SIZE_UNDEFINED: size = -1: size; // A Hare type. export type _type = struct { flags: flags, - _type: (alias | array | builtin | pointer | _struct | tagged | tuple), + _type: (alias | array | builtin | _enum | func | pointer | slice | + _struct | tagged | tuple), id: u32, sz: size, align: size,