1use std::{collections::HashMap, fmt::Display, sync::OnceLock};
2
3use cl_ast::{Pat, PatOp, fmt::FmtAdapter, types::Symbol};
4use cl_structures::intern::{
5 interned::Interned, leaky_interner::LeakyInterner, string_interner::StringInterner,
6};
7
8use crate::{
9 Callable,
10 convalue::ConValue,
11 env::Environment,
12 error::{Error, IResult},
13};
14
15pub type TypeId = usize;
16pub type Type = Interned<'static, TypeInfo>;
17
18static TYPE_INTERNER: OnceLock<LeakyInterner<TypeInfo>> = OnceLock::new();
19
20#[rustfmt::skip]
22#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub enum Model {
24 Integer { signed: bool, size: usize, min: i128, max: i128 },
25 Float { size: usize },
26 Bool,
27 Char,
28 Str,
29 Any,
30 Never,
32 Unit(usize),
34 Tuple(Box<[Type]>),
36 Struct(Box<[(Symbol, Type)]>, bool),
38 Enum(Box<[(Symbol, Type)]>),
40}
41
42impl Display for Model {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 use std::fmt::Write;
45 match self {
46 Self::Integer { signed, size, .. } => {
47 write!(f, "{}{}", if *signed { "i" } else { "u" }, size * 8)
48 }
49 Self::Float { size } => write!(f, "f{}", size * 8),
50 Self::Bool => "bool".fmt(f),
51 Self::Char => "char".fmt(f),
52 Self::Str => "str".fmt(f),
53 Self::Any => "_".fmt(f),
54 Self::Never => "!".fmt(f),
55 Self::Unit(_) => "()".fmt(f),
56 Self::Tuple(items) => f.delimit("struct (", ")").list(items, ", "),
57 Self::Struct(items, _) => {
58 let mut f = f.delimit("struct { ", "}");
59 for (name, idx) in items {
60 write!(f, "{name}: {idx}, ")?;
61 }
62 Ok(())
63 }
64 Self::Enum(items) => {
65 let mut f = f.delimit_indented("enum {", "\n}");
66 for (name, idx) in items {
67 write!(f, "\n{name}: {idx},")?;
68 }
69 Ok(())
70 }
71 }
72 }
73}
74
75#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub struct TypeInfo {
78 pub ident: Symbol,
79 pub model: Model,
80}
81
82macro make_int($T:ty, $signed: expr) {
83 Model::Integer {
84 signed: $signed,
85 size: size_of::<$T>(),
86 min: <$T>::MIN as _,
87 max: <$T>::MAX as _,
88 }
89}
90
91impl TypeInfo {
92 pub fn new(ident: impl Into<Symbol>, model: Model) -> Self {
93 Self { ident: ident.into(), model }
94 }
95
96 pub fn default_int() -> Type {
97 Self::new("i128", make_int!(i128, true)).intern()
98 }
99
100 #[rustfmt::skip]
101 pub fn defaults() -> Vec<Self> {
102 let unknown = Self::new("_", Model::Any).intern();
103 let types = [
104 Self::new("_", Model::Any),
105 Self::new("unit", Model::Unit(0)),
106 Self::new("bool", Model::Bool),
107 Self::new("char", Model::Char),
108 Self::new("str", Model::Str),
109 Self::new("never", Model::Never),
110 Self::new("f32", Model::Float{size: size_of::<f32>()}),
111 Self::new("f64", Model::Float{size: size_of::<f64>()}),
112 Self::new("i8", make_int!(i8, true)),
113 Self::new("i16", make_int!(i16, true)),
114 Self::new("i32", make_int!(i32, true)),
115 Self::new("i64", make_int!(i64, true)),
116 Self::new("i128", make_int!(i128, true)),
117 Self::new("isize", make_int!(isize, true)),
118 Self::new("int", make_int!(isize, true)),
119 Self::new("u8", make_int!(u8, false)),
120 Self::new("u16", make_int!(u16, false)),
121 Self::new("u32", make_int!(u32, false)),
122 Self::new("u64", make_int!(u64, false)),
123 Self::new("u128", make_int!(u128, false)),
124 Self::new("usize", make_int!(usize, false)),
125 Self::new("uint", make_int!(usize, false)),
126 Self::new("RangeExc", Model::Tuple([unknown, unknown].into())),
127 Self::new("RangeInc", Model::Tuple([unknown, unknown].into())),
128 Self::new("RangeTo", Model::Tuple([unknown].into())),
129 Self::new("RangeToInc", Model::Tuple([unknown].into())),
130 ];
131 types.into()
132 }
133
134 pub fn getattr(&self, attr: Symbol) -> IResult<ConValue> {
135 Ok(match (&self.model, attr.0) {
136 (_, "Self") => ConValue::TypeInfo(self.already_interned()),
137 (&Model::Integer { signed, .. }, "SIGNED") => ConValue::Bool(signed),
138 (&Model::Integer { size, .. }, "SIZE") => ConValue::Int(size as _),
139 (&Model::Integer { size, .. }, "BITS") => ConValue::Int(8 * size as i128),
140 (&Model::Integer { min, .. }, "MIN") => ConValue::Int(min),
141 (&Model::Integer { max, .. }, "MAX") => ConValue::Int(max),
142 (&Model::Float { size }, "SIZE") => ConValue::Int(size as _),
143 (Model::Bool, "SIZE") => ConValue::Int(size_of::<bool>() as _),
144 (Model::Char, "SIZE") => ConValue::Int(size_of::<char>() as _),
145 (Model::Never, _) => Err(Error::NotDefined(attr))?,
146 (Model::Unit(_), "SIZE") => ConValue::Int(0),
147 (Model::Unit(_), _) => Err(Error::NotDefined(attr))?,
148 (Model::Tuple(items), "ARITY") => ConValue::Int(items.len() as _),
149 (Model::Struct(items, _), "NAMES") => {
150 ConValue::Array(items.iter().map(|(n, _)| ConValue::Str(*n)).collect())
151 }
152 (Model::Struct(items, _), "TYPES") => {
153 ConValue::Array(items.iter().map(|(_, t)| ConValue::TypeInfo(*t)).collect())
154 }
155 (Model::Struct(items, exhaustive), _) => items
156 .iter()
157 .find_map(|&(name, ty)| (name == attr).then_some(ConValue::TypeInfo(ty)))
158 .ok_or(Error::NotDefined(attr))?,
159 (Model::Enum(items), _) => items
160 .iter()
161 .find_map(|&(name, ty)| (name == attr).then_some(ConValue::TypeInfo(ty)))
162 .ok_or(Error::NotDefined(attr))?,
163 (model, _) => Err(Error::NotDefined(attr))?,
164 })
165 }
166
167 pub fn make_tuple(&self, values: Box<[ConValue]>) -> IResult<ConValue> {
168 let typeids = match &self.model {
169 Model::Tuple(typeids) => typeids,
170 _ => return Err(Error::TypeError(self.ident.to_ref(), "not that")),
171 };
172 if typeids.len() != values.len() {
173 return Err(Error::ArgNumber(typeids.len(), values.len()));
174 }
175 Ok(ConValue::TupleStruct(self.already_interned(), values))
176 }
177
178 pub fn make_struct(&self, mut values: HashMap<Symbol, ConValue>) -> IResult<ConValue> {
179 let (model, exhaustive) = match &self.model {
180 Model::Struct(model, exhaustive) => (model, exhaustive),
181 _ => Err(Error::TypeError(self.ident.to_ref(), "not that"))?,
182 };
183
184 let mut members = HashMap::new();
185 if *exhaustive {
186 for (key, _id) in model {
187 let value = values.get_mut(key).ok_or(Error::NotInitialized(*key))?;
188 members.insert(*key, value.take());
189 }
190 } else {
191 members = values;
192 }
193
194 Ok(ConValue::Struct(self.already_interned(), Box::new(members)))
195 }
196
197 pub fn intern(self) -> Type {
198 TYPE_INTERNER
199 .get_or_init(LeakyInterner::new)
200 .get_or_insert(self)
201 }
202 pub fn already_interned(&self) -> Type {
203 TYPE_INTERNER
204 .get_or_init(LeakyInterner::new)
205 .get(self)
206 .expect(&self.ident)
207 }
208}
209
210impl Callable for TypeInfo {
211 fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
212 match &self.model {
213 Model::Tuple(_) => self.make_tuple(args.into()),
214 _ => Err(Error::NotCallable(ConValue::TypeInfo(
215 self.already_interned(),
216 )))?,
217 }
218 }
219
220 fn name(&self) -> Option<Symbol> {
221 Some(self.ident)
222 }
223}
224
225impl std::fmt::Display for TypeInfo {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 let Self { ident: _, model } = self;
228 write!(f, "{model}")
229 }
230}