63 lines
1.3 KiB
Rust
63 lines
1.3 KiB
Rust
use std::{cell::RefCell, collections::HashMap};
|
|
|
|
use gc::{allocator::GCAllocator, gc_ref::GcRef, trace::GCTrace};
|
|
|
|
use crate::ast::statement::Statement;
|
|
|
|
use super::{
|
|
ast_walker::{Interpret, RuntimeError},
|
|
types::Primitive,
|
|
};
|
|
|
|
#[derive(Default, GCTrace)]
|
|
pub struct Environment {
|
|
variables: HashMap<String, Primitive>,
|
|
parent: Option<GcRef<RefCell<Environment>>>,
|
|
}
|
|
|
|
impl Environment {
|
|
pub fn set_var(&mut self, name: String, v: Primitive) -> Option<Primitive> {
|
|
self.variables.insert(name, v)
|
|
}
|
|
pub fn get_var(&self, name: &str) -> Option<Primitive> {
|
|
self.variables
|
|
.get(name)
|
|
.cloned()
|
|
.or_else(|| self.parent.as_ref().and_then(|v| v.borrow().get_var(name)))
|
|
}
|
|
}
|
|
|
|
pub struct World {
|
|
env: GcRef<Environment>,
|
|
_gc: GCAllocator,
|
|
}
|
|
|
|
impl World {
|
|
pub fn set_var(&mut self, _name: String, _v: Primitive) -> Option<Primitive> {
|
|
todo!()
|
|
// self.env.set_var(name, v)
|
|
}
|
|
pub fn get_var(&self, name: &str) -> Option<Primitive> {
|
|
self.env.get_var(name)
|
|
}
|
|
}
|
|
|
|
impl World {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
pub fn exec(&mut self, nodes: Vec<Statement>) -> Result<Primitive, RuntimeError> {
|
|
nodes
|
|
.into_iter()
|
|
.try_fold(Primitive::Nil, |_, stmnt| stmnt.interpret(self))
|
|
}
|
|
}
|
|
|
|
impl Default for World {
|
|
fn default() -> Self {
|
|
let mut gc = GCAllocator::default();
|
|
let env = gc.alloc(Environment::default());
|
|
Self { env, _gc: gc }
|
|
}
|
|
}
|