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" BUILTIN_CHAR Type = "char" ) func ResolveType(name string) (Type, bool) { if name == string(BUILTIN_VOID) { return BUILTIN_VOID, true } else if name == string(BUILTIN_U8) { return BUILTIN_U8, true } else if name == string(BUILTIN_U16) { return BUILTIN_U16, true } else if name == string(BUILTIN_U32) { return BUILTIN_U32, true } else if name == string(BUILTIN_U64) { return BUILTIN_U64, true } else if name == string(BUILTIN_I8) { return BUILTIN_I8, true } else if name == string(BUILTIN_I16) { return BUILTIN_I16, true } else if name == string(BUILTIN_I32) { return BUILTIN_I32, true } else if name == string(BUILTIN_I64) { return BUILTIN_I64, true } else if name == string(BUILTIN_BOOL) { return BUILTIN_BOOL, true } else if name == string(BUILTIN_CHAR) { return BUILTIN_CHAR, 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 (a == BUILTIN_BOOL || a == BUILTIN_CHAR) && IsNumericType(b) { return true, b } if (b == BUILTIN_BOOL || b == BUILTIN_CHAR) && IsNumericType(a) { return true, a } 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 }