Files
brolang/compiler/types/types.odin
T
2026-06-09 23:05:28 +02:00

140 lines
2.3 KiB
Odin

package types
import "core:fmt"
Numeric_Category :: enum {
None,
Signed_Integer,
Unsigned_Integer,
Float,
}
Kind :: enum {
Invalid,
Void,
Int_Constraint,
Concrete,
}
Type :: struct {
kind: Kind,
category: Numeric_Category,
bits: int,
}
INVALID :: Type {
kind = .Invalid,
}
VOID :: Type {
kind = .Void,
}
INT :: Type {
kind = .Int_Constraint,
category = .Signed_Integer,
}
I8 :: Type {
kind = .Concrete,
category = .Signed_Integer,
bits = 8,
}
I16 :: Type {
kind = .Concrete,
category = .Signed_Integer,
bits = 16,
}
I32 :: Type {
kind = .Concrete,
category = .Signed_Integer,
bits = 32,
}
I64 :: Type {
kind = .Concrete,
category = .Signed_Integer,
bits = 64,
}
is_valid :: proc(value: Type) -> bool {
return value.kind != .Invalid
}
is_concrete_integer :: proc(value: Type) -> bool {
return(
value.kind == .Concrete &&
(value.category == .Signed_Integer || value.category == .Unsigned_Integer) \
)
}
is_signed :: proc(value: Type) -> bool {
return value.kind == .Concrete && value.category == .Signed_Integer
}
equal :: proc(a, b: Type) -> bool {
return a.kind == b.kind && a.category == b.category && a.bits == b.bits
}
can_widen :: proc(from, to: Type) -> bool {
if equal(from, to) {
return true
}
return(
from.kind == .Concrete &&
to.kind == .Concrete &&
from.category == to.category &&
from.bits < to.bits \
)
}
widest :: proc(a, b: Type) -> Type {
if a.kind != .Concrete || b.kind != .Concrete || a.category != b.category {
return INVALID
}
if a.bits >= b.bits {
return a
}
return b
}
smallest_signed_for_literal :: proc(value: i64) -> Type {
if value >= -128 && value <= 127 {
return I8
}
if value >= -32768 && value <= 32767 {
return I16
}
if value >= -2147483648 && value <= 2147483647 {
return I32
}
return I64
}
name :: proc(value: Type) -> string {
switch value.kind {
case .Invalid:
return "<invalid>"
case .Void:
return "void"
case .Int_Constraint:
return "int"
case .Concrete:
switch value.category {
case .Signed_Integer:
switch value.bits {
case 8:
return "i8"
case 16:
return "i16"
case 32:
return "i32"
case 64:
return "i64"
}
case .Unsigned_Integer:
return fmt.tprintf("u%d", value.bits)
case .Float:
return fmt.tprintf("f%d", value.bits)
case .None:
}
}
return "<invalid>"
}