From 9c2a24c2d9ed18da06b745b931f7482d0fb869e2 Mon Sep 17 00:00:00 2001 From: TriMill Date: Wed, 14 Sep 2022 11:16:53 -0400 Subject: [PATCH] function refactoring --- src/eval.rs | 4 +- src/lib.rs | 1 + src/stdlib/mod.rs | 24 ++--- src/value.rs | 230 ++++++++++++++++++++++++++-------------------- 4 files changed, 147 insertions(+), 112 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 1054fc5..45a0abb 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -152,7 +152,7 @@ pub fn eval_stmt(stmt: &Stmt, env: EnvRef) -> Result<(), Unwind> { }, Stmt::Fn { name, args, body } => { let name = name.ty.clone().as_ident().unwrap(); - let func = Func { + let func = Func::Func { name: Some(name.clone()), args: args.into_iter().map(|a| a.ty.clone().as_ident().unwrap()).collect(), env: env.clone(), @@ -208,7 +208,7 @@ pub fn eval_expr(expr: &Expr, env: EnvRef) -> Result { l.index(&idx).map_err(|e| RuntimeError::new(e, pos.clone())) }, Expr::Fn { args, body } => { - let func = Func { + let func = Func::Func { name: None, args: args.into_iter().map(|a| a.ty.clone().as_ident().unwrap()).collect(), env: env.clone(), diff --git a/src/lib.rs b/src/lib.rs index bf74c4f..342f84f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,7 @@ impl RuntimeError { } } + impl fmt::Display for ParserError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Error: {}\n In {} at {},{}\n", diff --git a/src/stdlib/mod.rs b/src/stdlib/mod.rs index 5127f84..82c9d83 100644 --- a/src/stdlib/mod.rs +++ b/src/stdlib/mod.rs @@ -2,32 +2,32 @@ use std::{rc::Rc, io::Write, cmp::Ordering}; use num_traits::ToPrimitive; -use crate::{value::{Value, BuiltinFunc}, eval::Environment}; +use crate::{value::{Value, Func}, eval::Environment}; pub fn load(env: &mut Environment) { let mut name: Rc; name = Rc::from("str"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_str, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_str, arg_count: 1, name })); name = Rc::from("repr"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_repr, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_repr, arg_count: 1, name })); name = Rc::from("print"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_print, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_print, arg_count: 1, name })); name = Rc::from("println"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_println, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_println, arg_count: 1, name })); name = Rc::from("input"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_input, arg_count: 0, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_input, arg_count: 0, name })); name = Rc::from("ord"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_ord, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_ord, arg_count: 1, name })); name = Rc::from("chr"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_chr, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_chr, arg_count: 1, name })); name = Rc::from("range"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_range, arg_count: 2, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_range, arg_count: 2, name })); name = Rc::from("len"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_len, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_len, arg_count: 1, name })); name = Rc::from("re"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_re, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_re, arg_count: 1, name })); name = Rc::from("im"); - env.declare(name.clone(), Value::BuiltinFunc(BuiltinFunc { func: fn_im, arg_count: 1, name })); + env.declare(name.clone(), Value::Func(Func::Builtin { func: fn_im, arg_count: 1, name })); } fn fn_str(args: Vec) -> Result { diff --git a/src/value.rs b/src/value.rs index bf761dd..36001c3 100644 --- a/src/value.rs +++ b/src/value.rs @@ -8,62 +8,134 @@ pub type Rational = num_rational::Ratio; pub type Complex = num_complex::Complex64; #[derive(Clone)] -pub struct BuiltinFunc { - pub name: Rc, - pub func: fn(Vec) -> Result, - pub arg_count: usize -} - -impl fmt::Debug for BuiltinFunc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("BuiltinFn").field("name", &self.name).field("arg_count", &self.arg_count).finish() +pub enum Func { + Func { + name: Option>, + args: Vec>, + env: EnvRef, + func: Stmt + }, + Builtin { + name: Rc, + func: fn(Vec) -> Result, + arg_count: usize } } -impl Iterator for BuiltinFunc { - type Item = Result; - - fn next(&mut self) -> Option { - // precondition: function takes zero arguments - match (self.func)(vec![]) { - Ok(Value::Nil) => None, - r => Some(r), - } - } -} - -#[derive(Clone)] -pub struct Func { - pub name: Option>, - pub args: Vec>, - pub env: EnvRef, - pub func: Stmt -} - impl fmt::Debug for Func { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Func") - .field("name", &self.name) - .field("args", &self.args) - .field("func", &self.func) - .finish_non_exhaustive() + match self { + Self::Func { name, args, .. } + => f.debug_struct("Func::Func") + .field("name", name) + .field("args", args) + .finish_non_exhaustive(), + Self::Builtin { name, arg_count, .. } + => f.debug_struct("Func::Builtin") + .field("name", name) + .field("arg_count", arg_count) + .finish_non_exhaustive(), + } + } + +} + +impl Func { + pub fn arg_count(&self) -> usize { + match self { + Self::Builtin { arg_count, .. } => *arg_count, + Self::Func { args, .. } => args.len() + } + } + + pub fn call(&self, arg_values: Vec, pos: &Position) -> Result { + match arg_values.len().cmp(&self.arg_count()) { + Ordering::Equal => match self { + Self::Builtin { func, .. } + => func(arg_values).map_err(|e| RuntimeError::new(e, pos.clone())), + Self::Func { name, args, func, env } => { + let mut env = Environment::extend(env.clone()); + for (k, v) in args.iter().zip(arg_values.iter()) { + env.declare(k.clone(), v.clone()); + } + match eval_stmt(func, env.wrap()) { + Ok(()) => Ok(Value::Nil), + Err(Unwind::Return{ value, .. }) => Ok(value), + Err(e) => Err(e.as_error().exit_fn(name.clone(), pos.clone())) + } + } + } + Ordering::Less => Err(RuntimeError::new( + format!("Not enough arguments for function: expected {}, got {}", self.arg_count(), arg_values.len()), + pos.clone() + )), + Ordering::Greater => Err(RuntimeError::new( + format!("Too many arguments for function: expected {}, got {}", self.arg_count(), arg_values.len()), + pos.clone() + )) + } + } +} + +pub enum EitherRteOrString { + Rte(RuntimeError), String(String) +} + +impl EitherRteOrString { + pub fn to_rte(self, pos: &Position) -> RuntimeError { + match self { + Self::Rte(e) => e, + Self::String(s) => RuntimeError::new(s, pos.clone()) + } + } +} + +impl From for EitherRteOrString { + fn from(s: String) -> Self { + Self::String(s) + } +} + +impl From for EitherRteOrString { + fn from(e: RuntimeError) -> Self { + Self::Rte(e) } } impl Iterator for Func { - type Item = Result; - + type Item = Result; fn next(&mut self) -> Option { - // precondition: function takes zero arguments - let env = Environment::extend(self.env.clone()).wrap(); - match eval_stmt(&self.func, env) { - Ok(_) => None, - Err(Unwind::Return{ value: Value::Nil, .. }) => None, - Err(Unwind::Return{ value, .. }) => Some(Ok(value)), - Err(e) => Some(Err(e.as_error())) + match self { + Self::Builtin { func, .. } => match (func)(vec![]) { + Ok(Value::Nil) => None, + r => Some(r.map_err(|e| e.into())), + }, + Self::Func { func, env, .. } => { + let env = Environment::extend(env.clone()).wrap(); + match eval_stmt(&func, env) { + Ok(_) => None, + Err(Unwind::Return{ value: Value::Nil, .. }) => None, + Err(Unwind::Return{ value, .. }) => Some(Ok(value)), + Err(e) => Some(Err(e.as_error().into())) + } + } } } } +// +//#[derive(Clone)] +//pub struct BuiltinFunc { +// pub name: Rc, +// pub func: fn(Vec) -> Result, +// pub arg_count: usize +//} +// +//impl fmt::Debug for BuiltinFunc { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// f.debug_struct("BuiltinFn").field("name", &self.name).field("arg_count", &self.arg_count).finish() +// } +//} +// #[derive(Clone, Debug)] pub struct Data { @@ -87,7 +159,6 @@ pub enum Value { Char(char), String(Rc), List(Rc>>), Map(Rc>), - BuiltinFunc(BuiltinFunc), Func(Func), Data(Data), } @@ -113,16 +184,9 @@ impl Value { => Ok(Box::new(s.chars() .map(Value::Char).map(Ok))), Value::List(l) => Ok(Box::new(l.borrow().clone().into_iter().map(Ok))), - Value::BuiltinFunc(bf) => { - if bf.arg_count == 0 { - Ok(Box::new(bf.clone().map(|e| e.map_err(|e| RuntimeError::new(e, pos.clone()))))) - } else { - Err("Only zero-argument functions can be used as iterators".into()) - } - }, Value::Func(f) => { - if f.args.len() == 0 { - Ok(Box::new(f.clone())) + if f.arg_count() == 0 { + Ok(Box::new(f.clone().map(|e| e.map_err(|e| e.to_rte(pos))))) } else { Err("Only zero-argument functions can be used as iterators".into()) } @@ -132,45 +196,10 @@ impl Value { } pub fn call(&self, args: Vec, pos: &Position) -> Result { - match self { - Value::BuiltinFunc(f) => { - match args.len().cmp(&f.arg_count) { - Ordering::Equal => - (f.func)(args).map_err(|e| RuntimeError::new(e, pos.clone())), - Ordering::Less => Err(RuntimeError::new( - format!("Not enough arguments for function: expected {}, got {}", f.arg_count, args.len()), - pos.clone() - )), - Ordering::Greater => Err(RuntimeError::new( - format!("Too many arguments for function: expected {}, got {}", f.arg_count, args.len()), - pos.clone() - )) - } - }, - Value::Func(f) => { - match args.len().cmp(&f.args.len()) { - Ordering::Equal => { - let mut env = Environment::extend(f.env.clone()); - for (k, v) in f.args.iter().zip(args.iter()) { - env.declare(k.clone(), v.clone()); - } - match eval_stmt(&f.func, env.wrap()) { - Ok(()) => Ok(Value::Nil), - Err(Unwind::Return{ value, .. }) => Ok(value), - Err(e) => Err(e.as_error().exit_fn(f.name.clone(), pos.clone())) - } - }, - Ordering::Less => Err(RuntimeError::new( - format!("Not enough arguments for function: expected {}, got {}", f.args.len(), args.len()), - pos.clone() - )), - Ordering::Greater => Err(RuntimeError::new( - format!("Too many arguments for function: expected {}, got {}", f.args.len(), args.len()), - pos.clone() - )) - } - }, - _ => Err(RuntimeError::new("Cannot call", pos.clone())) + if let Value::Func(f) = self { + f.call(args, pos) + } else { + Err(RuntimeError::new("Cannot call", pos.clone())) } } @@ -187,8 +216,8 @@ impl Value { Self::List(l) => Rc::from(format!("{:?}", l)), // TODO fix Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix Self::Type(_) => todo!(), - Self::BuiltinFunc(bf) => Rc::from(format!("", bf.name, bf.func as *const ())), - Self::Func(f) => match &f.name { + Self::Func(Func::Builtin { name, func, .. }) => Rc::from(format!("", name, *func as *const ())), + Self::Func(Func::Func { name, .. }) => match name { Some(name) => Rc::from(format!("", name)), None => Rc::from(""), }, @@ -209,8 +238,8 @@ impl Value { Self::List(l) => Rc::from(format!("{:?}", l.borrow())), // TODO fix Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix Self::Type(_) => todo!(), - Self::BuiltinFunc(bf) => Rc::from(format!("", bf.name, bf.func as *const ())), - Self::Func(f) => match &f.name { + Self::Func(Func::Builtin { name, func, .. }) => Rc::from(format!("", name, *func as *const ())), + Self::Func(Func::Func { name, .. }) => match name { Some(name) => Rc::from(format!("", name)), None => Rc::from(""), }, @@ -286,8 +315,13 @@ impl PartialEq for Value { (Self::String(a), Self::String(b)) => a == b, (Self::List(a), Self::List(b)) => a == b, (Self::Map(_), Self::Map(_)) => todo!("Can't test maps for equality yet"), - (Self::BuiltinFunc(a), Self::BuiltinFunc(b)) - => (a.func as *const ()) == (b.func as *const ()) && a.arg_count == b.arg_count, + (Self::Func(f1), Self::Func(f2)) => match (f1, f2) { + ( + Func::Builtin { func: f1, arg_count: c1, .. }, + Func::Builtin { func: f2, arg_count: c2, .. } + ) => (*f1 as *const ()) == (*f2 as *const ()) && c1 == c2, + _ => false + } (Self::Data(_), Self::Data(_)) => todo!("Can't compare data yet"), _ => false }