vngineer_simpleton/
lib.rs

1use 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(&param.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}