package types import "core:fmt" Numeric_Category :: enum { None, Signed_Integer, Unsigned_Integer, Float, } Kind :: enum { Invalid, Void, Int_Constraint, Concrete, } Type :: struct { kind: Kind, category: Numeric_Category, bits: int, } INVALID :: Type { kind = .Invalid, } VOID :: Type { kind = .Void, } INT :: Type { kind = .Int_Constraint, category = .Signed_Integer, } I8 :: Type { kind = .Concrete, category = .Signed_Integer, bits = 8, } I16 :: Type { kind = .Concrete, category = .Signed_Integer, bits = 16, } I32 :: Type { kind = .Concrete, category = .Signed_Integer, bits = 32, } I64 :: Type { kind = .Concrete, category = .Signed_Integer, bits = 64, } is_valid :: proc(value: Type) -> bool { return value.kind != .Invalid } is_concrete_integer :: proc(value: Type) -> bool { return( value.kind == .Concrete && (value.category == .Signed_Integer || value.category == .Unsigned_Integer) \ ) } is_signed :: proc(value: Type) -> bool { return value.kind == .Concrete && value.category == .Signed_Integer } equal :: proc(a, b: Type) -> bool { return a.kind == b.kind && a.category == b.category && a.bits == b.bits } can_widen :: proc(from, to: Type) -> bool { if equal(from, to) { return true } return( from.kind == .Concrete && to.kind == .Concrete && from.category == to.category && from.bits < to.bits \ ) } widest :: proc(a, b: Type) -> Type { if a.kind != .Concrete || b.kind != .Concrete || a.category != b.category { return INVALID } if a.bits >= b.bits { return a } return b } smallest_signed_for_literal :: proc(value: i64) -> Type { if value >= -128 && value <= 127 { return I8 } if value >= -32768 && value <= 32767 { return I16 } if value >= -2147483648 && value <= 2147483647 { return I32 } return I64 } name :: proc(value: Type) -> string { switch value.kind { case .Invalid: return "" case .Void: return "void" case .Int_Constraint: return "int" case .Concrete: switch value.category { case .Signed_Integer: switch value.bits { case 8: return "i8" case 16: return "i16" case 32: return "i32" case 64: return "i64" } case .Unsigned_Integer: return fmt.tprintf("u%d", value.bits) case .Float: return fmt.tprintf("f%d", value.bits) case .None: } } return "" }