package shared type Type interface { IsPrimitive() bool IsStruct() bool IsPointer() bool } func GetSizeOfType(t Type) int { if t == PRIMITIVE_U8 || t == PRIMITIVE_I8 { return 4 } if t == PRIMITIVE_U16 || t == PRIMITIVE_I16 { return 4 } if t == PRIMITIVE_U32 || t == PRIMITIVE_I32 { return 4 } if t == PRIMITIVE_U64 || t == PRIMITIVE_I64 { return 8 } if t == PRIMITIVE_CHAR { return 4 } if t == PRIMITIVE_BOOL { return 4 } if t == PRIMITIVE_CSTRING { return 8 } if st, ok := t.(Struct); ok { maxSize := 0 for _, field := range st.Fields { size := GetSizeOfType(field.R) if size > maxSize { maxSize = size } } return maxSize * len(st.Fields) } return 0 } func IsNumericType(t Type) bool { return t == PRIMITIVE_U8 || t == PRIMITIVE_I8 || t == PRIMITIVE_U16 || t == PRIMITIVE_I16 || t == PRIMITIVE_U32 || t == PRIMITIVE_I32 || t == PRIMITIVE_U64 || t == PRIMITIVE_I64 || t == PRIMITIVE_UNTYPED_INT } func IsUnsignedType(ts ...Type) bool { for _, t := range ts { if !(t == PRIMITIVE_U8 || t == PRIMITIVE_U16 || t == PRIMITIVE_U32 || t == PRIMITIVE_U64) { return false } } return true } func IsSignedType(ts ...Type) bool { for _, t := range ts { if !(t == PRIMITIVE_I8 || t == PRIMITIVE_I16 || t == PRIMITIVE_I32 || t == PRIMITIVE_I64) { return false } } return true } func BiggerNumericType(t1, t2 Type) Type { if t1 == PRIMITIVE_U64 || t2 == PRIMITIVE_U64 { return PRIMITIVE_U64 } if t1 == PRIMITIVE_I64 || t2 == PRIMITIVE_I64 { return PRIMITIVE_I64 } if t1 == PRIMITIVE_U32 || t2 == PRIMITIVE_U32 { return PRIMITIVE_U32 } if t1 == PRIMITIVE_I32 || t2 == PRIMITIVE_I32 { return PRIMITIVE_I32 } if t1 == PRIMITIVE_U16 || t2 == PRIMITIVE_U16 { return PRIMITIVE_U16 } if t1 == PRIMITIVE_I16 || t2 == PRIMITIVE_I16 { return PRIMITIVE_I16 } if t1 == PRIMITIVE_U8 || t2 == PRIMITIVE_U8 { return PRIMITIVE_U8 } if t1 == PRIMITIVE_I8 || t2 == PRIMITIVE_I8 { return PRIMITIVE_I8 } return PRIMITIVE_UNTYPED_INT } func CanCoerceTo(t1, t2 Type) bool { if t1 == PRIMITIVE_UNTYPED_INT && IsNumericType(t2) { return true } if t1 == t2 { return true } if (IsSignedType(t1, t2) || IsUnsignedType(t1, t2)) && BiggerNumericType(t1, t2) == t2 { return true } return false } func CanCastTo(t1, t2 Type) bool { if t1 == t2 { return true } if t1 == PRIMITIVE_CHAR && t2 == PRIMITIVE_U8 || t1 == PRIMITIVE_U8 && t2 == PRIMITIVE_CHAR { return true } if IsNumericType(t1) && IsNumericType(t2) { return true } return false } type Primitive string const ( PRIMITIVE_VOID Primitive = "void" PRIMITIVE_UNTYPED_INT Primitive = "_untyped_int" PRIMITIVE_U8 Primitive = "u8" PRIMITIVE_U16 Primitive = "u16" PRIMITIVE_U32 Primitive = "u32" PRIMITIVE_U64 Primitive = "u64" PRIMITIVE_I8 Primitive = "i8" PRIMITIVE_I16 Primitive = "i16" PRIMITIVE_I32 Primitive = "i32" PRIMITIVE_I64 Primitive = "i64" PRIMITIVE_BOOL Primitive = "bool" PRIMITIVE_CHAR Primitive = "char" PRIMITIVE_CSTRING Primitive = "cstring" ) func (pt Primitive) IsPrimitive() bool { return true } func (pt Primitive) IsStruct() bool { return false } func (pt Primitive) IsPointer() bool { return false } type Struct struct { Fields []Pair[string, Type] } func (st Struct) IsPrimitive() bool { return false } func (st Struct) IsStruct() bool { return true } func (st Struct) IsPointer() bool { return false } type Pointer struct { To Type } func (pt Pointer) IsPrimitive() bool { return false } func (pt Pointer) IsStruct() bool { return false } func (pt Pointer) IsPointer() bool { return true } type TypeTable map[string]Type func NewTypeTable() TypeTable { tt := TypeTable{} tt.Define(string(PRIMITIVE_VOID), PRIMITIVE_VOID) tt.Define(string(PRIMITIVE_UNTYPED_INT), PRIMITIVE_UNTYPED_INT) tt.Define(string(PRIMITIVE_U8), PRIMITIVE_U8) tt.Define(string(PRIMITIVE_U16), PRIMITIVE_U16) tt.Define(string(PRIMITIVE_U32), PRIMITIVE_U32) tt.Define(string(PRIMITIVE_U64), PRIMITIVE_U64) tt.Define(string(PRIMITIVE_I8), PRIMITIVE_I8) tt.Define(string(PRIMITIVE_I16), PRIMITIVE_I16) tt.Define(string(PRIMITIVE_I32), PRIMITIVE_I32) tt.Define(string(PRIMITIVE_I64), PRIMITIVE_I64) tt.Define(string(PRIMITIVE_BOOL), PRIMITIVE_BOOL) tt.Define(string(PRIMITIVE_CHAR), PRIMITIVE_CHAR) tt.Define(string(PRIMITIVE_CSTRING), PRIMITIVE_CSTRING) tt.Define("string", Struct{Fields: []Pair[string, Type]{ {"data", PRIMITIVE_CSTRING}, {"len", PRIMITIVE_U64}, }}) return tt } func (tt TypeTable) Define(name string, t Type) { tt[name] = t } func (tt TypeTable) Lookup(name string) (Type, bool) { t, ok := tt[name] return t, ok }