1use crate::references::reference::Reference;
2use crate::references::type_reference::{
3 NominalTypeDeclaration, TypeReference,
4};
5use crate::runtime::memory::Memory;
6use crate::types::definition::TypeDefinition;
7use crate::types::type_container::TypeContainer;
8use crate::values::core_values::decimal::typed_decimal::DecimalTypeVariant;
9use crate::values::core_values::integer::typed_integer::IntegerTypeVariant;
10use crate::values::core_values::r#type::Type;
11use datex_core::values::core_values::map::Map;
12use datex_core::values::pointer::PointerAddress;
13use datex_core::values::value_container::ValueContainer;
14use datex_macros::LibTypeString;
15use std::cell::RefCell;
16use std::collections::HashMap;
17use std::iter::once;
18use std::rc::Rc;
19use strum::IntoEnumIterator;
20
21thread_local! {
22 pub static CORE_LIB_TYPES: HashMap<CoreLibPointerId, TypeContainer> = create_core_lib();
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Hash, LibTypeString)]
26pub enum CoreLibPointerId {
27 Core, Type, Null, Boolean, Integer(Option<IntegerTypeVariant>), Decimal(Option<DecimalTypeVariant>), Text, Endpoint, List, Map, Function, Unit, }
40
41impl CoreLibPointerId {
42 const INTEGER_BASE: u16 = 100;
43 const DECIMAL_BASE: u16 = 300;
44
45 pub fn to_u16(&self) -> u16 {
46 match self {
47 CoreLibPointerId::Core => 0,
48 CoreLibPointerId::Null => 1,
49 CoreLibPointerId::Type => 2,
50 CoreLibPointerId::Boolean => 3,
51 CoreLibPointerId::Function => 5,
52 CoreLibPointerId::Endpoint => 7,
53 CoreLibPointerId::Text => 8,
54 CoreLibPointerId::List => 9,
55 CoreLibPointerId::Unit => 11,
56 CoreLibPointerId::Map => 12,
57 CoreLibPointerId::Integer(None) => Self::INTEGER_BASE,
58 CoreLibPointerId::Integer(Some(v)) => {
59 let v: u8 = (*v).into();
60 CoreLibPointerId::Integer(None).to_u16() + v as u16
61 }
62 CoreLibPointerId::Decimal(None) => Self::DECIMAL_BASE,
63 CoreLibPointerId::Decimal(Some(v)) => {
64 let v: u8 = (*v).into();
65 CoreLibPointerId::Decimal(None).to_u16() + v as u16
66 }
67 }
68 }
69
70 pub fn from_u16(id: u16) -> Option<Self> {
71 match id {
72 0 => Some(CoreLibPointerId::Core),
73 1 => Some(CoreLibPointerId::Null),
74 2 => Some(CoreLibPointerId::Type),
75 3 => Some(CoreLibPointerId::Boolean),
76 5 => Some(CoreLibPointerId::Function),
77 7 => Some(CoreLibPointerId::Endpoint),
78 8 => Some(CoreLibPointerId::Text),
79 9 => Some(CoreLibPointerId::List),
80 11 => Some(CoreLibPointerId::Unit),
81 12 => Some(CoreLibPointerId::Map),
82
83 Self::INTEGER_BASE => Some(CoreLibPointerId::Integer(None)),
84 n if (Self::INTEGER_BASE + 1..Self::DECIMAL_BASE).contains(&n) => {
85 IntegerTypeVariant::try_from((n - Self::INTEGER_BASE) as u8)
86 .ok()
87 .map(|v| CoreLibPointerId::Integer(Some(v)))
88 }
89
90 Self::DECIMAL_BASE => Some(CoreLibPointerId::Decimal(None)),
91 n if n > Self::DECIMAL_BASE => {
92 DecimalTypeVariant::try_from((n - Self::DECIMAL_BASE) as u8)
93 .ok()
94 .map(|v| CoreLibPointerId::Decimal(Some(v)))
95 }
96
97 _ => None,
98 }
99 }
100}
101
102impl From<CoreLibPointerId> for PointerAddress {
103 fn from(id: CoreLibPointerId) -> Self {
104 let id_bytes: [u8; 3] =
105 (id.to_u16() as u32).to_le_bytes()[0..3].try_into().unwrap();
106 PointerAddress::Internal(id_bytes)
107 }
108}
109
110impl TryFrom<&PointerAddress> for CoreLibPointerId {
111 type Error = String;
112 fn try_from(address: &PointerAddress) -> Result<Self, Self::Error> {
113 match address {
114 PointerAddress::Internal(id_bytes) => {
115 let mut id_array = [0u8; 4];
116 id_array[0..3].copy_from_slice(id_bytes);
117 let id = u32::from_le_bytes(id_array);
118 match CoreLibPointerId::from_u16(id as u16) {
119 Some(core_id) => Ok(core_id),
120 None => Err("Invalid CoreLibPointerId".to_string()),
121 }
122 }
123 e => Err(format!(
124 "CoreLibPointerId can only be created from Internal PointerAddress, got: {:?}",
125 e
126 )),
127 }
128 }
129}
130
131pub fn get_core_lib_type(id: impl Into<CoreLibPointerId>) -> TypeContainer {
132 let id = id.into();
133 if !has_core_lib_type(id.clone()) {
134 panic!("Core lib type not found: {:?}", id);
135 }
136 CORE_LIB_TYPES.with(|core| core.get(&id).unwrap().clone())
137}
138
139pub fn get_core_lib_type_reference(
140 id: impl Into<CoreLibPointerId>,
141) -> Rc<RefCell<TypeReference>> {
142 let type_container = get_core_lib_type(id);
143 match type_container {
144 TypeContainer::TypeReference(tr) => tr,
145 _ => panic!("Core lib type is not a TypeReference"),
146 }
147}
148
149fn has_core_lib_type<T>(id: T) -> bool
150where
151 T: Into<CoreLibPointerId>,
152{
153 CORE_LIB_TYPES.with(|core| core.contains_key(&id.into()))
154}
155
156pub fn load_core_lib(memory: &mut Memory) {
158 CORE_LIB_TYPES.with(|core| {
159 let structure = core
160 .values()
161 .map(|def| match def {
162 TypeContainer::TypeReference(def) => {
163 let name = def
164 .borrow()
165 .nominal_type_declaration
166 .as_ref()
167 .unwrap()
168 .to_string();
169 let reference = Reference::TypeReference(def.clone());
170 memory.register_reference(&reference);
171 (name, ValueContainer::Reference(reference))
172 }
173 _ => panic!("Core lib type is not a TypeReference"),
174 })
175 .collect::<Vec<(String, ValueContainer)>>();
176
177 let core_struct =
180 Reference::from(ValueContainer::from(Map::from_iter(structure)));
181 core_struct.set_pointer_address(CoreLibPointerId::Core.into());
182 memory.register_reference(&core_struct);
183 });
184}
185
186pub fn create_core_lib() -> HashMap<CoreLibPointerId, TypeContainer> {
189 let integer = integer();
190 let decimal = decimal();
191 vec![
192 r#type(),
193 text(),
194 list(),
195 boolean(),
196 endpoint(),
197 unit(),
198 map(),
199 null(),
200 ]
201 .into_iter()
202 .chain(once(integer.clone()))
203 .chain(
204 IntegerTypeVariant::iter()
205 .map(|variant| integer_variant(integer.1.clone(), variant)),
206 )
207 .chain(once(decimal.clone()))
208 .chain(
209 DecimalTypeVariant::iter()
210 .map(|variant| decimal_variant(decimal.1.clone(), variant)),
211 )
212 .collect::<HashMap<CoreLibPointerId, TypeContainer>>()
213}
214
215type CoreLibTypeDefinition = (CoreLibPointerId, TypeContainer);
216pub fn r#type() -> CoreLibTypeDefinition {
217 create_core_type("type", None, None, CoreLibPointerId::Type)
218}
219pub fn null() -> CoreLibTypeDefinition {
220 create_core_type("null", None, None, CoreLibPointerId::Null)
221}
222pub fn list() -> CoreLibTypeDefinition {
223 create_core_type("List", None, None, CoreLibPointerId::List)
224}
225pub fn map() -> CoreLibTypeDefinition {
226 create_core_type("Map", None, None, CoreLibPointerId::Map)
227}
228
229pub fn unit() -> CoreLibTypeDefinition {
230 create_core_type("Unit", None, None, CoreLibPointerId::Unit)
231}
232
233pub fn boolean() -> CoreLibTypeDefinition {
234 create_core_type("boolean", None, None, CoreLibPointerId::Boolean)
235}
236
237pub fn decimal() -> CoreLibTypeDefinition {
238 create_core_type("decimal", None, None, CoreLibPointerId::Decimal(None))
239}
240
241pub fn decimal_variant(
242 base_type: TypeContainer,
243 variant: DecimalTypeVariant,
244) -> CoreLibTypeDefinition {
245 let variant_name = variant.as_ref().to_string();
246 create_core_type(
247 "decimal",
248 Some(variant_name),
249 Some(base_type),
250 CoreLibPointerId::Decimal(Some(variant)),
251 )
252}
253pub fn endpoint() -> CoreLibTypeDefinition {
254 create_core_type("endpoint", None, None, CoreLibPointerId::Endpoint)
255}
256
257pub fn text() -> CoreLibTypeDefinition {
258 create_core_type("text", None, None, CoreLibPointerId::Text)
259}
260
261pub fn integer() -> CoreLibTypeDefinition {
262 create_core_type("integer", None, None, CoreLibPointerId::Integer(None))
263}
264
265pub fn integer_variant(
266 base_type: TypeContainer,
267 variant: IntegerTypeVariant,
268) -> CoreLibTypeDefinition {
269 let variant_name = variant.as_ref().to_string();
270 create_core_type(
271 "integer",
272 Some(variant_name),
273 Some(base_type),
274 CoreLibPointerId::Integer(Some(variant)),
275 )
276}
277
278fn create_core_type(
280 name: &str,
281 variant: Option<String>,
282 base_type: Option<TypeContainer>,
283 pointer_id: CoreLibPointerId,
284) -> CoreLibTypeDefinition {
285 let base_type_ref = match base_type {
286 Some(TypeContainer::TypeReference(reference)) => Some(reference),
287 Some(TypeContainer::Type(_)) => {
288 panic!("Base type must be a TypeReference")
289 }
290 None => None,
291 };
292 (
293 pointer_id.clone(),
294 TypeContainer::TypeReference(Rc::new(RefCell::new(TypeReference {
295 nominal_type_declaration: Some(NominalTypeDeclaration {
296 name: name.to_string(),
297 variant,
298 }),
299 type_value: Type {
300 base_type: base_type_ref,
301 reference_mutability: None,
302 type_definition: TypeDefinition::Unit,
303 },
304 pointer_address: Some(PointerAddress::from(pointer_id)),
305 }))),
306 )
307}
308
309#[cfg(test)]
310mod tests {
311 use crate::values::core_values::endpoint::Endpoint;
312
313 use super::*;
314 use itertools::Itertools;
315 use std::{assert_matches::assert_matches, str::FromStr};
316
317 #[test]
318 fn core_lib() {
319 assert!(has_core_lib_type(CoreLibPointerId::Endpoint));
320 assert!(has_core_lib_type(CoreLibPointerId::Null));
321 assert!(has_core_lib_type(CoreLibPointerId::Boolean));
322 assert!(has_core_lib_type(CoreLibPointerId::Integer(None)));
323 assert!(has_core_lib_type(CoreLibPointerId::Decimal(None)));
324 for variant in IntegerTypeVariant::iter() {
325 assert!(has_core_lib_type(CoreLibPointerId::Integer(Some(
326 variant
327 ))));
328 }
329 for variant in DecimalTypeVariant::iter() {
330 assert!(has_core_lib_type(CoreLibPointerId::Decimal(Some(
331 variant
332 ))));
333 }
334 }
335
336 #[test]
337 fn debug() {
338 let mut memory = Memory::new(Endpoint::LOCAL);
339 load_core_lib(&mut memory);
340 println!(
341 "{}",
342 memory
343 .get_value_reference(&CoreLibPointerId::Core.into())
344 .unwrap()
345 .borrow()
346 .value_container
347 );
348 }
349
350 #[test]
351 fn core_lib_type_addresses() {
352 let integer_base = "integer";
353 let integer_u8 = "integer/u8";
354 let integer_i32 = "integer/i32";
355 let decimal_base = "decimal";
356 let decimal_f64 = "decimal/f64";
357
358 assert_eq!(
359 CoreLibPointerId::from_str(integer_base),
360 Ok(CoreLibPointerId::Integer(None))
361 );
362 assert_eq!(
363 CoreLibPointerId::from_str(integer_u8),
364 Ok(CoreLibPointerId::Integer(Some(IntegerTypeVariant::U8)))
365 );
366 assert_eq!(
367 CoreLibPointerId::from_str(integer_i32),
368 Ok(CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32)))
369 );
370 assert_eq!(
371 CoreLibPointerId::from_str(decimal_base),
372 Ok(CoreLibPointerId::Decimal(None))
373 );
374 assert_eq!(
375 CoreLibPointerId::from_str(decimal_f64),
376 Ok(CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64)))
377 );
378
379 assert_eq!(CoreLibPointerId::Integer(None).to_string(), integer_base);
380 assert_eq!(
381 CoreLibPointerId::Integer(Some(IntegerTypeVariant::U8)).to_string(),
382 integer_u8
383 );
384 assert_eq!(
385 CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32))
386 .to_string(),
387 integer_i32
388 );
389 assert_eq!(CoreLibPointerId::Decimal(None).to_string(), decimal_base);
390 assert_eq!(
391 CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64))
392 .to_string(),
393 decimal_f64
394 );
395 }
396
397 #[test]
398 fn core_lib_pointer_id_conversion() {
399 let core_id = CoreLibPointerId::Core;
400 let pointer_address: PointerAddress = core_id.clone().into();
401 let converted_id: CoreLibPointerId =
402 (&pointer_address).try_into().unwrap();
403 assert_eq!(core_id, converted_id);
404
405 let boolean_id = CoreLibPointerId::Boolean;
406 let pointer_address: PointerAddress = boolean_id.clone().into();
407 let converted_id: CoreLibPointerId =
408 (&pointer_address).try_into().unwrap();
409 assert_eq!(boolean_id, converted_id);
410
411 let integer_id =
412 CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32));
413 let pointer_address: PointerAddress = integer_id.clone().into();
414 let converted_id: CoreLibPointerId =
415 (&pointer_address).try_into().unwrap();
416 assert_eq!(integer_id, converted_id);
417
418 let decimal_id =
419 CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64));
420 let pointer_address: PointerAddress = decimal_id.clone().into();
421 let converted_id: CoreLibPointerId =
422 (&pointer_address).try_into().unwrap();
423 assert_eq!(decimal_id, converted_id);
424
425 let type_id = CoreLibPointerId::Type;
426 let pointer_address: PointerAddress = type_id.clone().into();
427 let converted_id: CoreLibPointerId =
428 (&pointer_address).try_into().unwrap();
429 assert_eq!(type_id, converted_id);
430 }
431
432 #[test]
433 fn base_type_simple() {
434 let integer_type = get_core_lib_type(CoreLibPointerId::Integer(None));
436 let integer_base = integer_type.base_type();
437 assert_matches!(integer_base, TypeContainer::TypeReference(_));
438 assert_eq!(integer_base.to_string(), "integer");
439
440 let base = integer_base.base_type();
441 assert_matches!(base, TypeContainer::TypeReference(_));
442 assert_eq!(base.to_string(), "integer");
443
444 assert_eq!(integer_base, base);
445 }
446
447 #[test]
448 fn base_type_complex() {
449 let integer_u8_type = get_core_lib_type(CoreLibPointerId::Integer(
451 Some(IntegerTypeVariant::U8),
452 ));
453 assert_matches!(integer_u8_type, TypeContainer::TypeReference(_));
454 assert_eq!(integer_u8_type.to_string(), "integer/u8");
455
456 let integer = integer_u8_type.base_type();
457 assert_matches!(integer, TypeContainer::TypeReference(_));
458 assert_eq!(integer.to_string(), "integer");
459 assert_ne!(integer, integer_u8_type);
460
461 let integer_again = integer.base_type();
462 assert_matches!(integer_again, TypeContainer::TypeReference(_));
463 assert_eq!(integer_again.to_string(), "integer");
464 assert_eq!(integer_again, integer);
465 }
466
467 #[ignore]
468 #[test]
469 fn print_core_lib_addresses_as_hex() {
470 let sorted_entries = CORE_LIB_TYPES.with(|core| {
471 core.keys()
472 .map(|k| (k.clone(), PointerAddress::from(k.clone())))
473 .sorted_by_key(|(_, address)| address.bytes().to_vec())
474 .collect::<Vec<_>>()
475 });
476 for (core_lib_id, address) in sorted_entries {
477 println!("{:?}: {}", core_lib_id, address);
478 }
479 }
480}