roan_engine/interpreter/
expr.rs

1use crate::{context::Context, module::Module, value::Value, vm::VM};
2use anyhow::Result;
3use indexmap::IndexMap;
4use log::debug;
5use roan_ast::{
6    AccessKind, Assign, AssignOperator, BinOpKind, Binary, Expr, GetSpan, LiteralType, Spread,
7    UnOpKind, Unary, VecExpr,
8};
9use roan_error::error::{
10    RoanError,
11    RoanError::{InvalidSpread, StaticMemberAssignment, VariableNotFoundError},
12};
13
14impl Module {
15    /// Interpret an expression.
16    ///
17    /// Result of the expression is pushed onto the stack.
18    ///
19    /// # Arguments
20    /// * `expr` - [Expr] to interpret.
21    /// * `ctx` - The context in which to interpret the expression.
22    ///
23    /// # Returns
24    /// The result of the expression.
25    pub fn interpret_expr(&mut self, expr: &Expr, ctx: &mut Context, vm: &mut VM) -> Result<()> {
26        let val: Result<Value> = match expr {
27            Expr::Variable(v) => {
28                debug!("Interpreting variable: {}", v.ident);
29
30                let variable: &Value = self
31                    .find_variable(&v.ident)
32                    .or_else(|| {
33                        let constant = self.find_const(&v.ident);
34
35                        if let Some(constant) = constant {
36                            Some(&constant.value)
37                        } else {
38                            None
39                        }
40                    })
41                    .ok_or_else(|| VariableNotFoundError(v.ident.clone(), v.token.span.clone()))?;
42
43                Ok(variable.clone())
44            }
45            Expr::Literal(l) => {
46                debug!("Interpreting literal: {:?}", l);
47
48                Ok(Value::from_literal(l.clone()))
49            }
50            Expr::Call(call) => self.interpret_call(call, ctx, vm),
51            Expr::Parenthesized(p) => {
52                debug!("Interpreting parenthesized: {:?}", p);
53
54                self.interpret_expr(&p.expr, ctx, vm)?;
55
56                Ok(vm.pop().unwrap())
57            }
58            Expr::Access(access) => self.interpret_access(access.clone(), ctx, vm),
59            Expr::StructConstructor(constructor) => {
60                self.interpret_struct_constructor(constructor.clone(), ctx, vm)
61            }
62            Expr::Assign(assign) => self.interpret_assignment(assign.clone(), ctx, vm),
63            Expr::Vec(vec) => self.interpret_vec(vec.clone(), ctx, vm),
64            Expr::Binary(b) => self.interpret_binary(b.clone(), ctx, vm),
65            // Spread operator are only supposed to be used in vectors and function calls
66            Expr::Spread(s) => Err(InvalidSpread(s.expr.span()).into()),
67            Expr::Null(_) => Ok(Value::Null),
68            Expr::Unary(u) => self.interpret_unary(u.clone(), ctx, vm),
69            Expr::ThenElse(then_else) => self.interpret_then_else(then_else.clone(), ctx, vm),
70            Expr::Object(obj) => {
71                let mut fields = IndexMap::new();
72
73                for (field_name, expr) in obj.fields.iter() {
74                    self.interpret_expr(expr, ctx, vm)?;
75                    fields.insert(field_name.clone(), vm.pop().unwrap());
76                }
77
78                Ok(Value::Object(fields))
79            }
80        };
81
82        Ok(vm.push(val?))
83    }
84
85    /// Interpret a unary expression.
86    ///
87    /// # Arguments
88    /// * `unary` - [Unary] expression to interpret.
89    /// * `ctx` - The context in which to interpret the unary expression.
90    /// * `vm` - The virtual machine to use.
91    ///
92    /// # Returns
93    /// The result of the unary expression.
94    pub fn interpret_unary(&mut self, u: Unary, ctx: &mut Context, vm: &mut VM) -> Result<Value> {
95        self.interpret_expr(&u.expr, ctx, vm)?;
96        let val = vm.pop().unwrap();
97
98        let val = match (u.operator.clone().kind, val.clone()) {
99            (UnOpKind::Minus, Value::Int(i)) => Value::Int(-i),
100            (UnOpKind::Minus, Value::Float(f)) => Value::Float(-f),
101            (UnOpKind::LogicalNot, Value::Bool(b)) => Value::Bool(!b),
102            (UnOpKind::BitwiseNot, Value::Int(i)) => Value::Int(!i),
103            (UnOpKind::LogicalNot, Value::Null) => Value::Bool(true),
104            (UnOpKind::LogicalNot, _) => {
105                let b = val.is_truthy();
106
107                Value::Bool(!b)
108            }
109            _ => {
110                return Err(
111                    RoanError::InvalidUnaryOperation(u.operator.kind.to_string(), u.span()).into(),
112                )
113            }
114        };
115
116        Ok(val)
117    }
118
119    /// Interpret a vector expression.
120    ///
121    /// # Arguments
122    /// * `vec` - [VecExpr] to interpret.
123    /// * `ctx` - The context in which to interpret the vector expression.
124    ///
125    /// # Returns
126    /// The result of the vector expression.
127    pub fn interpret_vec(&mut self, vec: VecExpr, ctx: &mut Context, vm: &mut VM) -> Result<Value> {
128        debug!("Interpreting vec: {:?}", vec);
129
130        Ok(Value::Vec(
131            self.interpret_possible_spread(vec.exprs, ctx, vm)?,
132        ))
133    }
134
135    /// Interpret a binary expression.
136    ///
137    /// # Arguments
138    /// * `binary_expr` - [Binary] expression to interpret.
139    /// * `ctx` - The context in which to interpret the binary expression.
140    ///
141    /// # Returns
142    /// The result of the binary expression.
143    pub fn interpret_binary(
144        &mut self,
145        binary_expr: Binary,
146        ctx: &mut Context,
147        vm: &mut VM,
148    ) -> Result<Value> {
149        debug!("Interpreting binary: {:?}", binary_expr);
150
151        self.interpret_expr(&binary_expr.left, ctx, vm)?;
152        let left = vm.pop().unwrap();
153        self.interpret_expr(&binary_expr.right, ctx, vm)?;
154        let right = vm.pop().unwrap();
155
156        let val = match (left.clone(), binary_expr.operator, right.clone()) {
157            (_, BinOpKind::Plus, _) => left + right,
158            (_, BinOpKind::Minus, _) => left - right,
159            (_, BinOpKind::Multiply, _) => left * right,
160            (_, BinOpKind::Divide, _) => left / right,
161            (_, BinOpKind::Modulo, _) => left % right,
162            (_, BinOpKind::Equals, _) => Value::Bool(left == right),
163            (_, BinOpKind::BangEquals, _) => Value::Bool(left != right),
164            (_, BinOpKind::Power, _) => left.pow(right),
165
166            (_, BinOpKind::GreaterThan, _) => Value::Bool(left > right),
167            (_, BinOpKind::LessThan, _) => Value::Bool(left < right),
168            (_, BinOpKind::GreaterThanOrEqual, _) => Value::Bool(left >= right),
169            (_, BinOpKind::LessThanOrEqual, _) => Value::Bool(left <= right),
170
171            (Value::Bool(a), BinOpKind::And, Value::Bool(b)) => Value::Bool(a && b),
172            (Value::Bool(a), BinOpKind::Or, Value::Bool(b)) => Value::Bool(a || b),
173
174            (Value::Int(a), BinOpKind::BitwiseAnd, Value::Int(b)) => Value::Int(a & b),
175            (Value::Int(a), BinOpKind::BitwiseOr, Value::Int(b)) => Value::Int(a | b),
176            (Value::Int(a), BinOpKind::BitwiseXor, Value::Int(b)) => Value::Int(a ^ b),
177            (Value::Int(a), BinOpKind::ShiftLeft, Value::Int(b)) => Value::Int(a << b),
178            (Value::Int(a), BinOpKind::ShiftRight, Value::Int(b)) => Value::Int(a >> b),
179
180            _ => todo!("missing binary operator: {:?}", binary_expr.operator),
181        };
182
183        Ok(val)
184    }
185
186    /// Interpret a spread expression.
187    ///
188    /// This function requires vec of values to push to.
189    ///
190    /// # Arguments
191    /// * `expr` - [Expr] to interpret.
192    /// * `ctx` - The context in which to interpret the expression.
193    /// * `values` - The vec of values to push to.
194    ///
195    /// # Returns
196    /// The result of the expression.
197    pub fn interpret_spread(
198        &mut self,
199        s: Spread,
200        ctx: &mut Context,
201        vm: &mut VM,
202        values: &mut Vec<Value>,
203    ) -> Result<()> {
204        self.interpret_expr(&s.expr, ctx, vm)?;
205        let spread_val = vm.pop().unwrap();
206
207        if let Value::Vec(vec) = spread_val {
208            values.extend(vec);
209        } else {
210            return Err(InvalidSpread(s.expr.span()).into());
211        }
212
213        Ok(())
214    }
215
216    /// Helper function to interpret possible spread expressions.
217    ///
218    /// # Arguments
219    /// * `exprs` - The expressions to interpret.
220    /// * `ctx` - The context in which to interpret the expressions.
221    /// * `vm` - The virtual machine to use.
222    pub fn interpret_possible_spread(
223        &mut self,
224        exprs: Vec<Expr>,
225        ctx: &mut Context,
226        vm: &mut VM,
227    ) -> Result<Vec<Value>> {
228        let mut values = vec![];
229
230        for expr in exprs.iter() {
231            match expr {
232                Expr::Spread(s) => self.interpret_spread(s.clone(), ctx, vm, &mut values)?,
233                _ => {
234                    self.interpret_expr(expr, ctx, vm)?;
235                    values.push(vm.pop().unwrap());
236                }
237            }
238        }
239
240        Ok(values)
241    }
242
243    /// Interpret an assignment expression.
244    ///
245    /// # Arguments
246    /// * `assign` - [Assign] expression to interpret.
247    /// * `ctx` - The context in which to interpret the assignment expression.
248    ///
249    /// # Returns
250    /// The result of the assignment expression.
251    pub fn interpret_assignment(
252        &mut self,
253        assign: Assign,
254        ctx: &mut Context,
255        vm: &mut VM,
256    ) -> Result<Value> {
257        debug!("Interpreting assign: {:?}", assign);
258        let left = assign.left.as_ref();
259        let right = assign.right.as_ref();
260        let operator = assign.op.clone();
261
262        match left {
263            Expr::Variable(v) => {
264                self.interpret_expr(right, ctx, vm)?;
265                let val = vm.pop().unwrap();
266                let ident = v.ident.clone();
267                let final_val = val.clone();
268                match operator {
269                    AssignOperator::Assign => self.set_variable(&ident, val.clone())?,
270                    AssignOperator::PlusEquals => {
271                        self.update_variable(&ident, val, |a, b| a + b)?
272                    }
273                    AssignOperator::MinusEquals => {
274                        self.update_variable(&ident, val, |a, b| a - b)?
275                    }
276                    AssignOperator::MultiplyEquals => {
277                        self.update_variable(&ident, val, |a, b| a * b)?
278                    }
279                    AssignOperator::DivideEquals => {
280                        self.update_variable(&ident, val, |a, b| a / b)?
281                    }
282                }
283                Ok(final_val)
284            }
285            Expr::Access(access) => match &access.access {
286                AccessKind::Field(field) => {
287                    let base = access.base.as_ref().clone();
288
289                    self.interpret_expr(right, ctx, vm)?;
290                    let new_val = vm.pop().unwrap();
291
292                    self.interpret_expr(&base, ctx, vm)?;
293                    let base_val = vm.pop().unwrap();
294
295                    let field_name = {
296                        let field = field.as_ref().clone();
297                        match field {
298                            Expr::Variable(v) => v.ident.clone(),
299                            Expr::Literal(l) => match l.value.clone() {
300                                LiteralType::String(s) => s,
301                                _ => panic!("Invalid field name"),
302                            },
303                            // TODO: error
304                            _ => panic!("Invalid field name"),
305                        }
306                    };
307
308                    match base_val {
309                        Value::Object(mut fields) => {
310                            fields.insert(field_name, new_val.clone());
311
312                            if let Some(var_name) = Self::extract_variable_name(&access.base) {
313                                self.set_variable(&var_name, Value::Object(fields))?;
314                                Ok(new_val)
315                            } else {
316                                Err(RoanError::InvalidAssignment(
317                                    "Unable to determine variable for assignment".into(),
318                                    access.base.span(),
319                                )
320                                .into())
321                            }
322                        }
323                        Value::Struct(_, _) => todo!("Finish field assignment for struct"),
324                        _ => Err(RoanError::TypeMismatch(
325                            "Left side of assignment must be a struct or object".into(),
326                            access.base.span(),
327                        )
328                        .into()),
329                    }
330                }
331                AccessKind::Index(index_expr) => {
332                    self.interpret_expr(&access.base, ctx, vm)?;
333                    let base_val = vm.pop().unwrap();
334
335                    self.interpret_expr(index_expr, ctx, vm)?;
336                    let index_val = vm.pop().unwrap();
337
338                    self.interpret_expr(right, ctx, vm)?;
339                    let new_val = vm.pop().unwrap();
340
341                    if let (Value::Vec(mut vec), Value::Int(index)) = (base_val.clone(), index_val)
342                    {
343                        let idx = index as usize;
344                        if idx >= vec.len() {
345                            return Err(RoanError::IndexOutOfBounds(
346                                idx,
347                                vec.len(),
348                                index_expr.span(),
349                            )
350                            .into());
351                        }
352
353                        vec[idx] = new_val.clone();
354
355                        if let Some(var_name) = Self::extract_variable_name(&access.base) {
356                            self.set_variable(&var_name, Value::Vec(vec))?;
357                            Ok(new_val)
358                        } else {
359                            Err(RoanError::InvalidAssignment(
360                                "Unable to determine variable for assignment".into(),
361                                access.base.span(),
362                            )
363                            .into())
364                        }
365                    } else {
366                        Err(RoanError::TypeMismatch(
367                            "Left side of assignment must be a vector with integer index".into(),
368                            access.base.span(),
369                        )
370                        .into())
371                    }
372                }
373                AccessKind::StaticMethod(_) => Err(StaticMemberAssignment(access.span()).into()),
374            },
375            _ => todo!("missing left: {:?}", left),
376        }
377    }
378}