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 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}