psi_lang/
interpreter.rs

1use crate::{do_parse, do_walk, Action, Block, Error, Expr, IfPart, Namespace, Op, Table};
2use smartstring::alias::String;
3use std::collections::VecDeque;
4use std::fs;
5use std::io::{self, Write};
6
7#[derive(Debug)]
8pub struct Interpreter<'a> {
9    pub env: Namespace<'a>,
10    pub return_value: Option<Expr>,
11    pub do_break: bool,
12    pub do_continue: bool,
13}
14
15impl<'a> Interpreter<'a> {
16    pub fn new() -> Self {
17        Self {
18            env: Namespace::new(),
19            return_value: None,
20            do_break: false,
21            do_continue: false,
22        }
23    }
24
25    pub fn run_block(&mut self, block: &[Action]) -> Result<(), Error> {
26        for act in block {
27            self.run(act)?;
28            if self.return_value.is_some() || self.do_continue || self.do_break {
29                break;
30            }
31        }
32        Ok(())
33    }
34
35    pub fn run(&mut self, act: &Action) -> Result<(), Error> {
36        match act {
37            Action::Comment(_) => Ok(()),
38            Action::VarAssign(id, val) => self.var_assign(id, val),
39            Action::SingleShot(id, op, val) => self.single_shot(id, op, val),
40            Action::If(parts) => self.if_stmt(parts),
41            Action::FnDef(id, args, block) => {
42                self.fn_def(id, args, block.to_owned());
43                Ok(())
44            }
45            Action::FnCall(id, args) => {
46                self.fn_call(id, args)?;
47                self.return_value = None;
48                Ok(())
49            }
50            Action::Return(value) => {
51                if self.env.in_function() {
52                    self.return_value =
53                        Some(self.expr(value.as_ref().unwrap_or(&Expr::Boolean(false)))?);
54                    Ok(())
55                } else {
56                    Err(Error::ReturnOutOfFunction)
57                }
58            }
59            Action::Loop(block) => self.loop_stmt(block),
60            Action::For(id, expr, block) => self.for_stmt(id, expr, block),
61            Action::While(expr, block) => self.while_stmt(expr, block),
62            Action::Break => self.break_stmt(),
63            Action::Continue => self.continue_stmt(),
64            Action::Import(id, into) => self.import_stmt(id, into),
65        }
66    }
67
68    fn import_stmt(&mut self, id: &Expr, _into: &Option<Expr>) -> Result<(), Error> {
69        if let Expr::Identifier(parts) = id {
70            let raw = fs::read_to_string(format!("{}.psi", parts[0].to_string()))?;
71            let parse = do_parse(&raw)?;
72            let walk = do_walk(parse)?;
73            self.run_block(&walk)?;
74        }
75        Ok(())
76    }
77
78    fn while_stmt(&mut self, expr: &Expr, block: &[Action]) -> Result<(), Error> {
79        self.env.enter("while");
80        while !self.do_break
81            && self.expr(expr)? == Expr::Boolean(true)
82            && self.return_value.is_none()
83        {
84            self.run_block(block)?;
85        }
86        self.do_break = false;
87        self.do_continue = false;
88        self.env.leave();
89        Ok(())
90    }
91
92    fn for_stmt(&mut self, id: &[String], expr: &Expr, block: &[Action]) -> Result<(), Error> {
93        let expr = self.expr(expr)?;
94        self.env.enter("for");
95        let mut iteration = 0;
96        while !self.do_break && self.return_value.is_none() {
97            if let Ok(this) = self.var_index(&expr, vec![Expr::Integer(iteration)].into()) {
98                self.env.raw_expr(&id[0], &this);
99                self.run_block(block)?;
100                iteration += 1;
101            } else if let Expr::Table(ref items) = expr {
102                if id.len() != 2 {
103                    return Err(Error::IndexError);
104                }
105                self.env.raw_expr(
106                    &id[0],
107                    if let Some(i) = items.keys().get(iteration as usize) {
108                        i
109                    } else {
110                        break;
111                    },
112                );
113                self.env.raw_expr(
114                    &id[1],
115                    if let Some(i) = items.values().get(iteration as usize) {
116                        i
117                    } else {
118                        break;
119                    },
120                );
121                self.run_block(block)?;
122                iteration += 1;
123            } else {
124                break;
125            }
126        }
127        self.do_break = false;
128        self.do_continue = false;
129        self.env.leave();
130        Ok(())
131    }
132
133    fn break_stmt(&mut self) -> Result<(), Error> {
134        if self.env.in_loop() {
135            self.do_break = true;
136            Ok(())
137        } else {
138            Err(Error::BreakOutOfLoop)
139        }
140    }
141
142    fn continue_stmt(&mut self) -> Result<(), Error> {
143        if self.env.in_loop() {
144            self.do_continue = true;
145            Ok(())
146        } else {
147            Err(Error::ContinueOutOfLoop)
148        }
149    }
150
151    fn loop_stmt(&mut self, block: &[Action]) -> Result<(), Error> {
152        self.env.enter("loop");
153        while !self.do_break {
154            self.run_block(block)?;
155        }
156        self.do_break = false;
157        self.env.leave();
158        Ok(())
159    }
160
161    fn fn_def(&mut self, id: &Expr, args: &[String], block: Block) {
162        if let Expr::Identifier(id) = id {
163            self.env.insert_fn(&id.join("."), args, &block);
164        }
165    }
166
167    fn if_stmt(&mut self, parts: &[IfPart]) -> Result<(), Error> {
168        for part in parts {
169            match part {
170                IfPart::If(e, b) | IfPart::IfElse(e, b) => {
171                    if let Expr::Boolean(true) = self.expr(e)? {
172                        self.run_block(b)?;
173                        break;
174                    }
175                }
176                IfPart::Else(b) => self.run_block(b)?,
177            }
178        }
179        Ok(())
180    }
181
182    fn single_shot(&mut self, id: &Expr, op: &Op, val: &Expr) -> Result<(), Error> {
183        let exist = self.expr(id)?;
184        if let Expr::Identifier(i) = id {
185            let val = self.expr(val)?;
186            let new = match op {
187                Op::Add => exist + val,
188                Op::Sub => exist - val,
189                Op::Mul => exist * val,
190                Op::Div => exist / val,
191                Op::Rem => exist % val,
192                Op::Pow => exist.pow(val),
193                _ => unreachable!(),
194            };
195            self.env.insert_expr(&i.join("."), &new);
196        }
197        Ok(())
198    }
199
200    fn var_assign(&mut self, id: &Expr, val: &Expr) -> Result<(), Error> {
201        let val = self.expr(val)?;
202        if let Expr::Identifier(id) = id {
203            self.env.insert_expr(&id.join("."), &val);
204        }
205        Ok(())
206    }
207
208    fn expr(&mut self, e: &Expr) -> Result<Expr, Error> {
209        Ok(match e {
210            Expr::Float(_) | Expr::Integer(_) | Expr::Boolean(_) | Expr::StringRaw(_) => {
211                e.to_owned()
212            }
213            Expr::StringFmt(parts) => self.string_fmt(parts)?,
214            Expr::Identifier(id) => self.identifier(id)?,
215            Expr::Inclusive(s, e) => self.inclusive(s, e)?,
216            Expr::Exclusive(s, e) => self.exclusive(s, e)?,
217            Expr::Array(items) => self.array(items)?,
218            Expr::Table(items) => self.table(items.to_owned())?,
219            Expr::Not(e) => self.not(e)?,
220            Expr::BinOp(left, op, right) => self.bin_op(*left.clone(), *op, *right.clone())?,
221            Expr::FnCall(id, args) => {
222                self.fn_call(id, args)?;
223                let val = if let Some(val) = self.return_value.clone() {
224                    val
225                } else {
226                    return Err(Error::NoReturnValue);
227                };
228                self.return_value = None;
229                val
230            }
231            Expr::VarIndex(id, inds) => self.var_index(&*id, inds.to_owned())?,
232            Expr::Impossible => return Err(Error::ImpossibleOperation),
233        })
234    }
235
236    fn var_index(&mut self, id: &Expr, mut inds: VecDeque<Expr>) -> Result<Expr, Error> {
237        let mut result = self.expr(id)?;
238        while let Some(ind) = inds.pop_front() {
239            let ind = self.expr(&ind)?;
240            match result {
241                Expr::StringRaw(s) => result = self.index_string(&s, &ind)?,
242                Expr::Inclusive(s, e) => {
243                    let (s, e, i) = if let Some(rp) = self.range_parts(&s, &e, &ind) {
244                        rp
245                    } else {
246                        return Err(Error::InvalidIndex);
247                    };
248                    if s + i <= e {
249                        return Ok(Expr::Integer(s + i));
250                    } else {
251                        return Err(Error::IndexError);
252                    }
253                }
254                Expr::Exclusive(s, e) => {
255                    let (s, e, i) = if let Some(rp) = self.range_parts(&s, &e, &ind) {
256                        rp
257                    } else {
258                        return Err(Error::InvalidIndex);
259                    };
260                    if s + i < e {
261                        return Ok(Expr::Integer(s + i));
262                    } else {
263                        return Err(Error::IndexError);
264                    }
265                }
266                Expr::Array(items) => {
267                    if let Expr::Integer(i) = ind {
268                        result = if let Some(item) = items.get(i as usize) {
269                            item.to_owned()
270                        } else {
271                            return Err(Error::IndexError);
272                        }
273                    } else {
274                        return Err(Error::IndexError);
275                    }
276                }
277                Expr::Table(items) => {
278                    result = if let Some(ind) = items.get(ind) {
279                        ind
280                    } else {
281                        return Err(Error::IndexError);
282                    }
283                }
284                Expr::VarIndex(id, inds) => result = self.var_index(&id, inds)?,
285                _ => return Err(Error::IndexError),
286            }
287        }
288        Ok(result)
289    }
290
291    fn index_string(&mut self, s: &str, ind: &Expr) -> Result<Expr, Error> {
292        if let Expr::Integer(i) = ind {
293            Ok(Expr::StringRaw(
294                if let Some(c) = s.chars().nth(*i as usize) {
295                    c.to_string().into()
296                } else {
297                    return Err(Error::IndexError);
298                },
299            ))
300        } else {
301            Err(Error::InvalidIndex)
302        }
303    }
304
305    fn range_parts(&self, s: &Expr, e: &Expr, ind: &Expr) -> Option<(i64, i64, i64)> {
306        if let (Expr::Integer(s), Expr::Integer(e), Expr::Integer(i)) = (s, e, ind) {
307            Some((*s, *e, *i))
308        } else {
309            None
310        }
311    }
312
313    fn fn_call(&mut self, id: &Expr, args: &[Expr]) -> Result<(), Error> {
314        self.return_value = None;
315        let mut args_result = vec![];
316        for i in args {
317            args_result.push(self.expr(i)?);
318        }
319        let args = args_result;
320        if let Expr::Identifier(ref parts) = id {
321            self.env.enter("function");
322            if let Some((needed_arguments, block)) = self.env.get_fn(&parts.join(".")) {
323                for (k, v) in needed_arguments.iter().zip(&args) {
324                    self.env.insert_expr(k, v);
325                }
326                self.run_block(&block)?;
327            } else {
328                match parts
329                    .iter()
330                    .map(|x| x.as_str())
331                    .collect::<Vec<_>>()
332                    .as_slice()
333                {
334                    ["print"] => println!("{}", args[0]),
335                    ["input"] => {
336                        let mut input = std::string::String::new();
337                        print!("{}", args[0]);
338                        io::stdout().flush().unwrap();
339                        io::stdin().read_line(&mut input).unwrap();
340                        self.return_value =
341                            Some(Expr::StringRaw(input.trim_end_matches('\n').into()))
342                    }
343                    _ => return Err(Error::FunctionNotFound(parts.join(".").into())),
344                }
345            }
346            self.env.leave();
347        } else {
348            unreachable!()
349        }
350        Ok(())
351    }
352
353    fn bin_op(&mut self, mut left: Expr, op: Op, mut right: Expr) -> Result<Expr, Error> {
354        left = self.expr(&left)?;
355        right = self.expr(&right)?;
356        Ok(match op {
357            Op::Add => left + right,
358            Op::Sub => left - right,
359            Op::Mul => left * right,
360            Op::Div => left / right,
361            Op::Pow => left.pow(right),
362            Op::Rem => left % right,
363            Op::Equals => Expr::Boolean(left == right),
364            Op::NotEquals => Expr::Boolean(left != right),
365            Op::Greater => Expr::Boolean(left > right),
366            Op::Less => Expr::Boolean(left < right),
367            Op::GreaterEq => Expr::Boolean(left >= right),
368            Op::LessEq => Expr::Boolean(left <= right),
369            Op::Or => Expr::Boolean(left.as_bool()? || right.as_bool()?),
370            Op::And => Expr::Boolean(left.as_bool()? && right.as_bool()?),
371            Op::In => self.in_expr(&left, &right)?,
372        })
373    }
374
375    fn in_expr(&mut self, left: &Expr, right: &Expr) -> Result<Expr, Error> {
376        let (left, right) = (self.expr(left)?, self.expr(right)?);
377        Ok(match right {
378            Expr::StringRaw(fish) => {
379                if let Expr::StringRaw(sea) = left {
380                    Expr::Boolean(fish.contains(sea.as_str()))
381                } else {
382                    return Err(Error::InvalidIndex);
383                }
384            }
385            Expr::Inclusive(s, e) => self.in_inc(&s, &e, &left)?,
386            Expr::Exclusive(s, e) => self.in_exc(&s, &e, &left)?,
387            Expr::Array(ref items) => Expr::Boolean(items.contains(&left)),
388            Expr::Table(ref items) => Expr::Boolean(items.contains(&left)),
389            _ => return Err(Error::InvalidIndex),
390        })
391    }
392
393    fn in_inc(&mut self, s: &Expr, e: &Expr, left: &Expr) -> Result<Expr, Error> {
394        let (s, e) = (self.expr(s)?, self.expr(e)?);
395        if let (Expr::Integer(s), Expr::Integer(e), Expr::Integer(l)) = (s, e, left) {
396            Ok(Expr::Boolean(l <= &e && l >= &s))
397        } else {
398            Err(Error::InvalidIndex)
399        }
400    }
401
402    fn in_exc(&mut self, s: &Expr, e: &Expr, left: &Expr) -> Result<Expr, Error> {
403        let (s, e) = (self.expr(s)?, self.expr(e)?);
404        if let (Expr::Integer(s), Expr::Integer(e), Expr::Integer(l)) = (s, e, left) {
405            Ok(Expr::Boolean(l < &e && l >= &s))
406        } else {
407            Err(Error::InvalidIndex)
408        }
409    }
410
411    fn not(&mut self, e: &Expr) -> Result<Expr, Error> {
412        if let Expr::Boolean(b) = self.expr(e)? {
413            Ok(Expr::Boolean(!b))
414        } else {
415            Err(Error::EvalNotBool)
416        }
417    }
418
419    fn array(&mut self, items: &[Expr]) -> Result<Expr, Error> {
420        let mut items_result = vec![];
421        for i in items {
422            items_result.push(self.expr(i)?);
423        }
424        Ok(Expr::Array(items_result))
425    }
426
427    fn table(&mut self, mut items: Table) -> Result<Expr, Error> {
428        items.simplify(&mut |x| self.expr(&x))?;
429        Ok(Expr::Table(items))
430    }
431
432    fn inclusive(&mut self, start: &Expr, end: &Expr) -> Result<Expr, Error> {
433        Ok(Expr::Inclusive(
434            Box::new(self.expr(start)?),
435            Box::new(self.expr(end)?),
436        ))
437    }
438
439    fn exclusive(&mut self, start: &Expr, end: &Expr) -> Result<Expr, Error> {
440        Ok(Expr::Exclusive(
441            Box::new(self.expr(start)?),
442            Box::new(self.expr(end)?),
443        ))
444    }
445
446    fn string_fmt(&mut self, parts: &[Expr]) -> Result<Expr, Error> {
447        let mut result = String::new();
448        for part in parts {
449            result.push_str(&format!("{}", self.expr(part)?));
450        }
451        Ok(Expr::StringRaw(result))
452    }
453
454    fn identifier(&mut self, id: &[String]) -> Result<Expr, Error> {
455        if let Some(e) = self.env.get_expr(&id.join(".")) {
456            Ok(e)
457        } else {
458            Err(Error::VariableNotFound(id.join(".").into()))
459        }
460    }
461}
462
463impl<'a> Default for Interpreter<'a> {
464    fn default() -> Self {
465        Self::new()
466    }
467}