140 lines
2.3 KiB
Odin
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>"
|
|
}
|