diff options
Diffstat (limited to 'users/glittershark/achilles/src/interpreter')
-rw-r--r-- | users/glittershark/achilles/src/interpreter/error.rs | 19 | ||||
-rw-r--r-- | users/glittershark/achilles/src/interpreter/mod.rs | 182 | ||||
-rw-r--r-- | users/glittershark/achilles/src/interpreter/value.rs | 203 |
3 files changed, 0 insertions, 404 deletions
diff --git a/users/glittershark/achilles/src/interpreter/error.rs b/users/glittershark/achilles/src/interpreter/error.rs deleted file mode 100644 index 268d6f479a1e..000000000000 --- a/users/glittershark/achilles/src/interpreter/error.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::result; - -use thiserror::Error; - -use crate::ast::{Ident, Type}; - -#[derive(Debug, PartialEq, Eq, Error)] -pub enum Error { - #[error("Undefined variable {0}")] - UndefinedVariable(Ident<'static>), - - #[error("Unexpected type {actual}, expected type {expected}")] - InvalidType { - actual: Type<'static>, - expected: Type<'static>, - }, -} - -pub type Result<T> = result::Result<T, Error>; diff --git a/users/glittershark/achilles/src/interpreter/mod.rs b/users/glittershark/achilles/src/interpreter/mod.rs deleted file mode 100644 index a8ba2dd3acdc..000000000000 --- a/users/glittershark/achilles/src/interpreter/mod.rs +++ /dev/null @@ -1,182 +0,0 @@ -mod error; -mod value; - -pub use self::error::{Error, Result}; -pub use self::value::{Function, Value}; -use crate::ast::hir::{Binding, Expr}; -use crate::ast::{BinaryOperator, FunctionType, Ident, Literal, Type, UnaryOperator}; -use crate::common::env::Env; - -#[derive(Debug, Default)] -pub struct Interpreter<'a> { - env: Env<&'a Ident<'a>, Value<'a>>, -} - -impl<'a> Interpreter<'a> { - pub fn new() -> Self { - Self::default() - } - - fn resolve(&self, var: &'a Ident<'a>) -> Result<Value<'a>> { - self.env - .resolve(var) - .cloned() - .ok_or_else(|| Error::UndefinedVariable(var.to_owned())) - } - - pub fn eval(&mut self, expr: &'a Expr<'a, Type>) -> Result<Value<'a>> { - let res = match expr { - Expr::Ident(id, _) => self.resolve(id), - Expr::Literal(Literal::Int(i), _) => Ok((*i).into()), - Expr::Literal(Literal::Bool(b), _) => Ok((*b).into()), - Expr::Literal(Literal::String(s), _) => Ok(s.clone().into()), - Expr::Literal(Literal::Unit, _) => unreachable!(), - Expr::UnaryOp { op, rhs, .. } => { - let rhs = self.eval(rhs)?; - match op { - UnaryOperator::Neg => -rhs, - _ => unimplemented!(), - } - } - Expr::BinaryOp { lhs, op, rhs, .. } => { - let lhs = self.eval(lhs)?; - let rhs = self.eval(rhs)?; - match op { - BinaryOperator::Add => lhs + rhs, - BinaryOperator::Sub => lhs - rhs, - BinaryOperator::Mul => lhs * rhs, - BinaryOperator::Div => lhs / rhs, - BinaryOperator::Pow => todo!(), - BinaryOperator::Equ => Ok(lhs.eq(&rhs).into()), - BinaryOperator::Neq => todo!(), - } - } - Expr::Let { bindings, body, .. } => { - self.env.push(); - for Binding { ident, body, .. } in bindings { - let val = self.eval(body)?; - self.env.set(ident, val); - } - let res = self.eval(body)?; - self.env.pop(); - Ok(res) - } - Expr::If { - condition, - then, - else_, - .. - } => { - let condition = self.eval(condition)?; - if *(condition.as_type::<bool>()?) { - self.eval(then) - } else { - self.eval(else_) - } - } - Expr::Call { ref fun, args, .. } => { - let fun = self.eval(fun)?; - let expected_type = FunctionType { - args: args.iter().map(|_| Type::Int).collect(), - ret: Box::new(Type::Int), - }; - - let Function { - args: function_args, - body, - .. - } = fun.as_function(expected_type)?; - let arg_values = function_args.iter().zip( - args.iter() - .map(|v| self.eval(v)) - .collect::<Result<Vec<_>>>()?, - ); - let mut interpreter = Interpreter::new(); - for (arg_name, arg_value) in arg_values { - interpreter.env.set(arg_name, arg_value); - } - Ok(Value::from(*interpreter.eval(body)?.as_type::<i64>()?)) - } - Expr::Fun { - type_args: _, - args, - body, - type_, - } => { - let type_ = match type_ { - Type::Function(ft) => ft.clone(), - _ => unreachable!("Function expression without function type"), - }; - - Ok(Value::from(value::Function { - // TODO - type_, - args: args.iter().map(|(arg, _)| arg.to_owned()).collect(), - body: (**body).to_owned(), - })) - } - }?; - debug_assert_eq!(&res.type_(), expr.type_()); - Ok(res) - } -} - -pub fn eval<'a>(expr: &'a Expr<'a, Type>) -> Result<Value<'a>> { - let mut interpreter = Interpreter::new(); - interpreter.eval(expr) -} - -#[cfg(test)] -mod tests { - use std::convert::TryFrom; - - use super::value::{TypeOf, Val}; - use super::*; - use BinaryOperator::*; - - fn int_lit(i: u64) -> Box<Expr<'static, Type<'static>>> { - Box::new(Expr::Literal(Literal::Int(i), Type::Int)) - } - - fn do_eval<T>(src: &str) -> T - where - for<'a> &'a T: TryFrom<&'a Val<'a>>, - T: Clone + TypeOf, - { - let expr = crate::parser::expr(src).unwrap().1; - let hir = crate::tc::typecheck_expr(expr).unwrap(); - let res = eval(&hir).unwrap(); - res.as_type::<T>().unwrap().clone() - } - - #[test] - fn simple_addition() { - let expr = Expr::BinaryOp { - lhs: int_lit(1), - op: Mul, - rhs: int_lit(2), - type_: Type::Int, - }; - let res = eval(&expr).unwrap(); - assert_eq!(*res.as_type::<i64>().unwrap(), 2); - } - - #[test] - fn variable_shadowing() { - let res = do_eval::<i64>("let x = 1 in (let x = 2 in x) + x"); - assert_eq!(res, 3); - } - - #[test] - fn conditional_with_equals() { - let res = do_eval::<i64>("let x = 1 in if x == 1 then 2 else 4"); - assert_eq!(res, 2); - } - - #[test] - #[ignore] - fn function_call() { - let res = do_eval::<i64>("let id = fn x = x in id 1"); - assert_eq!(res, 1); - } -} diff --git a/users/glittershark/achilles/src/interpreter/value.rs b/users/glittershark/achilles/src/interpreter/value.rs deleted file mode 100644 index 55ba42f9de58..000000000000 --- a/users/glittershark/achilles/src/interpreter/value.rs +++ /dev/null @@ -1,203 +0,0 @@ -use std::borrow::Cow; -use std::convert::TryFrom; -use std::fmt::{self, Display}; -use std::ops::{Add, Div, Mul, Neg, Sub}; -use std::rc::Rc; -use std::result; - -use derive_more::{Deref, From, TryInto}; - -use super::{Error, Result}; -use crate::ast::hir::Expr; -use crate::ast::{FunctionType, Ident, Type}; - -#[derive(Debug, Clone)] -pub struct Function<'a> { - pub type_: FunctionType<'a>, - pub args: Vec<Ident<'a>>, - pub body: Expr<'a, Type<'a>>, -} - -#[derive(From, TryInto)] -#[try_into(owned, ref)] -pub enum Val<'a> { - Int(i64), - Float(f64), - Bool(bool), - String(Cow<'a, str>), - Function(Function<'a>), -} - -impl<'a> TryFrom<Val<'a>> for String { - type Error = (); - - fn try_from(value: Val<'a>) -> result::Result<Self, Self::Error> { - match value { - Val::String(s) => Ok(s.into_owned()), - _ => Err(()), - } - } -} - -impl<'a> fmt::Debug for Val<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Val::Int(x) => f.debug_tuple("Int").field(x).finish(), - Val::Float(x) => f.debug_tuple("Float").field(x).finish(), - Val::Bool(x) => f.debug_tuple("Bool").field(x).finish(), - Val::String(s) => f.debug_tuple("String").field(s).finish(), - Val::Function(Function { type_, .. }) => { - f.debug_struct("Function").field("type_", type_).finish() - } - } - } -} - -impl<'a> PartialEq for Val<'a> { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Val::Int(x), Val::Int(y)) => x == y, - (Val::Float(x), Val::Float(y)) => x == y, - (Val::Bool(x), Val::Bool(y)) => x == y, - (Val::Function(_), Val::Function(_)) => false, - (_, _) => false, - } - } -} - -impl<'a> From<u64> for Val<'a> { - fn from(i: u64) -> Self { - Self::from(i as i64) - } -} - -impl<'a> Display for Val<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Val::Int(x) => x.fmt(f), - Val::Float(x) => x.fmt(f), - Val::Bool(x) => x.fmt(f), - Val::String(s) => write!(f, "{:?}", s), - Val::Function(Function { type_, .. }) => write!(f, "<{}>", type_), - } - } -} - -impl<'a> Val<'a> { - pub fn type_(&self) -> Type { - match self { - Val::Int(_) => Type::Int, - Val::Float(_) => Type::Float, - Val::Bool(_) => Type::Bool, - Val::String(_) => Type::CString, - Val::Function(Function { type_, .. }) => Type::Function(type_.clone()), - } - } - - pub fn as_type<'b, T>(&'b self) -> Result<&'b T> - where - T: TypeOf + 'b + Clone, - &'b T: TryFrom<&'b Self>, - { - <&T>::try_from(self).map_err(|_| Error::InvalidType { - actual: self.type_().to_owned(), - expected: <T as TypeOf>::type_of(), - }) - } - - pub fn as_function<'b>(&'b self, function_type: FunctionType) -> Result<&'b Function<'a>> { - match self { - Val::Function(f) if f.type_ == function_type => Ok(&f), - _ => Err(Error::InvalidType { - actual: self.type_().to_owned(), - expected: Type::Function(function_type.to_owned()), - }), - } - } -} - -#[derive(Debug, PartialEq, Clone, Deref)] -pub struct Value<'a>(Rc<Val<'a>>); - -impl<'a> Display for Value<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl<'a, T> From<T> for Value<'a> -where - Val<'a>: From<T>, -{ - fn from(x: T) -> Self { - Self(Rc::new(x.into())) - } -} - -impl<'a> Neg for Value<'a> { - type Output = Result<Value<'a>>; - - fn neg(self) -> Self::Output { - Ok((-self.as_type::<i64>()?).into()) - } -} - -impl<'a> Add for Value<'a> { - type Output = Result<Value<'a>>; - - fn add(self, rhs: Self) -> Self::Output { - Ok((self.as_type::<i64>()? + rhs.as_type::<i64>()?).into()) - } -} - -impl<'a> Sub for Value<'a> { - type Output = Result<Value<'a>>; - - fn sub(self, rhs: Self) -> Self::Output { - Ok((self.as_type::<i64>()? - rhs.as_type::<i64>()?).into()) - } -} - -impl<'a> Mul for Value<'a> { - type Output = Result<Value<'a>>; - - fn mul(self, rhs: Self) -> Self::Output { - Ok((self.as_type::<i64>()? * rhs.as_type::<i64>()?).into()) - } -} - -impl<'a> Div for Value<'a> { - type Output = Result<Value<'a>>; - - fn div(self, rhs: Self) -> Self::Output { - Ok((self.as_type::<f64>()? / rhs.as_type::<f64>()?).into()) - } -} - -pub trait TypeOf { - fn type_of() -> Type<'static>; -} - -impl TypeOf for i64 { - fn type_of() -> Type<'static> { - Type::Int - } -} - -impl TypeOf for bool { - fn type_of() -> Type<'static> { - Type::Bool - } -} - -impl TypeOf for f64 { - fn type_of() -> Type<'static> { - Type::Float - } -} - -impl TypeOf for String { - fn type_of() -> Type<'static> { - Type::CString - } -} |