use yog_script_ids::clr;
use super::model::Type;
use crate::words::{self, Word};
static BUILTINS: &[(&Word, Type, &str)] = &[
(&words::i8::WORD, Type::I8, clr::SBYTE),
(&words::i16::WORD, Type::I16, clr::INT16),
(&words::i32::WORD, Type::I32, clr::INT32),
(&words::i64::WORD, Type::I64, clr::INT64),
(&words::u8::WORD, Type::U8, clr::BYTE),
(&words::u16::WORD, Type::U16, clr::UINT16),
(&words::u32::WORD, Type::U32, clr::UINT32),
(&words::u64::WORD, Type::U64, clr::UINT64),
(&words::f32::WORD, Type::F32, clr::SINGLE),
(&words::f64::WORD, Type::F64, clr::DOUBLE),
(&words::decimal::WORD, Type::Decimal, clr::DECIMAL),
(&words::char::WORD, Type::Char, clr::CHAR),
(&words::bool::WORD, Type::Bool, clr::BOOLEAN),
(&words::string::WORD, Type::String, clr::STRING),
(&words::object::WORD, Type::Object, clr::OBJECT),
(&words::dynamic::WORD, Type::Dynamic, clr::OBJECT),
(&words::void::WORD, Type::Void, clr::VOID),
];
static INTEGERS: &[(Type, u32, bool)] = &[
(Type::I8, i8::BITS, true),
(Type::I16, i16::BITS, true),
(Type::I32, i32::BITS, true),
(Type::I64, i64::BITS, true),
(Type::U8, u8::BITS, false),
(Type::U16, u16::BITS, false),
(Type::U32, u32::BITS, false),
(Type::U64, u64::BITS, false),
];
pub(super) fn integer_width(t: &Type) -> Option<(u32, bool)> {
INTEGERS
.iter()
.find(|(i, ..)| i == t)
.map(|&(_, bits, signed)| (bits, signed))
}
pub(super) fn by_word(name: &str) -> Option<Type> {
BUILTINS
.iter()
.find(|(w, ..)| w.text == name)
.map(|(_, t, _)| t.clone())
}
pub(super) fn word(t: &Type) -> Option<&'static str> {
BUILTINS
.iter()
.find(|(_, b, _)| b == t)
.map(|(w, ..)| w.text)
}
pub(super) fn by_system_name(name: &str) -> Option<Type> {
BUILTINS
.iter()
.find(|(_, t, n)| *n == name && *t != Type::Dynamic)
.map(|(_, t, _)| t.clone())
}
pub(super) fn system_name(t: &Type) -> Option<&'static str> {
BUILTINS.iter().find(|(_, b, _)| b == t).map(|(.., n)| *n)
}
fn widens_to(t: &Type) -> &'static [Type] {
match t {
Type::I8 => &[
Type::I16,
Type::I32,
Type::I64,
Type::F32,
Type::F64,
Type::Decimal,
],
Type::U8 => &[
Type::I16,
Type::U16,
Type::I32,
Type::U32,
Type::I64,
Type::U64,
Type::F32,
Type::F64,
Type::Decimal,
],
Type::I16 => &[Type::I32, Type::I64, Type::F32, Type::F64, Type::Decimal],
Type::U16 | Type::Char => &[
Type::I32,
Type::U32,
Type::I64,
Type::U64,
Type::F32,
Type::F64,
Type::Decimal,
],
Type::I32 => &[Type::I64, Type::F32, Type::F64, Type::Decimal],
Type::U32 => &[Type::I64, Type::U64, Type::F32, Type::F64, Type::Decimal],
Type::I64 | Type::U64 => &[Type::F32, Type::F64, Type::Decimal],
Type::F32 => &[Type::F64],
_ => &[],
}
}
pub(super) fn is_number(t: &Type) -> bool {
t == &Type::F64 || t == &Type::Decimal || !widens_to(t).is_empty()
}
pub(super) fn is_integer(t: &Type) -> bool {
is_number(t) && !matches!(t, Type::F32 | Type::F64 | Type::Decimal)
}
pub(super) fn widens(from: &Type, to: &Type) -> bool {
from == to || widens_to(from).contains(to)
}