package shared type Type string const ( BUILTIN_VOID Type = "void" BUILTIN_UNTYPED_INT Type = "_untyped_int" // reserved for number literals that we dont yet know the type of BUILTIN_U8 Type = "u8" BUILTIN_U16 Type = "u16" BUILTIN_U32 Type = "u32" BUILTIN_U64 Type = "u64" BUILTIN_I8 Type = "i8" BUILTIN_I16 Type = "i16" BUILTIN_I32 Type = "i32" BUILTIN_I64 Type = "i64" BUILTIN_BOOL Type = "bool" ) func ResolveType(name string) (Type, bool) { if name == "void" { return BUILTIN_VOID, true } else if name == "u8" { return BUILTIN_U8, true } else if name == "u16" { return BUILTIN_U16, true } else if name == "u32" { return BUILTIN_U32, true } else if name == "u64" { return BUILTIN_U64, true } else if name == "i8" { return BUILTIN_I8, true } else if name == "i16" { return BUILTIN_I16, true } else if name == "i32" { return BUILTIN_I32, true } else if name == "i64" { return BUILTIN_I64, true } else if name == "bool" { return BUILTIN_BOOL, true } return BUILTIN_VOID, false } func IsNumericType(t Type) bool { return t == BUILTIN_UNTYPED_INT || t == BUILTIN_U8 || t == BUILTIN_U16 || t == BUILTIN_U32 || t == BUILTIN_U64 || t == BUILTIN_I8 || t == BUILTIN_I16 || t == BUILTIN_I32 || t == BUILTIN_I64 } func AreCompatibleTypes(a, b Type) (bool, Type) { if a == b { return true, a } if IsNumericType(a) && IsNumericType(b) { return AreCompatibleNumericTypes(a, b) } if IsUntypedNumeric(a) && IsNumericType(b) { return true, b } if IsUntypedNumeric(b) && IsNumericType(a) { return true, a } return false, BUILTIN_VOID } func AreCompatibleNumericTypes(a, b Type) (bool, Type) { if !IsNumericType(a) || !IsNumericType(b) { return false, BUILTIN_VOID } if a == b { return true, a } if IsUnsignedType(a) && IsSignedType(b) || IsSignedType(a) && IsUnsignedType(b) { larger := LargerNumericType(a, b) return true, larger } return true, LargerNumericType(a, b) } func IsSignedType(t Type) bool { return t == BUILTIN_I8 || t == BUILTIN_I16 || t == BUILTIN_I32 || t == BUILTIN_I64 } func IsUnsignedType(t Type) bool { return t == BUILTIN_U8 || t == BUILTIN_U16 || t == BUILTIN_U32 || t == BUILTIN_U64 } func LargerNumericType(a, b Type) Type { precedence := []Type{ BUILTIN_U8, BUILTIN_I8, BUILTIN_U16, BUILTIN_I16, BUILTIN_U32, BUILTIN_I32, BUILTIN_U64, BUILTIN_I64, } aIndex := -1 bIndex := -1 for i, t := range precedence { if t == a { aIndex = i } if t == b { bIndex = i } } if aIndex > bIndex { return a } return b } func IsUntypedNumeric(t Type) bool { return t == BUILTIN_UNTYPED_INT } func CanCoerceTo(src, dest Type) bool { if src == dest { return true } if IsUntypedNumeric(src) && IsNumericType(dest) { return true } return false }