vngineer_simpleton/
lib.rs1use intuicio_essentials::{core as intuicio_core, data as intuicio_data, prelude::*};
2use intuicio_frontend_simpleton::prelude::*;
3use vngineer_core::prelude::*;
4
5#[derive(IntuicioStruct, Default)]
6struct VnResultJumpTo {
7 pub chapter: Reference,
8 pub label: Reference,
9}
10
11#[derive(IntuicioStruct, Default)]
12struct VnResultEnter {
13 pub chapter: Reference,
14 pub label: Reference,
15}
16
17#[derive(IntuicioStruct, Default)]
18struct VnResultExit;
19
20pub fn value_to_reference(value: &VnValue, registry: &Registry) -> Reference {
21 match value {
22 VnValue::None => Reference::null(),
23 VnValue::Boolean(value) => Reference::new_boolean(*value, registry),
24 VnValue::Number(value) => Reference::new_real(*value, registry),
25 VnValue::Text(value) => Reference::new_text(value.to_owned(), registry),
26 VnValue::Color(value) => Reference::new_integer(*value as Integer, registry),
27 VnValue::Array(value) => Reference::new_array(
28 value
29 .iter()
30 .map(|value| value_to_reference(value, registry))
31 .collect(),
32 registry,
33 ),
34 VnValue::Map(value) => Reference::new_map(
35 value
36 .iter()
37 .map(|(key, value)| (key.to_owned(), value_to_reference(value, registry)))
38 .collect(),
39 registry,
40 ),
41 }
42}
43
44#[intuicio_function(module_name = "vn", use_context, use_registry)]
45pub fn simpleton(
46 context: &mut Context,
47 registry: &Registry,
48 name: VnValue,
49 module_name: VnValue,
50 arguments: VnValue,
51) -> VnResult {
52 let name = name.as_text().expect("`name` is not a text!");
53 let module_name = module_name.as_text();
54 let arguments = arguments.as_map().expect("`arguments` is not a map!");
55 let function = registry
56 .find_function(FunctionQuery {
57 name: Some(name.into()),
58 module_name: module_name.map(|name| name.into()),
59 ..Default::default()
60 })
61 .unwrap_or_else(|| {
62 panic!(
63 "Function `{}::{}` not found!",
64 name,
65 module_name.unwrap_or_default()
66 );
67 });
68 for param in function.signature().inputs.iter().rev() {
69 if let Some(value) = arguments.get(¶m.name) {
70 context.stack().push(value_to_reference(value, registry));
71 }
72 }
73 function.invoke(context, registry);
74 if function.signature().outputs.len() != 1 {
75 panic!(
76 "Function `{}::{}` must have single output!",
77 name,
78 module_name.unwrap_or_default()
79 );
80 }
81 let result = context.stack().pop::<Reference>().unwrap_or_else(|| {
82 panic!(
83 "Function `{}::{}` must return `Reference`!",
84 name,
85 module_name.unwrap_or_default()
86 );
87 });
88 let result = if let Some(result) = result.read::<VnResultJumpTo>() {
89 let chapter = result.chapter.read::<Text>().map(|value| value.to_owned());
90 let label = result.label.read::<Text>().map(|value| value.to_owned());
91 VnResult::JumpTo { chapter, label }
92 } else if let Some(result) = result.read::<VnResultEnter>() {
93 let chapter = result.chapter.read::<Text>().map(|value| value.to_owned());
94 let label = result.label.read::<Text>().map(|value| value.to_owned());
95 VnResult::Enter { chapter, label }
96 } else if result.read::<VnResultExit>().is_some() {
97 VnResult::Exit
98 } else {
99 VnResult::Continue
100 };
101 result
102}
103
104pub fn install(registry: &mut Registry) {
105 registry.add_struct(VnResultJumpTo::define_struct(registry));
106 registry.add_struct(VnResultEnter::define_struct(registry));
107 registry.add_struct(VnResultExit::define_struct(registry));
108 registry.add_function(simpleton::define_function(registry));
109}