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
18pub(crate) static 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 Ref(Type),
36 Slice(Type),
38 Tuple(Box<[Type]>),
40 Struct(Box<[(Symbol, Type)]>, bool),
42 Enum(Box<[(Symbol, Type)]>),
44}
45
46impl Display for Model {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 use std::fmt::Write;
49 match self {
50 Self::Integer { signed, size, .. } => {
51 write!(f, "{}{}", if *signed { "i" } else { "u" }, size * 8)
52 }
53 Self::Float { size } => write!(f, "f{}", size * 8),
54 Self::Bool => "bool".fmt(f),
55 Self::Char => "char".fmt(f),
56 Self::Str => "str".fmt(f),
57 Self::Any => "_".fmt(f),
58 Self::Never => "!".fmt(f),
59 Self::Unit(_) => "()".fmt(f),
60 Self::Ref(t) => write!(f, "&{t}"),
61 Self::Slice(t) => write!(f, "[{t}]"),
62 Self::Tuple(items) => f.delimit("(", ")").list(items, ", "),
63 Self::Struct(items, _) => {
64 let mut f = f.delimit("{", " }");
65 for (idx, (name, ty)) in items.iter().enumerate() {
66 if idx > 0 {
67 write!(f, ",")?;
68 }
69 write!(f, " {name}: {ty}")?;
70 }
71 Ok(())
72 }
73 Self::Enum(items) => {
74 let mut f = f.delimit_indented("enum {", "\n}");
75 for (name, idx) in items {
76 write!(f, "\n{name}: {idx},")?;
77 }
78 Ok(())
79 }
80 }
81 }
82}
83
84#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
86pub struct TypeInfo {
87 pub ident: Option<Symbol>,
88 pub model: Model,
89}
90
91macro make_int($T:ty, $signed: expr) {
92 Model::Integer {
93 signed: $signed,
94 size: size_of::<$T>(),
95 min: <$T>::MIN as _,
96 max: <$T>::MAX as _,
97 }
98}
99
100impl TypeInfo {
101 pub fn new(ident: impl Into<Symbol>, model: Model) -> Self {
102 Self { ident: Some(ident.into()), model }
103 }
104
105 pub fn name(&self) -> &'static str {
106 match self.ident {
107 Some(name) => name.to_ref(),
108 None => "_",
109 }
110 }
111
112 pub fn default_int() -> Type {
113 Self::new("i128", make_int!(i128, true)).intern()
114 }
115
116 #[rustfmt::skip]
117 pub fn defaults() -> Vec<Self> {
118 let unknown = Self::new("_", Model::Any).intern();
119 let types = [
120 Self::new("_", Model::Any),
121 Self::new("unit", Model::Unit(0)),
122 Self::new("bool", Model::Bool),
123 Self::new("char", Model::Char),
124 Self::new("str", Model::Str),
125 Self::new("never", Model::Never),
126 Self::new("f32", Model::Float{size: size_of::<f32>()}),
127 Self::new("f64", Model::Float{size: size_of::<f64>()}),
128 Self::new("i8", make_int!(i8, true)),
129 Self::new("i16", make_int!(i16, true)),
130 Self::new("i32", make_int!(i32, true)),
131 Self::new("i64", make_int!(i64, true)),
132 Self::new("i128", make_int!(i128, true)),
133 Self::new("isize", make_int!(isize, true)),
134 Self::new("int", make_int!(isize, true)),
135 Self::new("u8", make_int!(u8, false)),
136 Self::new("u16", make_int!(u16, false)),
137 Self::new("u32", make_int!(u32, false)),
138 Self::new("u64", make_int!(u64, false)),
139 Self::new("u128", make_int!(u128, false)),
140 Self::new("usize", make_int!(usize, false)),
141 Self::new("uint", make_int!(usize, false)),
142 Self::new("RangeExc", Model::Tuple([unknown, unknown].into())),
143 Self::new("RangeInc", Model::Tuple([unknown, unknown].into())),
144 Self::new("RangeTo", Model::Tuple([unknown].into())),
145 Self::new("RangeToInc", Model::Tuple([unknown].into())),
146 ];
147 types.into()
148 }
149
150 pub fn getattr(&self, attr: Symbol) -> IResult<ConValue> {
151 Ok(match (&self.model, attr.0) {
152 (_, "Self") => ConValue::TypeInfo(self.already_interned()),
153 (&Model::Integer { signed, .. }, "SIGNED") => ConValue::Bool(signed),
154 (&Model::Integer { size, .. }, "SIZE") => ConValue::Int(size as _),
155 (&Model::Integer { size, .. }, "BITS") => ConValue::Int(8 * size as i128),
156 (&Model::Integer { min, .. }, "MIN") => ConValue::Int(min),
157 (&Model::Integer { max, .. }, "MAX") => ConValue::Int(max),
158 (&Model::Float { size }, "SIZE") => ConValue::Int(size as _),
159 (&Model::Float { .. }, "INF") => ConValue::Float(f64::INFINITY),
160 (&Model::Float { .. }, "NAN" | "NaN") => ConValue::Float(f64::NAN),
161 (Model::Bool, "SIZE") => ConValue::Int(size_of::<bool>() as _),
162 (Model::Char, "SIZE") => ConValue::Int(size_of::<char>() as _),
163 (Model::Never, _) => Err(Error::NotDefined(attr))?,
164 (Model::Unit(_), "SIZE") => ConValue::Int(0),
165 (Model::Unit(_), _) => Err(Error::NotDefined(attr))?,
166 (Model::Tuple(items), "ARITY") => ConValue::Int(items.len() as _),
167 (Model::Struct(items, _), "NAMES") => {
168 ConValue::Array(items.iter().map(|(n, _)| ConValue::Str(*n)).collect())
169 }
170 (Model::Struct(items, _), "TYPES") => {
171 ConValue::Array(items.iter().map(|(_, t)| ConValue::TypeInfo(*t)).collect())
172 }
173 (Model::Struct(items, _), "MEMBERS") => ConValue::Array(
174 items
175 .iter()
176 .map(|(n, t)| {
177 ConValue::Tuple([ConValue::Str(*n), ConValue::TypeInfo(*t)].into())
178 })
179 .collect(),
180 ),
181 (Model::Struct(items, exhaustive), _) => items
182 .iter()
183 .find_map(|&(name, ty)| (name == attr).then_some(ConValue::TypeInfo(ty)))
184 .ok_or(Error::NotDefined(attr))?,
185 (Model::Enum(items), _) => items
186 .iter()
187 .find_map(|&(name, ty)| (name == attr).then_some(ConValue::TypeInfo(ty)))
188 .ok_or(Error::NotDefined(attr))?,
189 (model, _) => Err(Error::NotDefined(attr))?,
190 })
191 }
192
193 pub fn make_tuple(&self, values: Box<[ConValue]>) -> IResult<ConValue> {
194 let Model::Tuple(typeids) = &self.model else {
195 Err(Error::TypeError(self.name(), "tuple struct"))?
196 };
197 if typeids.len() != values.len() {
198 return Err(Error::ArgNumber(typeids.len(), values.len()));
199 }
200 Ok(ConValue::TupleStruct(self.already_interned(), values))
201 }
202
203 pub fn make_struct(&self, mut values: HashMap<Symbol, ConValue>) -> IResult<ConValue> {
204 let Model::Struct(model, exhaustive) = &self.model else {
205 Err(Error::TypeError(self.name(), "struct"))?
206 };
207
208 let mut members = HashMap::new();
209 if *exhaustive {
210 for (key, _id) in model {
211 let value = values.get_mut(key).ok_or(Error::NotInitialized(*key))?;
212 members.insert(*key, value.take());
213 }
214 } else {
215 members = values;
216 }
217
218 Ok(ConValue::Struct(self.already_interned(), Box::new(members)))
219 }
220
221 pub fn intern(self) -> Type {
222 TYPE_INTERNER
223 .get_or_init(LeakyInterner::new)
224 .get_or_insert(self)
225 }
226 pub fn already_interned(&self) -> Type {
227 TYPE_INTERNER
228 .get_or_init(LeakyInterner::new)
229 .get(self)
230 .unwrap_or_else(|| panic!("{}", self.name()))
231 }
232}
233
234impl Callable for TypeInfo {
235 fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
236 match &self.model {
237 Model::Tuple(_) => self.make_tuple(args.into()),
238 _ => Err(Error::NotCallable(ConValue::TypeInfo(
239 self.already_interned(),
240 )))?,
241 }
242 }
243
244 fn name(&self) -> Option<Symbol> {
245 self.ident
246 }
247}
248
249impl std::fmt::Display for TypeInfo {
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251 let Self { ident, model } = self;
252 let Some(ident) = ident else {
253 return model.fmt(f);
254 };
255 match model {
256 Model::Any | Model::Unit(0) => write!(f, "{ident}"),
257 Model::Unit(n) => write!(f, "{ident} = {n}"),
258 Model::Integer { .. }
259 | Model::Float { .. }
260 | Model::Bool
261 | Model::Char
262 | Model::Str
263 | Model::Never
264 | Model::Ref(_)
265 | Model::Slice(_) => write!(f, "{model}"),
266 Model::Tuple(_) | Model::Struct(_, _) | Model::Enum(_) => {
267 write!(f, "{ident} {model}")
268 }
269 }
270 }
271}