2024-03-11 22:05:36 +01:00
|
|
|
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
|
|
|
|
|
2024-03-14 16:42:22 +01:00
|
|
|
type Lang_Bool bool
|
|
|
|
|
2024-03-17 19:55:28 +01:00
|
|
|
var PRIMITIVE_TYPE_NAMES = []string{"i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "bool"}
|
2024-03-11 22:05:36 +01:00
|
|
|
|
|
|
|
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
|
2024-03-14 16:42:22 +01:00
|
|
|
Primitive_Bool
|
2024-03-11 22:05:36 +01:00
|
|
|
)
|
|
|
|
|
2024-03-17 19:55:28 +01:00
|
|
|
const STRING_TYPE_NAME = "string"
|
|
|
|
|
|
|
|
var STRING_TYPE = Type{Type: Type_Named, Value: STRING_TYPE_NAME}
|
|
|
|
|
2024-03-11 22:05:36 +01:00
|
|
|
const InvalidValue = 0xEEEEEE // Magic value
|
|
|
|
|
2024-03-13 23:26:20 +01:00
|
|
|
type CompilerError struct {
|
2024-03-29 15:12:37 +01:00
|
|
|
Position TokenPosition
|
2024-03-13 23:26:20 +01:00
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e CompilerError) Error() string {
|
2024-03-29 15:12:37 +01:00
|
|
|
return e.Message + " (at " + e.Position.SourceFile + ", index " + strconv.FormatUint(e.Position.Position, 10) + ")"
|
2024-03-13 23:26:20 +01:00
|
|
|
}
|
|
|
|
|
2024-03-11 22:05:36 +01:00
|
|
|
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()")
|
|
|
|
}
|
|
|
|
}
|
2024-03-17 19:55:28 +01:00
|
|
|
|
2024-03-28 15:48:50 +01:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2024-11-23 19:18:38 +01:00
|
|
|
func (t ExpressionType) String() string {
|
|
|
|
return strconv.Itoa(int(t))
|
|
|
|
}
|
|
|
|
|
2024-03-24 14:01:23 +01:00
|
|
|
func getOperation(operator Operator) Operation {
|
2024-03-23 14:03:20 +01:00
|
|
|
switch operator {
|
|
|
|
case Operator_Greater:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Greater
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Less:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Less
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Plus, Operator_PlusEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Add
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Minus, Operator_MinusEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Sub
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Multiply, Operator_MultiplyEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Mul
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Divide, Operator_DivideEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Div
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_Modulo, Operator_ModuloEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Mod
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_EqualsEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_Equals
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_GreaterEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_GreaterEquals
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_LessEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_LessEquals
|
2024-03-23 14:03:20 +01:00
|
|
|
case Operator_NotEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return Operation_NotEquals
|
2024-04-20 13:56:41 +02:00
|
|
|
case Operator_Equals:
|
|
|
|
return Operation_Nop
|
2024-03-23 14:03:20 +01:00
|
|
|
default:
|
|
|
|
return InvalidValue
|
|
|
|
}
|
|
|
|
}
|
2024-03-24 14:01:23 +01:00
|
|
|
|
2024-04-09 13:57:17 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-24 14:01:23 +01:00
|
|
|
func isBooleanOperation(operation Operation) bool {
|
|
|
|
switch operation {
|
2024-04-09 13:57:17 +02:00
|
|
|
case Operation_Greater, Operation_Less, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals:
|
2024-03-24 14:01:23 +01:00
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func isArithmeticOperation(operation Operation) bool {
|
|
|
|
return !isBooleanOperation(operation)
|
|
|
|
}
|
2024-11-23 19:18:38 +01:00
|
|
|
|
|
|
|
func isValidLHS(expressionType ExpressionType) bool {
|
|
|
|
switch expressionType {
|
|
|
|
case Expression_ArrayAccess, Expression_VariableReference, Expression_RawMemoryReference:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|