diff options
| author | 2022-08-17 13:10:45 +0200 | |
|---|---|---|
| committer | 2022-08-17 13:32:11 +0200 | |
| commit | 86242b6cc1f53a86fcce1312211d3232661bf454 (patch) | |
| tree | a86552654922058fc53c1678878bb5c720bd25f6 /src/type.cff | |
| parent | 37cd29c0299dc3a726c7f8273cf203a868133f57 (diff) | |
collatz checks
Diffstat (limited to 'src/type.cff')
| -rw-r--r-- | src/type.cff | 51 |
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; } |