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 }