use crate::reduced_ir::{ReducedIR, Expression, Function, Statement, Literal}; use crate::symbol_table::{DefId}; use crate::util::ScopeStack; use std::fmt::Write; use std::convert::From; type EvalResult = Result; #[derive(Debug)] pub struct State<'a> { environments: ScopeStack<'a, DefId, RuntimeValue>, } #[derive(Debug)] struct RuntimeError { msg: String } impl From for RuntimeError { fn from(msg: String) -> Self { Self { msg } } } impl RuntimeError { fn get_msg(&self) -> String { format!("Runtime error: {}", self.msg) } } fn paren_wrapped(terms: impl Iterator) -> String { let mut buf = String::new(); write!(buf, "(").unwrap(); for term in terms.map(Some).intersperse(None) { match term { Some(e) => write!(buf, "{}", e).unwrap(), None => write!(buf, ", ").unwrap(), }; } write!(buf, ")").unwrap(); buf } #[derive(Debug)] enum RuntimeValue { Expression(Expression), } impl From for RuntimeValue { fn from(ex: Expression) -> Self { Self::Expression(ex) } } fn expr_to_repl(expr: &Expression) -> String { match expr { Expression::Unimplemented => format!("Expression {:?} not implemented", expr), Expression::Literal(lit) => match lit { Literal::Nat(n) => format!("{}", n), Literal::Int(i) => format!("{}", i), Literal::Float(f) => format!("{}", f), Literal::Bool(b) => format!("{}", b), Literal::StringLit(s) => format!("\"{}\"", s), } Expression::Tuple(terms) => paren_wrapped(terms.iter().map(|x| expr_to_repl(x))), Expression::Assign { lval, rval } => { "".to_string() }, e => format!("Expression {:?} shouldn't be here", e), } } impl RuntimeValue { fn to_repl(&self) -> String { match self { RuntimeValue::Expression(ref expr) => expr_to_repl(expr) } } } impl<'a> State<'a> { pub fn new() -> Self { Self { environments: ScopeStack::new(Some("global".to_string())) } } pub fn evaluate(&mut self, reduced: ReducedIR, repl: bool) -> Vec> { let mut acc = vec![]; for statement in reduced.entrypoint.into_iter() { match self.statement(statement) { Ok(Some(output)) if repl => { acc.push(Ok(output.to_repl())) }, Ok(_) => (), Err(error) => { acc.push(Err(error.into())); return acc; } } } acc } fn statement(&mut self, stmt: Statement) -> EvalResult> { match stmt { Statement::Binding { id, expr, constant } => { println!("eval() binding id: {}", id); let evaluated = self.expression(expr)?; self.environments.insert(id, evaluated.into()); Ok(None) }, Statement::Expression(expr) => { let evaluated = self.expression(expr)?; Ok(Some(evaluated.into())) } } } fn expression(&mut self, expression: Expression) -> EvalResult { use Expression::Unimplemented; Ok(match expression { lit @ Expression::Literal(_) => lit, Expression::Tuple(items) => Expression::Tuple(items.into_iter().map(|expr| self.expression(expr)).collect::>>()?), Expression::Assign { lval, box rval } => { let mut env = self.environments.lookup(&lval); Unimplemented }, Expression::Call { f, args } => self.call_expression(f, args)?, Unimplemented => Unimplemented, Expression::ReductionError(e) => return Err(e.into()), _ => Expression::Literal(Literal::Nat(69420)), }) } fn call_expression(&mut self, f: Function, args: Vec) -> EvalResult { Err("Call expression not implemented".to_string().into()) } }