hare

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

commit 6df07020525689247ecccf3e6f946d4785206883
parent b24ec40012b94f4c07e955ac3a7973b9ea4ec274
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 29 Apr 2021 16:57:35 -0400

hare::types: implement pointer types

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

Diffstat:
Mhare/types/hash.ha | 26+++++++++++++++++++-------
Mhare/types/store.ha | 11++++++++---
Mhare/types/types.ha | 15++++++++++++++-
3 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/hare/types/hash.ha b/hare/types/hash.ha @@ -2,6 +2,7 @@ use endian; use hash::fnv; use hash; use strings; +use fmt; // Keep ordered with respect to bootstrap harec:include/types.h type storage = enum u8 { @@ -34,6 +35,7 @@ fn type_storage(t: *_type) u8 = match (t._type) { builtin::UINTPTR => storage::UINTPTR, builtin::VOID => storage::VOID, }, + p: pointer => storage::POINTER, * => abort(), // TODO }; @@ -42,25 +44,35 @@ fn write8(h: *hash::hash, u: u8) void = { hash::write(h, buf[..1]); }; +fn write32(h: *hash::hash, u: u32) void = { + static let buf: [size(u32)]u8 = [0...]; + endian::leputu32(buf, u); + hash::write(h, buf); +}; + // Returns the hash of a type. These hashes are deterministic and universally // unique: different computers will generate the same hash for the same type. export fn hash(t: *_type) u32 = { // Note that this function should produce the same hashes as harec; see // bootstrap harec:src/types.c:type_hash - let hash = fnv::fnv32a(); - defer hash::close(hash); - write8(hash, type_storage(t)); - write8(hash, t.flags); + let id = fnv::fnv32a(); + defer hash::close(id); + write8(id, type_storage(t)); + write8(id, t.flags); match (t._type) { a: alias => for (let i = len(a); i > 0; i -= 1) { - hash::write(hash, strings::toutf8(a[i - 1])); - write8(hash, 0); + hash::write(id, strings::toutf8(a[i - 1])); + write8(id, 0); }, builtin => void, + p: pointer => { + write8(id, p.flags); + write32(id, hash(p.referent)); + }, }; - return fnv::sum32(hash); + return fnv::sum32(id); }; @test fn hash() void = { diff --git a/hare/types/store.ha b/hare/types/store.ha @@ -33,7 +33,7 @@ export fn store(resolver: *resolver, rstate: *void) *typestore = { // Returned from [[lookup]] when we are unable to resolve this type, but it does // not necessarily have an error. This occurs when a type includes an unknown // forward reference. -export type deferred = void; +export type deferred = void!; // A resolver function was not provided to [[store]], but was required to look // up this type. @@ -47,7 +47,7 @@ export fn lookup( store: *typestore, t: *ast::_type, ) (const *_type | deferred | error) = { - const t = fromast(t); + const t = fromast(store, t)?; const h = hash(&t); let bucket = &store.map[h % BUCKETS]; // XXX: Should not have to dereference bucket @@ -64,13 +64,17 @@ export fn lookup( return &bucket[len(*bucket) - 1]._type; }; -fn fromast(atype: *ast::_type) _type = { +fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = { let underlying = match (atype._type) { a: ast::alias_type => { assert(!a.unwrap); // TODO ast::ident_dup(a.ident): alias; }, b: ast::builtin_type => b: builtin, + p: ast::pointer_type => pointer { + referent = lookup(store, p.referent)?, + flags = p.flags: pointer_flags, + }, * => abort(), // TODO }; return _type { @@ -83,6 +87,7 @@ fn type_finish(t: *_type) void = { match (t._type) { a: alias => ast::ident_free(a), builtin => void, + pointer => void, * => abort(), // TODO }; }; diff --git a/hare/types/types.ha b/hare/types/types.ha @@ -10,6 +10,19 @@ export type builtin = enum u8 { U16, U32, U64, U8, UINT, UINTPTR, VOID, }; +// Flags which apply to a pointer type. +export type pointer_flags = enum u8 { + NONE = 0, + // Keep me consistent with ast::pointer_flags + NULLABLE = 1 << 0, +}; + +// *int +export type pointer = struct { + referent: const *_type, + flags: pointer_flags, +}; + // Flags for a Hare type. export type flags = enum u8 { NONE = 0, @@ -21,5 +34,5 @@ export type flags = enum u8 { // A Hare type. export type _type = struct { flags: flags, - _type: (alias | builtin), + _type: (alias | builtin | pointer), };