lorgn_runtime/
runtime.rs

1use std::collections::HashMap;
2
3use lorgn_lang::ast::{Expr, Name};
4
5use crate::{Module, Value};
6
7pub struct Runtime {
8    modules: HashMap<Name, Module>,
9}
10
11impl Default for Runtime {
12    fn default() -> Self {
13        let modules = HashMap::new();
14        Self { modules }
15    }
16}
17
18impl Runtime {
19    pub fn register(&mut self, module: Module) {
20        self.modules.insert(module.name().clone(), module);
21    }
22
23    pub fn evaluate(&mut self, expression: Expr) -> Value {
24        let mut context = self.context();
25        context.run_expr(&expression)
26    }
27
28    fn context(&mut self) -> Context {
29        Context::new(&mut self.modules)
30    }
31}
32
33pub use eval_result::EvRes;
34mod eval_result;
35
36pub struct Scope {
37    bubble_variables: bool,
38    variables: HashMap<Name, Value>,
39}
40
41impl Scope {
42    pub fn new(bubble_variables: bool) -> Self {
43        let variables = HashMap::new();
44        Self {
45            bubble_variables,
46            variables,
47        }
48    }
49
50    pub fn new_with(variables: Vec<(Name, Value)>, bubble_variables: bool) -> Self {
51        let mut result = Self::new(bubble_variables);
52        for (name, value) in variables {
53            result.insert(name, value)
54        }
55        result
56    }
57
58    pub fn insert(&mut self, name: Name, value: Value) {
59        self.variables.insert(name, value);
60    }
61
62    pub fn get(&self, name: &Name) -> Option<&Value> {
63        self.variables.get(name)
64    }
65
66    pub fn get_mut(&mut self, name: &Name) -> Option<&mut Value> {
67        self.variables.get_mut(name)
68    }
69}
70
71pub use context::Context;
72mod context {
73    use std::{cell::RefMut, collections::HashMap};
74
75    use lorgn_lang::ast::{
76        Assignment, Block, Break, Condition, Expr, FnCall, FnDef, Invoke, Litteral, Loop, Name,
77        Path, Return,
78    };
79
80    use crate::{Function, Module, Value};
81
82    use super::{EvRes, Scope};
83
84    pub struct Context<'r> {
85        modules: &'r HashMap<Name, Module>,
86        scopes: Vec<Scope>,
87    }
88
89    impl<'r> Context<'r> {
90        pub fn new(modules: &'r mut HashMap<Name, Module>) -> Self {
91            let scopes = vec![];
92            Self { modules, scopes }
93        }
94
95        pub fn find_function(&self, path: &Path) -> Option<RefMut<Function>> {
96            self.modules
97                .get(&path.module)
98                .and_then(|m| m.get_function(&path.item))
99        }
100
101        pub fn find_variable(&mut self, name: &Name) -> Option<&mut Value> {
102            for scope in self.scopes.iter_mut().rev() {
103                if !scope.bubble_variables {
104                    return None;
105                }
106                if let Some(result) = scope.variables.get_mut(name) {
107                    return Some(result);
108                }
109            }
110            None
111        }
112
113        pub fn run_fun(&mut self, fn_def: &FnDef, params: Vec<Value>) -> Value {
114            let variables = fn_def
115                .parameters
116                .iter()
117                .cloned()
118                .zip(params.into_iter())
119                .collect();
120            self.push_scope(Scope::new_with(variables, false));
121            let res = self.eval_block(&fn_def.expressions);
122            self.pop_scope();
123            match res {
124                EvRes::Value(res) => res,
125                EvRes::ReturnSC(res) => res,
126                EvRes::BreakSC(_) => panic!("break outside of loop"),
127            }
128        }
129
130        pub fn run_expr(&mut self, expr: &Expr) -> Value {
131            self.eval_expr(expr).into_value().unwrap()
132        }
133
134        fn push_scope(&mut self, scope: Scope) {
135            self.scopes.push(scope)
136        }
137
138        fn pop_scope(&mut self) {
139            self.scopes.pop();
140        }
141
142        pub fn top_scope(&mut self) -> Option<&mut Scope> {
143            self.scopes.last_mut()
144        }
145
146        pub fn top_index(&self) -> usize {
147            self.scopes.len() - 1
148        }
149
150        fn eval_expr(&mut self, expr: &Expr) -> EvRes {
151            match expr {
152                Expr::Block(block) => self.eval_block(block),
153                Expr::Assignment(assignment) => self.eval_assignment(assignment),
154                Expr::Invoke(invoke) => self.eval_invoke(invoke),
155                Expr::Litteral(litteral) => self.eval_litteral(litteral),
156                Expr::FnCall(fn_call) => self.eval_fn_call(fn_call),
157                Expr::Condition(condition) => self.eval_condition(condition),
158                Expr::Loop(loop_) => self.eval_loop(loop_),
159                Expr::Return(return_) => self.eval_return(return_),
160                Expr::Break(break_) => self.eval_break(break_),
161            }
162        }
163
164        fn eval_block(&mut self, block: &Block) -> EvRes {
165            let mut last = None;
166            for expr in &block.expressions {
167                let result = self.eval_expr(expr);
168                if let EvRes::Value(result) = result {
169                    last = Some(result);
170                } else {
171                    return result;
172                }
173            }
174            let result = last.unwrap_or(Value::None);
175            EvRes::new_val(result)
176        }
177
178        fn eval_assignment(&mut self, assignment: &Assignment) -> EvRes {
179            let result = self.eval_expr(&assignment.value);
180            if let EvRes::Value(result) = result {
181                let name = assignment.variable_name.clone();
182                self.top_scope().unwrap().insert(name, result.clone());
183                EvRes::new_val(result)
184            } else {
185                result
186            }
187        }
188
189        fn eval_invoke(&mut self, invoke: &Invoke) -> EvRes {
190            let value = self.find_variable(&invoke.variable_name).unwrap().clone();
191            EvRes::new_val(value)
192        }
193
194        fn eval_litteral(&mut self, litteral: &Litteral) -> EvRes {
195            match litteral {
196                Litteral::String(str) => EvRes::Value(str.clone().into()),
197                Litteral::Integer(int) => EvRes::Value((*int).into()),
198                Litteral::Float(flt) => EvRes::Value((*flt).into()),
199                Litteral::Bool(bool) => EvRes::Value((*bool).into()),
200                Litteral::List(vec) => {
201                    let mut results = vec![];
202                    for expr in vec {
203                        let result = self.eval_expr(expr);
204                        if let EvRes::Value(result) = result {
205                            results.push(result);
206                        } else {
207                            return result;
208                        }
209                    }
210                    EvRes::Value(results.into())
211                }
212                Litteral::Map(map) => {
213                    let mut results = HashMap::new();
214                    for (name, expr) in map {
215                        let result = self.eval_expr(expr);
216                        if let EvRes::Value(result) = result {
217                            results.insert(name.clone(), result);
218                        } else {
219                            return result;
220                        }
221                    }
222                    EvRes::Value(results.into())
223                }
224            }
225        }
226
227        fn eval_fn_call(&mut self, fn_call: &FnCall) -> EvRes {
228            let mut args = vec![];
229            for arg in &fn_call.arguments {
230                let res = self.eval_expr(arg);
231                if res.is_short_circuit() {
232                    return res;
233                }
234                args.push(res.into_value().unwrap());
235            }
236            let path = &fn_call.fn_path;
237            let module = self.modules.get(&path.module).unwrap();
238            let mut function = module.get_function(&path.item).unwrap();
239            let res = function.call(args, self);
240            EvRes::Value(res)
241        }
242
243        fn eval_condition(&mut self, condition: &Condition) -> EvRes {
244            let cond = self.eval_expr(&condition.condition);
245            if cond.is_short_circuit() {
246                return cond;
247            }
248            let cond = cond.into_value().unwrap();
249            if cond.into_bool().unwrap() {
250                self.eval_expr(&condition.true_case)
251            } else {
252                self.eval_expr(&condition.false_case)
253            }
254        }
255
256        fn eval_loop(&mut self, loop_: &Loop) -> EvRes {
257            let body = &loop_.body;
258            let result = loop {
259                let res = self.eval_expr(body);
260                match res {
261                    EvRes::ReturnSC(_) => return res,
262                    EvRes::BreakSC(result) => break result,
263                    _ => (),
264                };
265            };
266            EvRes::new_val(result)
267        }
268
269        fn eval_return(&mut self, return_: &Return) -> EvRes {
270            let result = self.eval_expr(&return_.expression);
271            match result {
272                EvRes::ReturnSC(_) => result,
273                EvRes::Value(v) => EvRes::ReturnSC(v),
274                EvRes::BreakSC(_) => panic!("break outside of loop"),
275            }
276        }
277
278        fn eval_break(&mut self, break_: &Break) -> EvRes {
279            let result = self.eval_expr(&break_.expression);
280            match result {
281                EvRes::ReturnSC(_) => result,
282                EvRes::Value(v) => EvRes::BreakSC(v),
283                EvRes::BreakSC(v) => EvRes::BreakSC(v),
284            }
285        }
286    }
287}