speedcat/src/type.odin
Slendi a966ff45a3 Improve messages, implement* field access
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>
2024-04-08 11:42:39 +03:00

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
}