aplang_lib/standard_library/
mod.rs

1use crate::interpreter::FunctionMap;
2use crate::interpreter::Value;
3use crate::standard_library::io::input;
4use crate::std_function;
5use rand::Rng;
6use std::collections::HashMap;
7use crate::display;
8
9mod file_system;
10mod io;
11mod math;
12mod std_macros;
13mod strings;
14mod style;
15mod time;
16mod map;
17mod robot;
18
19#[derive(Debug, Clone, Default)]
20pub struct Modules {
21    modules: HashMap<String, fn() -> FunctionMap>,
22}
23
24impl Modules {
25    fn inject(&mut self) {
26        self.register("CORE", std_core);
27        self.register("FS", file_system::file_system);
28        self.register("TIME", time::time);
29        self.register("MATH", math::std_math);
30        self.register("IO", io::std_io);
31        self.register("STRING", strings::std_strings);
32        self.register("STYLE", style::std_style);
33        self.register("MAP", map::std_map);
34        self.register("ROBOT", robot::std_robot)
35    }
36    pub fn init() -> Self {
37        // create bland hashmap of modules
38        let mut modules = Self::default();
39        // load in the module functions
40        modules.inject();
41        // return handle
42        modules
43    }
44
45    pub fn lookup(&self, module: &str) -> Option<&fn() -> FunctionMap> {
46        self.modules.get(module)
47    }
48
49    pub fn register(&mut self, module_name: &str, injector: fn() -> FunctionMap) {
50        // if a module is defined again with the same name, then the prev will be discarded
51        let _ = self.modules.insert(module_name.to_string(), injector);
52    }
53}
54
55fn std_core() -> FunctionMap {
56    let mut functions = FunctionMap::new();
57
58    std_function!(functions => fn DISPLAY(value: Value) {
59        display!("{}\n", value);
60
61        return Ok(Value::Null)
62    });
63
64    std_function!(functions => fn DISPLAY_NOLN(value: Value) {
65        display!("{}", value);
66
67        return Ok(Value::Null)
68    });
69
70    std_function!(functions => fn INPUT() {
71        let result = input("").expect("Failed to get user input! Critical Failure");
72        // let result = input("").unwrap_or_default();
73        Ok(Value::String(result))
74    });
75
76    std_function!(functions => fn INSERT(list: Value::List, i: Value::Number, value: Value) {
77        // subtract one because indexed at one
78        list.borrow_mut().insert(i as usize - 1, value.clone());
79
80        return Ok(Value::Null)
81    });
82
83    std_function!(functions => fn APPEND(list: Value::List, value: Value) {
84        list.borrow_mut().push(value.clone());
85
86        return Ok(Value::Null)
87    });
88
89    std_function!(functions => fn REMOVE(list: Value::List, i: Value::Number) {
90        // todo instead of panic with default hook make this return a nice error
91        let poped = list.borrow_mut().remove(i as usize - 1);
92        return Ok(poped);
93    });
94
95    std_function!(functions => fn LENGTH(collection: Value) {
96        let len = match collection {
97            Value::List(list) => {
98                list.borrow().len() as f64
99            }
100            Value::String(string) => {
101                string.len() as f64
102            }
103            _ => {
104                return Ok(Value::Null)
105            }
106        };
107
108        Ok(Value::Number(len))
109    });
110
111    // return a random integer from a to b including a and b
112    std_function!(functions => fn RANDOM(a: Value::Number, b: Value::Number) {
113        let mut rng = rand::rng();
114        let result = rng.random_range(a as i64..=b as i64);
115
116        return Ok(Value::Number(result as f64))
117    });
118
119    functions
120}