aboutsummaryrefslogtreecommitdiff
path: root/src/type.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-16 05:28:18 +0200
committerlemon <lsof@mailbox.org>2022-08-16 05:28:18 +0200
commit73f68a9c5ed4c8139cc1c4f7695da29e5a3fb4c8 (patch)
treeb2cebcf1f6b6073eeeb0595710d6fdf05fcb06fb /src/type.cff
parentb3159bfd93c8bdce71f7437abdc521b5ccb72367 (diff)
stuff
Diffstat (limited to 'src/type.cff')
-rw-r--r--src/type.cff47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/type.cff b/src/type.cff
index 33d78e6..97fc44a 100644
--- a/src/type.cff
+++ b/src/type.cff
@@ -136,3 +136,50 @@ extern fn putprimtypes(env *Env) void {
)
ty_voidptr = interntype({ .size: g_targ.ptrsize, .u: :Ptr ty_void });
}
+
+extern fn isnumtype(ty *const Type) bool {
+ return ty->is(:Int) or ty->is(:Flo);
+}
+
+fn numtype2rank(ty *const Type) int {
+ ty = unconstify(ty);
+ switch {
+ case ty->is(:Int) and (ty == ty_int or ty.size < ty_int.size);
+ return 0;
+ case ty == ty_uint; return 1;
+ case ty == ty_i32; return 2;
+ case ty == ty_u32; return 3;
+ case ty == ty_i64; return 4;
+ case ty == ty_u64; return 5;
+ case ty == ty_f32; return 6;
+ case ty == ty_f64; return 7;
+ }
+ return -1;
+}
+
+fn rank2numtype(r int) *const Type {
+ static const types []**const Type = {
+ &ty_int, &ty_uint, &ty_i32, &ty_u32,
+ &ty_i64, &ty_u64, &ty_f32, &ty_f64,
+ };
+ assert(r >= 0 and r < types.#len, "rank");
+ return *types[r];
+}
+
+extern fn typeof2(a *const Type, b *const Type) *const Type {
+ if a == b and not a->is(:Int) {
+ return a;
+ }
+ if isnumtype(a) and isnumtype(b) {
+ let ra = numtype2rank(a),
+ rb = numtype2rank(b);
+ return rank2numtype(MAX(ra, rb));
+ }
+ if unconstify(a) == b {
+ return a;
+ }
+ if a == unconstify(b) {
+ return b;
+ }
+ return #null;
+}