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:
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),
};