aboutsummaryrefslogtreecommitdiff
path: root/src/type.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-15 12:22:47 +0200
committerlemon <lsof@mailbox.org>2022-08-15 12:22:47 +0200
commitf906d0b350b0b4ceb747669c9a9845d11bd0e486 (patch)
tree5f09a7b714e6ce93f6094a06e5f736513110fb8d /src/type.cff
parentf802bb99263aaa5be492999babd44cd2fdb1c65f (diff)
self hosted progress
Diffstat (limited to 'src/type.cff')
-rw-r--r--src/type.cff146
1 files changed, 126 insertions, 20 deletions
diff --git a/src/type.cff b/src/type.cff
index a3c7021..33d78e6 100644
--- a/src/type.cff
+++ b/src/type.cff
@@ -1,32 +1,138 @@
import "cffc.hff";
import "util.hff";
+import "common.hff";
+import "set.hff";
-fn hashtype(ty *const Type) u32 {
- let h = FNV1A_INI;
- h = fnv1a_i(h, ty.konst ? 1 : 0);
+struct TypeTraits {
+ fn hash(ty *const Type) u32 {
+ let h = FNV1A_INI;
+ h = fnv1a_i(h, as(int)ty.u.#tag);
+ h = fnv1a_i(h, ty.konst ? 1 : 0);
- switch ty.u {
- case Void; case Bool;
+ switch ty.u {
+ case Void; case Bool;
- case Flo;
- h = fnv1a_i(h, ty.size);
- h = fnv1a_i(h, ty.align);
+ case Flo;
+ h = fnv1a_i(h, ty.size);
- case Int i;
- h = fnv1a_i(h, i.sgn ? 1 : 0);
- h = fnv1a_i(h, ty.size);
- h = fnv1a_i(h, ty.align);
+ case Int i;
+ h = fnv1a_i(h, i.sgn ? 1 : 0);
+ h = fnv1a_i(h, ty.size);
- case Ptr child;
- h = fnv1a_i(h, child.id);
+ case Ptr child;
+ h = fnv1a_i(h, child.id);
- case Arr arr;
- h = fnv1a_i(h, arr.child.id);
- h = fnv1a_i(h, arr.length);
+ case Arr arr;
+ h = fnv1a_i(h, arr.child.id);
+ h = fnv1a_i(h, arr.length);
- case Slice child;
- h = fnv1a_i(h, child.id);
+ case Slice child;
+ h = fnv1a_i(h, child.id);
+ }
+ return h;
}
- return h;
+
+ fn eq(a *const Type, b *const Type) bool {
+ if a.u.#tag != b.u.#tag or a.size != b.size
+ or a.align != b.align or a.konst != b.konst {
+ return #f;
+ }
+ switch a.u {
+ case Void; case Bool; case Flo;
+ case Int i;
+ return i.sgn == b.u.Int.sgn;
+ case Ptr child;
+ return child == b.u.Ptr;
+ case Arr arr;
+ let brr = b.u.Arr;
+ return arr.length == brr.length and arr.child == brr.child;
+ case Slice child;
+ return child == b.u.Slice;
+ case Fn f0;
+ let f1 = b.u.Fn;
+ if f0.variadic != f1.variadic {
+ return #f;
+ }
+ if f0.ret != f1.ret {
+ return #f;
+ }
+ if f0.params.#len != f1.params.#len {
+ return #f;
+ }
+ foreach(p, i, f0.params,
+ if p != f1.params[i] {
+ return #f;
+ }
+ )
+ return #t;
+ }
+ return #f;
+ }
+
+ fn dup(ty *const Type) *const Type {
+ let p *Type = xmalloc(sizeof Type);
+ static id int = 0;
+ *p = *ty;
+ p.id = id++;
+ return p;
+ }
+}
+
+extern fn interntype(ty0 Type) *const Type {
+ static set Set<*const Type, TypeTraits> = {};
+
+ if ty0.align == 0 {
+ ty0.align = ty0.size;
+ }
+
+ return *set->intern(&ty0);
+}
+
+extern static ty_void *const Type = {},
+ ty_bool *const Type = {},
+ ty_i8 *const Type = {},
+ ty_u8 *const Type = {},
+ ty_i16 *const Type = {},
+ ty_u16 *const Type = {},
+ ty_i32 *const Type = {},
+ ty_u32 *const Type = {},
+ ty_int *const Type = {},
+ ty_uint *const Type = {},
+ ty_i64 *const Type = {},
+ ty_u64 *const Type = {},
+ ty_isize *const Type = {},
+ ty_usize *const Type = {},
+ ty_iptrint *const Type = {},
+ ty_uptrint *const Type = {},
+ ty_f32 *const Type = {},
+ ty_f64 *const Type = {},
+ ty_voidptr *const Type = {};
+
+extern fn putprimtypes(env *Env) void {
+ let types []struct { name *const u8, gty **const Type, ty Type } = {
+ { "void", &ty_void, { .size: 0, .align: 1, .u: :Void }},
+ { "bool", &ty_bool, { .size: 1, .align: 1, .u: :Bool }},
+ { "f32", &ty_f32, { .size: 4, .u: :Flo }},
+ { "f64", &ty_f64, { .size: 8, g_targ.f64align, .u: :Flo }},
+ { "i8", &ty_i8, { .size: 1, .u: :Int { .sgn: #t }}},
+ { "u8", &ty_u8, { .size: 1, .u: :Int { .sgn: #f }}},
+ { "i16", &ty_i16, { .size: 2, .u: :Int { .sgn: #t }}},
+ { "u16", &ty_u16, { .size: 2, .u: :Int { .sgn: #f }}},
+ { "i32", &ty_i32, { .size: 4, .u: :Int { .sgn: #t }}},
+ { "u32", &ty_u32, { .size: 4, .u: :Int { .sgn: #f }}},
+ { "int", &ty_int, { g_targ.intsize, .u: :Int { .sgn: #t }}},
+ { "uint", &ty_uint, { g_targ.intsize, .u: :Int { .sgn: #f }}},
+ { "isize", &ty_isize,{ g_targ.sizesize, .u: :Int { .sgn: #t }}},
+ { "usize", &ty_usize,{ g_targ.sizesize, .u: :Int { .sgn: #f }}},
+ { "i64", &ty_i64, { .size: 8, g_targ.i64align, .u: :Int { .sgn: #t }}},
+ { "u64", &ty_u64, { .size: 8, g_targ.i64align, .u: :Int { .sgn: #f }}},
+ { "iptrint",&ty_iptrint, { g_targ.ptrsize, .u: :Int { .sgn: #t }}},
+ { "uptrint",&ty_uptrint, { g_targ.ptrsize, .u: :Int { .sgn: #f }}},
+ };
+
+ foreach(type, _, types[0::],
+ envput(env, { type.name, .u: :Ty (*type.gty = interntype(type.ty)) }, #null);
+ )
+ ty_voidptr = interntype({ .size: g_targ.ptrsize, .u: :Ptr ty_void });
}