package main import ( "strconv" ) type Lang_I8 int8 type Lang_I16 int16 type Lang_I32 int32 type Lang_I64 int64 type Lang_U8 uint8 type Lang_U16 uint16 type Lang_U32 uint32 type Lang_U64 uint64 type Lang_Bool bool var PRIMITIVE_TYPE_NAMES = []string{"i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "bool"} type PrimitiveType uint32 const ( Primitive_I8 PrimitiveType = iota Primitive_I16 Primitive_I32 Primitive_I64 Primitive_U8 Primitive_U16 Primitive_U32 Primitive_U64 Primitive_F32 Primitive_F64 Primitive_Bool ) const STRING_TYPE_NAME = "string" var STRING_TYPE = Type{Type: Type_Named, Value: STRING_TYPE_NAME} const InvalidValue = 0xEEEEEE // Magic value type CompilerError struct { Position TokenPosition Message string } func (e CompilerError) Error() string { return e.Message + " (at " + e.Position.SourceFile + ", index " + strconv.FormatUint(e.Position.Position, 10) + ")" } func isSignedInt(primitiveType PrimitiveType) bool { switch primitiveType { case Primitive_I8, Primitive_I16, Primitive_I32, Primitive_I64: return true default: return false } } func isUnsignedInt(primitiveType PrimitiveType) bool { switch primitiveType { case Primitive_U8, Primitive_U16, Primitive_U32, Primitive_U64: return true default: return false } } func isFloatingPoint(primitiveType PrimitiveType) bool { switch primitiveType { case Primitive_F32, Primitive_F64: return true default: return false } } func getBits(primitiveType PrimitiveType) int { switch primitiveType { case Primitive_I8, Primitive_U8: return 8 case Primitive_I16, Primitive_U16: return 16 case Primitive_I32, Primitive_U32, Primitive_F32: return 32 case Primitive_I64, Primitive_U64, Primitive_F64: return 64 default: panic("Passed an invalid type (" + strconv.FormatUint(uint64(primitiveType), 10) + ") to getBits()") } } func getPrimitiveTypeName(primitiveType PrimitiveType) string { return PRIMITIVE_TYPE_NAMES[primitiveType] } func getTypeName(theType Type) string { switch theType.Type { case Type_Primitive: return getPrimitiveTypeName(theType.Value.(PrimitiveType)) case Type_Named: return theType.Value.(NamedType).TypeName case Type_Array: return getTypeName(theType.Value.(ArrayType).ElementType) + "[]" case Type_Tuple: name := "(" for idx, member := range theType.Value.(TupleType).Types { name += getTypeName(member) if idx != len(theType.Value.(TupleType).Types)-1 { name += ", " } } name += ")" return name default: panic("type name not implemented") } } func (t Type) String() string { return getTypeName(t) } func (t PrimitiveType) String() string { return getPrimitiveTypeName(t) } func (t ExpressionType) String() string { return strconv.Itoa(int(t)) } func getOperation(operator Operator) Operation { switch operator { case Operator_Greater: return Operation_Greater case Operator_Less: return Operation_Less case Operator_Plus, Operator_PlusEquals: return Operation_Add case Operator_Minus, Operator_MinusEquals: return Operation_Sub case Operator_Multiply, Operator_MultiplyEquals: return Operation_Mul case Operator_Divide, Operator_DivideEquals: return Operation_Div case Operator_Modulo, Operator_ModuloEquals: return Operation_Mod case Operator_EqualsEquals: return Operation_Equals case Operator_GreaterEquals: return Operation_GreaterEquals case Operator_LessEquals: return Operation_LessEquals case Operator_NotEquals: return Operation_NotEquals case Operator_Equals: return Operation_Nop default: return InvalidValue } } func getUnaryOperation(operator Operator) UnaryOperation { switch operator { case Operator_Minus: return UnaryOperation_Negate case Operator_Plus: return UnaryOperation_Nop case Operator_BitwiseNot: return UnaryOperation_BitwiseNot case Operator_Not: return UnaryOperation_LogicalNot default: return InvalidValue } } func isBooleanOperation(operation Operation) bool { switch operation { case Operation_Greater, Operation_Less, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals: return true default: return false } } func isArithmeticOperation(operation Operation) bool { return !isBooleanOperation(operation) } func isValidLHS(expressionType ExpressionType) bool { switch expressionType { case Expression_ArrayAccess, Expression_VariableReference, Expression_RawMemoryReference: return true default: return false } }