diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index 7979e9b..d6f2b00 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::rc::Rc; use std::fmt::Write; use std::io; @@ -6,9 +7,11 @@ use itertools::Itertools; use util::StateStack; use ast_reducing::{ReducedAST, Stmt, Expr, Lit, Func}; +use typechecking::TypeContext; pub struct State<'a> { - values: StateStack<'a, Rc, ValueEntry> + values: StateStack<'a, Rc, ValueEntry>, + type_context_handle: Option>>, } macro_rules! builtin_binding { @@ -18,12 +21,12 @@ macro_rules! builtin_binding { } impl<'a> State<'a> { - pub fn new() -> State<'a> { + pub fn new(type_context_handle: Option>>) -> State<'a> { let mut values = StateStack::new(Some(format!("global"))); builtin_binding!("print", values); builtin_binding!("println", values); builtin_binding!("getline", values); - State { values } + State { values, type_context_handle } } pub fn debug_print(&self) -> String { @@ -415,7 +418,10 @@ impl<'a> State<'a> { if params.len() != args.len() { return Err(format!("calling a {}-argument function with {} args", params.len(), args.len())) } - let mut func_state = State { values: self.values.new_frame(name.map(|n| format!("{}", n))) }; + let mut func_state = State { + values: self.values.new_frame(name.map(|n| format!("{}", n))), + type_context_handle: self.type_context_handle.clone(), + }; for (param, val) in params.into_iter().zip(args.into_iter()) { let val = func_state.expression(val)?; func_state.values.insert(param, ValueEntry::Binding { constant: true, val }); @@ -518,7 +524,7 @@ mod eval_tests { macro_rules! fresh_env { ($string:expr, $correct:expr) => { - let mut state = State::new(); + let mut state = State::new(None); let all_output = state.evaluate(parse(tokenize($string)).0.unwrap().reduce(), true); let ref output = all_output.last().unwrap(); assert_eq!(**output, Ok($correct.to_string())); diff --git a/schala-lang/src/lib.rs b/schala-lang/src/lib.rs index 1038827..e8d0e1d 100644 --- a/schala-lang/src/lib.rs +++ b/schala-lang/src/lib.rs @@ -10,6 +10,9 @@ extern crate schala_repl; #[macro_use] extern crate schala_codegen; +use std::cell::RefCell; +use std::rc::Rc; + use itertools::Itertools; use schala_repl::{ProgrammingLanguageInterface, EvalOptions, TraceArtifact, UnfinishedComputation, FinishedComputation}; @@ -31,14 +34,15 @@ mod eval; #[PipelineSteps(tokenizing, parsing, symbol_table, typechecking, ast_reducing, eval)] pub struct Schala { state: eval::State<'static>, - type_context: typechecking::TypeContext + type_context: Rc>, } impl Schala { pub fn new() -> Schala { + let type_context = Rc::new(RefCell::new(typechecking::TypeContext::new())); Schala { - state: eval::State::new(), - type_context: typechecking::TypeContext::new(), + type_context: type_context.clone(), + state: eval::State::new(Some(type_context)), } } } @@ -70,9 +74,10 @@ fn parsing(_handle: &mut Schala, input: Vec, comp: Option<&mu } fn symbol_table(handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result { - match handle.type_context.add_top_level_types(&input) { + let add = handle.type_context.borrow_mut().add_top_level_types(&input); + match add { Ok(()) => { - let artifact = TraceArtifact::new("symbol_table", handle.type_context.debug_symbol_table()); + let artifact = TraceArtifact::new("symbol_table", handle.type_context.borrow().debug_symbol_table()); comp.map(|comp| comp.add_artifact(artifact)); Ok(input) }, @@ -81,7 +86,7 @@ fn symbol_table(handle: &mut Schala, input: parsing::AST, comp: Option<&mut Unfi } fn typechecking(handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result { - match handle.type_context.type_check_ast(&input) { + match handle.type_context.borrow_mut().type_check_ast(&input) { Ok(ty) => { comp.map(|comp| comp.add_artifact(TraceArtifact::new("type_check", format!("{:?}", ty)))); Ok(input)