1use crate::collections::HashMap;
2use crate::references::reference::Reference;
3use crate::references::type_reference::{
4 NominalTypeDeclaration, TypeReference,
5};
6use crate::runtime::memory::Memory;
7use crate::stdlib::boxed::Box;
8use crate::stdlib::format;
9use crate::stdlib::rc::Rc;
10use crate::stdlib::string::String;
11use crate::stdlib::string::ToString;
12use crate::stdlib::vec;
13use crate::stdlib::vec::Vec;
14use crate::types::definition::TypeDefinition;
15use crate::types::structural_type_definition::StructuralTypeDefinition;
16use crate::values::core_value::CoreValue;
17use crate::values::core_values::callable::{
18 Callable, CallableBody, CallableKind, CallableSignature,
19};
20use crate::values::core_values::decimal::typed_decimal::DecimalTypeVariant;
21use crate::values::core_values::integer::typed_integer::IntegerTypeVariant;
22use crate::values::core_values::map::Map;
23use crate::values::core_values::r#type::Type;
24use crate::values::pointer::PointerAddress;
25use crate::values::value::Value;
26use crate::values::value_container::ValueContainer;
27use core::cell::RefCell;
28use core::iter::once;
29use core::prelude::rust_2024::*;
30use core::result::Result;
31use datex_core::values::core_values::integer::Integer;
32use datex_macros::LibTypeString;
33use log::info;
34use strum::IntoEnumIterator;
35
36type CoreLibTypes = HashMap<CoreLibPointerId, Type>;
37type CoreLibVals = HashMap<CoreLibPointerId, ValueContainer>;
38
39#[cfg_attr(not(feature = "embassy_runtime"), thread_local)]
40pub static mut CORE_LIB_TYPES: Option<CoreLibTypes> = None;
41
42#[cfg_attr(not(feature = "embassy_runtime"), thread_local)]
43pub static mut CORE_LIB_VALS: Option<CoreLibVals> = None;
44
45fn with_full_core_lib<R>(
46 handler: impl FnOnce(&CoreLibTypes, &CoreLibVals) -> R,
47) -> R {
48 unsafe {
49 if CORE_LIB_TYPES.is_none() {
50 CORE_LIB_TYPES.replace(create_core_lib_types());
51 }
52 if CORE_LIB_VALS.is_none() {
53 CORE_LIB_VALS.replace(create_core_lib_vals());
54 }
55 handler(
56 CORE_LIB_TYPES.as_ref().unwrap_unchecked(),
57 CORE_LIB_VALS.as_ref().unwrap_unchecked(),
58 )
59 }
60}
61
62fn with_core_lib_types<R>(handler: impl FnOnce(&CoreLibTypes) -> R) -> R {
63 unsafe {
64 if CORE_LIB_TYPES.is_none() {
65 CORE_LIB_TYPES.replace(create_core_lib_types());
66 }
67 handler(CORE_LIB_TYPES.as_ref().unwrap_unchecked())
68 }
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Hash, LibTypeString)]
72pub enum CoreLibPointerId {
73 Core, Type, Null, Boolean, Integer(Option<IntegerTypeVariant>), Decimal(Option<DecimalTypeVariant>), Text, Endpoint, List, Map, Callable, Unit, Never, Unknown, Print, }
89
90impl CoreLibPointerId {
91 const INTEGER_BASE: u16 = 100;
92 const DECIMAL_BASE: u16 = 300;
93
94 pub fn to_u16(&self) -> u16 {
95 match self {
96 CoreLibPointerId::Core => 0,
97 CoreLibPointerId::Null => 1,
98 CoreLibPointerId::Type => 2,
99 CoreLibPointerId::Boolean => 3,
100 CoreLibPointerId::Callable => 5,
101 CoreLibPointerId::Endpoint => 7,
102 CoreLibPointerId::Text => 8,
103 CoreLibPointerId::List => 9,
104 CoreLibPointerId::Unit => 11,
105 CoreLibPointerId::Map => 12,
106 CoreLibPointerId::Never => 13,
107 CoreLibPointerId::Unknown => 14,
108 CoreLibPointerId::Print => 15,
109 CoreLibPointerId::Integer(None) => Self::INTEGER_BASE,
110 CoreLibPointerId::Integer(Some(v)) => {
111 let v: u8 = (*v).into();
112 CoreLibPointerId::Integer(None).to_u16() + v as u16
113 }
114 CoreLibPointerId::Decimal(None) => Self::DECIMAL_BASE,
115 CoreLibPointerId::Decimal(Some(v)) => {
116 let v: u8 = (*v).into();
117 CoreLibPointerId::Decimal(None).to_u16() + v as u16
118 }
119 }
120 }
121
122 pub fn from_u16(id: u16) -> Option<Self> {
123 match id {
124 0 => Some(CoreLibPointerId::Core),
125 1 => Some(CoreLibPointerId::Null),
126 2 => Some(CoreLibPointerId::Type),
127 3 => Some(CoreLibPointerId::Boolean),
128 5 => Some(CoreLibPointerId::Callable),
129 7 => Some(CoreLibPointerId::Endpoint),
130 8 => Some(CoreLibPointerId::Text),
131 9 => Some(CoreLibPointerId::List),
132 11 => Some(CoreLibPointerId::Unit),
133 12 => Some(CoreLibPointerId::Map),
134 13 => Some(CoreLibPointerId::Never),
135 14 => Some(CoreLibPointerId::Unknown),
136 15 => Some(CoreLibPointerId::Print),
137
138 Self::INTEGER_BASE => Some(CoreLibPointerId::Integer(None)),
139 n if (Self::INTEGER_BASE + 1..Self::DECIMAL_BASE).contains(&n) => {
140 IntegerTypeVariant::try_from((n - Self::INTEGER_BASE) as u8)
141 .ok()
142 .map(|v| CoreLibPointerId::Integer(Some(v)))
143 }
144
145 Self::DECIMAL_BASE => Some(CoreLibPointerId::Decimal(None)),
146 n if n > Self::DECIMAL_BASE => {
147 DecimalTypeVariant::try_from((n - Self::DECIMAL_BASE) as u8)
148 .ok()
149 .map(|v| CoreLibPointerId::Decimal(Some(v)))
150 }
151
152 _ => None,
153 }
154 }
155}
156
157impl From<CoreLibPointerId> for PointerAddress {
158 fn from(id: CoreLibPointerId) -> Self {
159 let id_bytes: [u8; 3] =
160 (id.to_u16() as u32).to_le_bytes()[0..3].try_into().unwrap();
161 PointerAddress::Internal(id_bytes)
162 }
163}
164
165impl TryFrom<&PointerAddress> for CoreLibPointerId {
166 type Error = String;
167 fn try_from(address: &PointerAddress) -> Result<Self, Self::Error> {
168 match address {
169 PointerAddress::Internal(id_bytes) => {
170 let mut id_array = [0u8; 4];
171 id_array[0..3].copy_from_slice(id_bytes);
172 let id = u32::from_le_bytes(id_array);
173 match CoreLibPointerId::from_u16(id as u16) {
174 Some(core_id) => Ok(core_id),
175 None => Err("Invalid CoreLibPointerId".to_string()),
176 }
177 }
178 e => Err(format!(
179 "CoreLibPointerId can only be created from Internal PointerAddress, got: {:?}",
180 e
181 )),
182 }
183 }
184}
185
186pub fn get_core_lib_type(id: impl Into<CoreLibPointerId>) -> Type {
187 with_core_lib_types(|core_lib_types| {
188 core_lib_types.get(&id.into()).unwrap().clone()
189 })
190}
191
192pub fn get_core_lib_type_reference(
193 id: impl Into<CoreLibPointerId>,
194) -> Rc<RefCell<TypeReference>> {
195 let type_container = get_core_lib_type(id);
196 match type_container.type_definition {
197 TypeDefinition::Reference(tr) => tr,
198 _ => core::panic!("Core lib type is not a TypeReference"),
199 }
200}
201
202pub fn get_core_lib_value(
204 id: impl Into<CoreLibPointerId>,
205) -> Option<ValueContainer> {
206 let id = id.into();
207 with_full_core_lib(|core_lib_types, core_lib_values| {
208 if let Some(ty) = core_lib_types.get(&id) {
210 match &ty.type_definition {
211 TypeDefinition::Reference(tr) => {
212 Some(ValueContainer::Reference(Reference::TypeReference(
213 tr.clone(),
214 )))
215 }
216 _ => core::panic!("Core lib type is not a TypeReference"),
217 }
218 } else if let Some(val) = core_lib_values.get(&id) {
219 Some(val.clone())
220 } else {
221 None
222 }
223 })
224}
225
226pub fn get_core_lib_type_definition(
227 id: impl Into<CoreLibPointerId>,
228) -> TypeDefinition {
229 get_core_lib_type(id).type_definition
230}
231
232fn has_core_lib_type<T>(id: T) -> bool
233where
234 T: Into<CoreLibPointerId>,
235{
236 with_core_lib_types(|core_lib_types| {
237 core_lib_types.contains_key(&id.into())
238 })
239}
240
241pub fn load_core_lib(memory: &mut Memory) {
243 with_full_core_lib(|core_lib_types, core_lib_values| {
244 let mut types_structure = core_lib_types
245 .values()
246 .map(|ty| match &ty.type_definition {
247 TypeDefinition::Reference(type_reference) => {
248 let name = type_reference
249 .borrow()
250 .nominal_type_declaration
251 .as_ref()
252 .unwrap()
253 .to_string();
254 let reference =
255 Reference::TypeReference(type_reference.clone());
256 memory.register_reference(&reference);
257 (name, ValueContainer::Reference(reference))
258 }
259 _ => core::panic!("Core lib type is not a TypeReference"),
260 })
261 .collect::<Vec<(String, ValueContainer)>>();
262
263 for (name, val) in core_lib_values.iter() {
265 let name = name.to_string();
266 types_structure.push((name, val.clone()));
267 }
268
269 let core_struct = Reference::from(ValueContainer::from(
272 Map::from_iter(types_structure),
273 ));
274 core_struct.set_pointer_address(CoreLibPointerId::Core.into());
275 memory.register_reference(&core_struct);
276 });
277}
278
279pub fn create_core_lib_types() -> HashMap<CoreLibPointerId, Type> {
282 let integer = integer();
283 let decimal = decimal();
284 vec![
285 ty(),
286 text(),
287 list(),
288 boolean(),
289 endpoint(),
290 unit(),
291 never(),
292 unknown(),
293 map(),
294 null(),
295 callable(),
296 ]
297 .into_iter()
298 .chain(once(integer.clone()))
299 .chain(
300 IntegerTypeVariant::iter()
301 .map(|variant| integer_variant(integer.1.clone(), variant)),
302 )
303 .chain(once(decimal.clone()))
304 .chain(
305 DecimalTypeVariant::iter()
306 .map(|variant| decimal_variant(decimal.1.clone(), variant)),
307 )
308 .collect::<HashMap<CoreLibPointerId, Type>>()
309}
310
311pub fn create_core_lib_vals() -> HashMap<CoreLibPointerId, ValueContainer> {
312 vec![print()]
313 .into_iter()
314 .collect::<HashMap<CoreLibPointerId, ValueContainer>>()
315}
316
317type CoreLibTypeDefinition = (CoreLibPointerId, Type);
318pub fn ty() -> CoreLibTypeDefinition {
319 create_core_type("type", None, None, CoreLibPointerId::Type)
320}
321pub fn null() -> CoreLibTypeDefinition {
322 create_core_type("null", None, None, CoreLibPointerId::Null)
323}
324pub fn list() -> CoreLibTypeDefinition {
325 create_core_type("List", None, None, CoreLibPointerId::List)
326}
327pub fn map() -> CoreLibTypeDefinition {
328 create_core_type("Map", None, None, CoreLibPointerId::Map)
329}
330
331pub fn unit() -> CoreLibTypeDefinition {
332 create_core_type("Unit", None, None, CoreLibPointerId::Unit)
333}
334
335pub fn never() -> CoreLibTypeDefinition {
336 create_core_type("never", None, None, CoreLibPointerId::Never)
337}
338
339pub fn unknown() -> CoreLibTypeDefinition {
340 create_core_type("unknown", None, None, CoreLibPointerId::Unknown)
341}
342
343pub fn boolean() -> CoreLibTypeDefinition {
344 create_core_type("boolean", None, None, CoreLibPointerId::Boolean)
345}
346
347pub fn decimal() -> CoreLibTypeDefinition {
348 create_core_type("decimal", None, None, CoreLibPointerId::Decimal(None))
349}
350
351pub fn callable() -> CoreLibTypeDefinition {
352 create_core_type("Callable", None, None, CoreLibPointerId::Callable)
353}
354
355pub fn decimal_variant(
356 base_type: Type,
357 variant: DecimalTypeVariant,
358) -> CoreLibTypeDefinition {
359 let variant_name = variant.as_ref().to_string();
360 create_core_type(
361 "decimal",
362 Some(variant_name),
363 Some(base_type),
364 CoreLibPointerId::Decimal(Some(variant)),
365 )
366}
367pub fn endpoint() -> CoreLibTypeDefinition {
368 create_core_type("endpoint", None, None, CoreLibPointerId::Endpoint)
369}
370
371pub fn text() -> CoreLibTypeDefinition {
372 create_core_type("text", None, None, CoreLibPointerId::Text)
373}
374
375pub fn integer() -> CoreLibTypeDefinition {
376 create_core_type("integer", None, None, CoreLibPointerId::Integer(None))
377}
378
379pub fn integer_variant(
380 base_type: Type,
381 variant: IntegerTypeVariant,
382) -> CoreLibTypeDefinition {
383 let variant_name = variant.as_ref().to_string();
384 create_core_type(
385 "integer",
386 Some(variant_name),
387 Some(base_type),
388 CoreLibPointerId::Integer(Some(variant)),
389 )
390}
391
392pub fn print() -> (CoreLibPointerId, ValueContainer) {
393 (
394 CoreLibPointerId::Print,
395 ValueContainer::Value(Value::callable(
396 Some("print".to_string()),
397 CallableSignature {
398 kind: CallableKind::Function,
399 parameter_types: vec![],
400 rest_parameter_type: Some((
401 Some("values".to_string()),
402 Box::new(Type::unknown()),
403 )),
404 return_type: None,
405 yeet_type: None,
406 },
407 CallableBody::Native(|mut args: &[ValueContainer]| {
408 let mut output = String::new();
411
412 if let Some(ValueContainer::Value(Value {
414 inner: CoreValue::Text(text),
415 ..
416 })) = args.get(0)
417 {
418 output.push_str(&text.0);
419 args = &args[1..];
421 if !args.is_empty() {
423 output.push(' ');
424 }
425 }
426
427 #[cfg(feature = "decompiler")]
428 let args_string = args
429 .iter()
430 .map(|v| {
431 crate::decompiler::decompile_value(
432 v,
433 crate::decompiler::DecompileOptions::colorized(),
434 )
435 })
436 .collect::<Vec<_>>()
437 .join(" ");
438 #[cfg(not(feature = "decompiler"))]
439 let args_string = args
440 .iter()
441 .map(|v| v.to_string())
442 .collect::<Vec<_>>()
443 .join(" ");
444 output.push_str(&args_string);
445
446 #[cfg(feature = "std")]
447 println!("[PRINT] {}", output);
448 info!("[PRINT] {}", output);
449 Ok(None)
450 }),
451 )),
452 )
453}
454
455fn create_core_type(
457 name: &str,
458 variant: Option<String>,
459 base_type: Option<Type>,
460 pointer_id: CoreLibPointerId,
461) -> CoreLibTypeDefinition {
462 let base_type_ref = match base_type {
463 Some(Type {
464 type_definition: TypeDefinition::Reference(reference),
465 ..
466 }) => Some(reference),
467 Some(_) => {
468 core::panic!("Base type must be a Reference")
469 }
470 None => None,
471 };
472 (
473 pointer_id.clone(),
474 Type::new(
475 TypeDefinition::reference(Rc::new(RefCell::new(TypeReference {
476 nominal_type_declaration: Some(NominalTypeDeclaration {
477 name: name.to_string(),
478 variant,
479 }),
480 type_value: Type {
481 base_type: base_type_ref,
482 reference_mutability: None,
483 type_definition: TypeDefinition::Unit,
484 },
485 pointer_address: Some(PointerAddress::from(pointer_id)),
486 }))),
487 None,
488 ),
489 )
490}
491
492#[cfg(test)]
493mod tests {
494 use crate::values::core_values::endpoint::Endpoint;
495
496 use super::*;
497 use crate::stdlib::{assert_matches::assert_matches, str::FromStr};
498 use itertools::Itertools;
499
500 #[test]
501 fn core_lib() {
502 assert!(has_core_lib_type(CoreLibPointerId::Endpoint));
503 assert!(has_core_lib_type(CoreLibPointerId::Null));
504 assert!(has_core_lib_type(CoreLibPointerId::Boolean));
505 assert!(has_core_lib_type(CoreLibPointerId::Integer(None)));
506 assert!(has_core_lib_type(CoreLibPointerId::Decimal(None)));
507 assert!(has_core_lib_type(CoreLibPointerId::Type));
508 assert!(has_core_lib_type(CoreLibPointerId::Text));
509 assert!(has_core_lib_type(CoreLibPointerId::List));
510 assert!(has_core_lib_type(CoreLibPointerId::Map));
511 assert!(has_core_lib_type(CoreLibPointerId::Callable));
512 assert!(has_core_lib_type(CoreLibPointerId::Unit));
513 assert!(has_core_lib_type(CoreLibPointerId::Never));
514 assert!(has_core_lib_type(CoreLibPointerId::Unknown));
515 for variant in IntegerTypeVariant::iter() {
516 assert!(has_core_lib_type(CoreLibPointerId::Integer(Some(
517 variant
518 ))));
519 }
520 for variant in DecimalTypeVariant::iter() {
521 assert!(has_core_lib_type(CoreLibPointerId::Decimal(Some(
522 variant
523 ))));
524 }
525 }
526
527 #[test]
528 fn debug() {
529 let mut memory = Memory::new(Endpoint::LOCAL);
530 load_core_lib(&mut memory);
531 println!(
532 "{}",
533 memory
534 .get_value_reference(&CoreLibPointerId::Core.into())
535 .unwrap()
536 .borrow()
537 .value_container
538 );
539 }
540
541 #[test]
542 fn core_lib_type_addresses() {
543 let integer_base = "integer";
544 let integer_u8 = "integer/u8";
545 let integer_i32 = "integer/i32";
546 let decimal_base = "decimal";
547 let decimal_f64 = "decimal/f64";
548
549 assert_eq!(
550 CoreLibPointerId::from_str(integer_base),
551 Ok(CoreLibPointerId::Integer(None))
552 );
553 assert_eq!(
554 CoreLibPointerId::from_str(integer_u8),
555 Ok(CoreLibPointerId::Integer(Some(IntegerTypeVariant::U8)))
556 );
557 assert_eq!(
558 CoreLibPointerId::from_str(integer_i32),
559 Ok(CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32)))
560 );
561 assert_eq!(
562 CoreLibPointerId::from_str(decimal_base),
563 Ok(CoreLibPointerId::Decimal(None))
564 );
565 assert_eq!(
566 CoreLibPointerId::from_str(decimal_f64),
567 Ok(CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64)))
568 );
569
570 assert_eq!(CoreLibPointerId::Integer(None).to_string(), integer_base);
571 assert_eq!(
572 CoreLibPointerId::Integer(Some(IntegerTypeVariant::U8)).to_string(),
573 integer_u8
574 );
575 assert_eq!(
576 CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32))
577 .to_string(),
578 integer_i32
579 );
580 assert_eq!(CoreLibPointerId::Decimal(None).to_string(), decimal_base);
581 assert_eq!(
582 CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64))
583 .to_string(),
584 decimal_f64
585 );
586 }
587
588 #[test]
589 fn core_lib_pointer_id_conversion() {
590 let core_id = CoreLibPointerId::Core;
591 let pointer_address: PointerAddress = core_id.clone().into();
592 let converted_id: CoreLibPointerId =
593 (&pointer_address).try_into().unwrap();
594 assert_eq!(core_id, converted_id);
595
596 let boolean_id = CoreLibPointerId::Boolean;
597 let pointer_address: PointerAddress = boolean_id.clone().into();
598 let converted_id: CoreLibPointerId =
599 (&pointer_address).try_into().unwrap();
600 assert_eq!(boolean_id, converted_id);
601
602 let integer_id =
603 CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32));
604 let pointer_address: PointerAddress = integer_id.clone().into();
605 let converted_id: CoreLibPointerId =
606 (&pointer_address).try_into().unwrap();
607 assert_eq!(integer_id, converted_id);
608
609 let decimal_id =
610 CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64));
611 let pointer_address: PointerAddress = decimal_id.clone().into();
612 let converted_id: CoreLibPointerId =
613 (&pointer_address).try_into().unwrap();
614 assert_eq!(decimal_id, converted_id);
615
616 let type_id = CoreLibPointerId::Type;
617 let pointer_address: PointerAddress = type_id.clone().into();
618 let converted_id: CoreLibPointerId =
619 (&pointer_address).try_into().unwrap();
620 assert_eq!(type_id, converted_id);
621 }
622
623 #[test]
624 fn base_type_simple() {
625 let integer_type = get_core_lib_type(CoreLibPointerId::Integer(None));
627 let integer_base = integer_type.base_type_reference();
628 assert_eq!(integer_base.unwrap().borrow().to_string(), "integer");
629 }
630
631 #[test]
632 fn base_type_complex() {
633 let integer_u8_type = get_core_lib_type(CoreLibPointerId::Integer(
635 Some(IntegerTypeVariant::U8),
636 ));
637 assert_eq!(integer_u8_type.to_string(), "integer/u8");
638
639 let integer = integer_u8_type.base_type_reference();
640 assert_eq!(integer.unwrap().borrow().to_string(), "integer");
641 }
642
643 #[ignore]
644 #[test]
645 fn print_core_lib_addresses_as_hex() {
646 with_full_core_lib(|core_lib_types, _| {
647 let sorted_entries = core_lib_types
648 .keys()
649 .map(|k| (k.clone(), PointerAddress::from(k.clone())))
650 .sorted_by_key(|(_, address)| address.bytes().to_vec())
651 .collect::<Vec<_>>();
652 for (core_lib_id, address) in sorted_entries {
653 println!("{:?}: {}", core_lib_id, address);
654 }
655 });
656 }
657
658 #[test]
659 #[ignore]
660 fn create_core_type_ts_mapping() {
665 let core_lib = create_core_lib_types();
666 let mut core_lib: Vec<(CoreLibPointerId, PointerAddress)> = core_lib
667 .keys()
668 .map(|key| (key.clone(), PointerAddress::from(key.clone())))
669 .collect();
670 core_lib.sort_by_key(|(key, _)| {
671 PointerAddress::from(key.clone()).bytes().to_vec()
672 });
673
674 println!("export const CoreTypeAddress = {{");
675 for (core_lib_id, address) in core_lib {
676 println!(
677 " {}: \"{}\",",
678 core_lib_id.to_string().replace("/", "_"),
679 address.to_string().strip_prefix("$").unwrap()
680 );
681 }
682 println!("}} as const;");
683 }
684}