package types import "github.com/marzeq/qk/shared" type Type interface { Equals(Type) bool CanCoerceTo(Type) bool } type PrimitiveType string const ( PRIMITIVE_I8 PrimitiveType = "i8" PRIMITIVE_I16 PrimitiveType = "i16" PRIMITIVE_I32 PrimitiveType = "i32" PRIMITIVE_I64 PrimitiveType = "i64" PRIMITIVE_U8 PrimitiveType = "u8" PRIMITIVE_U16 PrimitiveType = "u16" PRIMITIVE_U32 PrimitiveType = "u32" PRIMITIVE_U64 PrimitiveType = "u64" PRIMITIVE_F32 PrimitiveType = "f32" PRIMITIVE_F64 PrimitiveType = "f64" PRIMITIVE_ISZ PrimitiveType = "isz" PRIMITIVE_USZ PrimitiveType = "usz" PRIMITIVE_VOID PrimitiveType = "void" PRIMITIVE_CHAR PrimitiveType = "char" ) func (p PrimitiveType) IsInteger() bool { return p == PRIMITIVE_I8 || p == PRIMITIVE_I16 || p == PRIMITIVE_I32 || p == PRIMITIVE_I64 || p == PRIMITIVE_U8 || p == PRIMITIVE_U16 || p == PRIMITIVE_U32 || p == PRIMITIVE_U64 || p == PRIMITIVE_ISZ || p == PRIMITIVE_USZ } func (p PrimitiveType) IsFloat() bool { return p == PRIMITIVE_F32 || p == PRIMITIVE_F64 } func (p PrimitiveType) IsNumeric() bool { return p.IsInteger() || p.IsFloat() } func (p PrimitiveType) Equals(other Type) bool { if otherPrimitive, ok := other.(PrimitiveType); ok { return p == otherPrimitive } return false } func (p PrimitiveType) CanCoerceTo(other Type) bool { if p.Equals(other) { return true } otherPrimitive, ok := other.(PrimitiveType) if !ok { return false } if p.IsNumeric() && otherPrimitive.IsNumeric() { return true } if p.Equals(PRIMITIVE_CHAR) && otherPrimitive.Equals(PRIMITIVE_U8) || p.Equals(PRIMITIVE_U8) && otherPrimitive.Equals(PRIMITIVE_CHAR) { return true } return false } type StructType struct { Fields []shared.Pair[string, Type] } func (s StructType) Equals(other Type) bool { otherStruct, ok := other.(StructType) if !ok { return false } if len(s.Fields) != len(otherStruct.Fields) { return false } for i, field := range s.Fields { otherField := otherStruct.Fields[i] if field.L != otherField.L || !field.R.Equals(otherField.R) { return false } } return true } func (s StructType) CanCoerceTo(other Type) bool { if s.Equals(other) { return true } return false } type PointerType struct { Base Type } func (p PointerType) Equals(other Type) bool { if otherPointer, ok := other.(PointerType); ok { return p.Base.Equals(otherPointer.Base) } return false } func (p PointerType) CanCoerceTo(other Type) bool { if p.Equals(other) { return true } otherPointer, ok := other.(PointerType) if !ok { return false } if p.Base.Equals(PRIMITIVE_VOID) || otherPointer.Base.Equals(PRIMITIVE_VOID) { return true } return p.Base.CanCoerceTo(otherPointer.Base) } type ArrayType struct { Base Type Size int } func (a ArrayType) Equals(other Type) bool { otherArray, ok := other.(ArrayType) if !ok { return false } if a.Size != otherArray.Size { return false } return a.Base.Equals(otherArray.Base) } func (a ArrayType) CanCoerceTo(other Type) bool { if a.Equals(other) { return true } otherArray, ok := other.(ArrayType) if !ok { return false } if a.Size != otherArray.Size { return false } return a.Base.CanCoerceTo(otherArray.Base) } type FunctionType struct { Parameters []Type ReturnType Type } func (f FunctionType) Equals(other Type) bool { otherFunction, ok := other.(FunctionType) if !ok { return false } if len(f.Parameters) != len(otherFunction.Parameters) { return false } for i, param := range f.Parameters { if !param.Equals(otherFunction.Parameters[i]) { return false } } return f.ReturnType.Equals(otherFunction.ReturnType) } func (f FunctionType) CanCoerceTo(other Type) bool { otherFunction, ok := other.(FunctionType) if !ok { return false } if len(f.Parameters) != len(otherFunction.Parameters) { return false } for i := range f.Parameters { if !otherFunction.Parameters[i].CanCoerceTo(f.Parameters[i]) { return false } } return f.ReturnType.CanCoerceTo(otherFunction.ReturnType) } type ErrorType struct{} func (e ErrorType) Equals(other Type) bool { _, ok := other.(ErrorType) return ok } func (e ErrorType) CanCoerceTo(other Type) bool { return e.Equals(other) }