Compiler messages are now printed in color with their respective code, field access support has been added in the type checker. However, field access nodes that contain other field access nodes are not yet supported. Signed-off-by: Slendi <slendi@socopon.com>
138 lines
2.9 KiB
Odin
138 lines
2.9 KiB
Odin
package main
|
|
|
|
import "core:fmt"
|
|
|
|
TypeKind :: enum {
|
|
Integer,
|
|
Float,
|
|
Pointer,
|
|
Array,
|
|
Struct,
|
|
}
|
|
|
|
StructType :: struct {
|
|
name: [dynamic]u8,
|
|
}
|
|
|
|
Type :: struct {
|
|
kind: TypeKind,
|
|
bit_size: u8,
|
|
is_signed: bool,
|
|
pointer_to: ^Type,
|
|
array_of: ^Type,
|
|
array_size: u64,
|
|
struct_type: ^StructType,
|
|
}
|
|
|
|
type_to_string :: proc(type: ^Type) -> string {
|
|
if type.kind == .Integer {
|
|
if type.is_signed {
|
|
return fmt.aprintf("i{}", type.bit_size)
|
|
} else {
|
|
return fmt.aprintf("u{}", type.bit_size)
|
|
}
|
|
} else if type.kind == .Float {
|
|
return fmt.aprintf("f{}", type.bit_size)
|
|
} else if type.kind == .Pointer {
|
|
return fmt.aprintf("^{}", type_to_string(type.pointer_to))
|
|
} else if type.kind == .Array {
|
|
return fmt.aprintf("[{}]{}", type.array_size, type_to_string(type.array_of))
|
|
} else if type.kind == .Struct {
|
|
return fmt.aprintf("Struct`%s`", type.struct_type.name)
|
|
}
|
|
return "???"
|
|
}
|
|
|
|
FunctionType :: struct {
|
|
name: [dynamic]u8,
|
|
return_type: ^Type,
|
|
parameter_types: [dynamic]^Type,
|
|
}
|
|
|
|
compare_types :: proc(a: ^Type, b: ^Type) -> (ret: bool, cast_required: bool) {
|
|
cast_required = false
|
|
|
|
if (a == nil && b != nil) || (a != nil && b == nil) {
|
|
ret = false
|
|
return
|
|
}
|
|
|
|
if (a.kind == .Integer || a.kind == .Float) && (a.bit_size > b.bit_size) {
|
|
ret = true
|
|
cast_required = true
|
|
return
|
|
}
|
|
|
|
ret = a != nil && b != nil && a.kind == b.kind && a.bit_size == b.bit_size && a.is_signed == b.is_signed
|
|
if ret == false {
|
|
return
|
|
}
|
|
|
|
if a.kind == .Pointer {
|
|
ret, _ = compare_types(a.pointer_to, b.pointer_to)
|
|
} else if a.kind == .Array {
|
|
ret, _ = compare_types(a.array_of, b.array_of)
|
|
ret = a.array_size == b.array_size && ret
|
|
}
|
|
return
|
|
}
|
|
|
|
compare_function_types :: proc(a: ^FunctionType, b: ^FunctionType) -> (ret: bool) {
|
|
ok, cast_ := compare_types(a.return_type, b.return_type)
|
|
ret = a != nil && b != nil && (ok && !cast_)
|
|
if ret {
|
|
for &arg, i in a.parameter_types {
|
|
ok, cast_ := compare_types(arg, b.parameter_types[i])
|
|
if !(ok && !cast_) {
|
|
ret = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
function_type_create :: proc() -> (ret: ^FunctionType) {
|
|
ret = new(FunctionType)
|
|
return
|
|
}
|
|
|
|
type_create_integer :: proc(bit_size: u8, signed: bool) -> (ret: ^Type) {
|
|
ret = new(Type)
|
|
ret.kind = .Integer
|
|
ret.bit_size = bit_size
|
|
ret.is_signed = signed
|
|
return
|
|
}
|
|
|
|
type_create_float :: proc(bit_size: u8) -> (ret: ^Type) {
|
|
ret = new(Type)
|
|
ret.kind = .Float
|
|
ret.bit_size = bit_size
|
|
ret.is_signed = true
|
|
return
|
|
}
|
|
|
|
type_create_pointer :: proc(to: ^Type) -> (ret: ^Type) {
|
|
ret = new(Type)
|
|
ret.kind = .Pointer
|
|
ret.pointer_to = to
|
|
return
|
|
}
|
|
|
|
type_create_array :: proc(of: ^Type, size: u64) -> (ret: ^Type) {
|
|
ret = new(Type)
|
|
ret.kind = .Array
|
|
ret.array_of = of
|
|
ret.array_size = size
|
|
return
|
|
}
|
|
|
|
type_create_struct :: proc(name: [dynamic]u8) -> (ret: ^Type) {
|
|
ret = new(Type)
|
|
ret.kind = .Struct
|
|
ret.struct_type = new(StructType)
|
|
ret.struct_type.name = name
|
|
return
|
|
}
|