145 lines
4.1 KiB
Rust
145 lines
4.1 KiB
Rust
|
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<T> = Result<T, String>;
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct State<'a> {
|
||
|
environments: ScopeStack<'a, DefId, RuntimeValue>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
struct RuntimeError {
|
||
|
msg: String
|
||
|
}
|
||
|
|
||
|
impl From<String> 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<Item=String>) -> 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<Expression> 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<Result<String, String>> {
|
||
|
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<Option<RuntimeValue>> {
|
||
|
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<Expression> {
|
||
|
use Expression::Unimplemented;
|
||
|
Ok(match expression {
|
||
|
lit @ Expression::Literal(_) => lit,
|
||
|
Expression::Tuple(items) => Expression::Tuple(items.into_iter().map(|expr| self.expression(expr)).collect::<EvalResult<Vec<Expression>>>()?),
|
||
|
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<Expression>) -> EvalResult<Expression> {
|
||
|
Err("Call expression not implemented".to_string().into())
|
||
|
}
|
||
|
}
|
||
|
|