From 1ea2d8ba9fef3bee2c757d19d8b42e541e3fe390 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 8 Mar 2021 00:04:44 -0500 Subject: Implement functions, both top-level and anonymous Implement both top-level and anonymous functions, but not closures in either case. --- src/interpreter/mod.rs | 56 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) (limited to 'src/interpreter/mod.rs') diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index adff3568c2c3..fc1556d1c292 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -2,13 +2,13 @@ mod error; mod value; pub use self::error::{Error, Result}; -pub use self::value::Value; -use crate::ast::{BinaryOperator, Expr, Ident, Literal, UnaryOperator}; +pub use self::value::{Function, Value}; +use crate::ast::{BinaryOperator, Expr, FunctionType, Ident, Literal, Type, UnaryOperator}; use crate::common::env::Env; #[derive(Debug, Default)] pub struct Interpreter<'a> { - env: Env<'a, Value>, + env: Env<'a, Value<'a>>, } impl<'a> Interpreter<'a> { @@ -16,14 +16,14 @@ impl<'a> Interpreter<'a> { Self::default() } - fn resolve(&self, var: &'a Ident<'a>) -> Result { + fn resolve(&self, var: &'a Ident<'a>) -> Result> { self.env .resolve(var) .cloned() .ok_or_else(|| Error::UndefinedVariable(var.to_owned())) } - pub fn eval(&mut self, expr: &'a Expr<'a>) -> Result { + pub fn eval(&mut self, expr: &'a Expr<'a>) -> Result> { match expr { Expr::Ident(id) => self.resolve(id), Expr::Literal(Literal::Int(i)) => Ok((*i).into()), @@ -63,12 +63,44 @@ impl<'a> Interpreter<'a> { else_, } => { let condition = self.eval(condition)?; - if *(condition.into_type::()?) { + if *(condition.as_type::()?) { 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::>>()?, + ); + 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::()?)) + } + Expr::Fun(fun) => Ok(Value::from(value::Function { + // TODO + type_: FunctionType { + args: fun.args.iter().map(|_| Type::Int).collect(), + ret: Box::new(Type::Int), + }, + args: fun.args.iter().map(|arg| arg.to_owned()).collect(), + body: fun.body.to_owned(), + })), } } } @@ -92,12 +124,12 @@ mod tests { fn parse_eval(src: &str) -> T where - for<'a> &'a T: TryFrom<&'a Val>, + for<'a> &'a T: TryFrom<&'a Val<'a>>, T: Clone + TypeOf, { let expr = crate::parser::expr(src).unwrap().1; let res = eval(&expr).unwrap(); - res.into_type::().unwrap().clone() + res.as_type::().unwrap().clone() } #[test] @@ -108,7 +140,7 @@ mod tests { rhs: int_lit(2), }; let res = eval(&expr).unwrap(); - assert_eq!(*res.into_type::().unwrap(), 2); + assert_eq!(*res.as_type::().unwrap(), 2); } #[test] @@ -122,4 +154,10 @@ mod tests { let res = parse_eval::("let x = 1 in if x == 1 then 2 else 4"); assert_eq!(res, 2); } + + #[test] + fn function_call() { + let res = parse_eval::("let id = fn x = x in id 1"); + assert_eq!(res, 1); + } } -- cgit 1.4.1