From c5d837d2cd9a57e453da9eaab0e41e0c185e084e Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 4 Aug 2022 10:07:13 +0200 Subject: fold & more --- bootstrap/types.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) (limited to 'bootstrap/types.c') diff --git a/bootstrap/types.c b/bootstrap/types.c index 8e735d0..401f9e6 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -206,3 +206,125 @@ visittypes(void (*visitor)(const struct type *, void *), void *arg) { for (struct typesnode *n = types.buckets[i]; n; n = n->next) visitor(&n->ty, arg); } + +const struct type * +constify(const struct type *ty) { + struct type ty2 = *ty; + if (ty->konst) + return ty; + if (ty2.t != TYfn) + ty2.konst = 1; + return interntype(ty2); +} + +const struct type * +unconstify(const struct type *ty) { + struct type ty2 = *ty; + if (!ty->konst) + return ty; + ty2.konst = 0; + return interntype(ty2); +} + +const struct type * +constifychild(const struct type *ty) { + struct type ty2 = *ty; + const struct type *child = constify(ty->child); + if (child == ty->child) + return ty; + ty2.child = child; + return interntype(ty2); +} + +static const struct type * +arraydecay(const struct type *ty) { + struct type ty2 = *ty; + + if (ty->t != TYarr) + return ty; + + ty2.t = TYptr; + return interntype(ty2); +} + +int +numtype2rank(const struct type *a) { + if (a->t == TYint) { + if (a->size < g_targ.intsize || a == ty_int) + return 0; + if (a == ty_uint) return 1; + if (a == ty_i32) return 2; + if (a == ty_u32) return 3; + if (a == ty_i64) return 4; + if (a == ty_u64) return 5; + } + if (a == ty_f32) return 6; + if (a == ty_f64) return 7; + return -1; +} + +const struct type * +rank2numtype(int r) { + static const struct type **types[] = { + &ty_int, &ty_uint, &ty_i32, &ty_u32, + &ty_i64, &ty_u64, &ty_f32, &ty_f64, + }; + assert(r >= 0 && r < ARRAY_LENGTH(types)); + return *types[r]; +} + +bool +isnumtype(const struct type *a) { + return a->t == TYint || a->t == TYfloat; +} + +// peer type resolution +const struct type * +typeof2(const struct type *a, const struct type *b) { + if (isnumtype(a) && isnumtype(b)) { + int ra = numtype2rank(a), rb = numtype2rank(b); + return rank2numtype(MAX(ra, rb)); + } + if (a == b) + return a; + if (unconstify(a) == b) + return a; + if (a == unconstify(b)) + return b; + if (a->t == TYarr && b->t == TYarr) + a = arraydecay(a); + if (a->t == TYptr && b->t == TYarr) + b = arraydecay(b); + if (a->t == TYarr && b->t == TYptr) + a = arraydecay(a); + if (a->t == TYptr && b->t == TYptr) { + bool akonst = a->child->konst, + bkonst = b->child->konst; + const struct type *uac = unconstify(a->child), + *ubc = unconstify(b->child); + if (uac == ubc) + return akonst ? a : b; + if (uac == ty_void) { + if (bkonst && !akonst) + return constifychild(a); + return a; + } + if (ubc == ty_void) { + if (akonst && !bkonst) + return constifychild(b); + return b; + } + if (uac == ty_u8) { + if (bkonst && !akonst) + return constifychild(a); + return a; + } + if (ubc == ty_u8) { + if (akonst && !bkonst) + return constifychild(b); + return b; + } + + } + return NULL; +} -- cgit v1.2.3