amvm/
runtime.rs

1mod commands;
2mod error;
3mod expr;
4mod result;
5mod scope;
6pub mod variable;
7
8pub use error::AmvmError;
9pub use result::{AmvmPropagate, AmvmResult};
10
11use crate::{AmvmHeader, AmvmScope, Command, Value};
12use std::io::Write;
13use std::{collections::HashMap, sync::Arc};
14
15use self::variable::AmvmVariable;
16
17#[derive(Debug, Clone)]
18pub struct Context {
19    // TODO: Create struct for variables that contains a reference
20    // counter, this will help garbage collection.
21    variables: HashMap<String, AmvmVariable>,
22}
23
24impl Context {
25    pub fn new() -> Self {
26        Self {
27            variables: HashMap::new(),
28        }
29    }
30
31    pub fn create_sub(&self) -> Self {
32        Self {
33            variables: self.variables.clone(),
34        }
35    }
36
37    pub fn get_variable(&self, name: &String) -> &AmvmVariable {
38        self.variables.get(name).unwrap_or_else(|| {
39            let backtrace = format!("{}", std::backtrace::Backtrace::capture());
40            let backtrace = backtrace
41                .split("\n")
42                .filter(|l| {
43                    !l.contains("at /rustc/")
44                        && !l.contains(": std::")
45                        && !l.contains(": core::")
46                        && !l.contains(": _")
47                })
48                .collect::<Vec<&str>>()
49                .join("\n");
50
51            let _ = std::io::stdout().lock().flush();
52
53            eprintln!(
54                "\n\x1b[31mERROR: Variable {name:?} is not defined.\n\x1b[2m{backtrace}\x1b[0m"
55            );
56            std::process::exit(1)
57        })
58    }
59}
60
61#[derive(Debug, Clone)]
62pub struct Runtime {
63    scope: AmvmScope,
64}
65
66impl Runtime {
67    pub fn new(header: AmvmHeader, ast: Vec<Command>) -> Self {
68        Self {
69            scope: AmvmScope::new(&Arc::new(header), ast, None),
70        }
71    }
72
73    pub fn run(&mut self) -> AmvmResult {
74        for cmd in self.scope.body.clone().iter() {
75            commands::eval(&mut self.scope, cmd)?;
76        }
77
78        Ok(Value::Null)
79    }
80}