aboutsummaryrefslogtreecommitdiff
path: root/src/type.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-17 13:10:45 +0200
committerlemon <lsof@mailbox.org>2022-08-17 13:32:11 +0200
commit86242b6cc1f53a86fcce1312211d3232661bf454 (patch)
treea86552654922058fc53c1678878bb5c720bd25f6 /src/type.cff
parent37cd29c0299dc3a726c7f8273cf203a868133f57 (diff)
collatz checks
Diffstat (limited to 'src/type.cff')
-rw-r--r--src/type.cff51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/type.cff b/src/type.cff
index 1d224cc..e3989c7 100644
--- a/src/type.cff
+++ b/src/type.cff
@@ -202,6 +202,31 @@ fn rank2numtype(r int) *const Type {
return *types[r];
}
+fn arraydecay(ty *const Type) *const Type {
+ switch ty.u {
+ case Arr arr; return mkptrtype(arr.child);
+ case else; return ty;
+ }
+}
+
+fn constifychild(ty *const Type) *const Type {
+ let ty2 = *ty;
+ switch ty.u {
+ case Ptr child;
+ let cchild = constify(child);
+ if child == cchild { return ty; }
+ ty2.u.Ptr = child;
+ return interntype(ty2);
+ case Slice child;
+ let cchild = constify(child);
+ if child == cchild { return ty; }
+ ty2.u.Slice = child;
+ return interntype(ty2);
+ case else;
+ assert(#f, "constifychild: not ptr or slice");
+ }
+}
+
extern fn typeof2(a *const Type, b *const Type) *const Type {
if a == b and !a->is(:Int) {
return a;
@@ -217,5 +242,31 @@ extern fn typeof2(a *const Type, b *const Type) *const Type {
if a == unconstify(b) {
return b;
}
+ if a->is(:Arr) and b->is(:Arr) {
+ a = arraydecay(a);
+ }
+ if a->is(:Ptr) and b->is(:Arr) {
+ b = arraydecay(b);
+ }
+ if a->is(:Arr) and b->is(:Ptr) {
+ a = arraydecay(a);
+ }
+ if a.u.#tag == b.u.#tag and (a->is(:Ptr) or a->is(:Slice)) {
+ let akonst = a.u.Ptr.konst,
+ bkonst = b.u.Ptr.konst,
+ uac = unconstify(a.u.Ptr),
+ ubc = unconstify(b.u.Ptr);
+ if uac == ubc {
+ return akonst ? a : b;
+ }
+ if uac == ty_void {
+ if bkonst and !akonst { return constifychild(a); }
+ return a;
+ }
+ if ubc == ty_void {
+ if akonst and !bkonst { return constifychild(b); }
+ return b;
+ }
+ }
return #null;
}