From f94f22a3d0aeff98cc9169c94b683aa139e9c81c Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 27 Mar 2021 13:16:25 +0530 Subject: implement char literals --- src/lisp/eval.rs | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'src/lisp/eval.rs') diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 5accec4..370b624 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs @@ -2,7 +2,7 @@ use crate::{ app::AppState, lisp::{ error::{EvalError, LispError}, - expr::{Ident, LispExpr, LispFunction}, + expr::{Arity, Ident, LispExpr, LispFunction}, number::LispNumber, EnvList, Environment, }, @@ -16,6 +16,7 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result match expr { LispExpr::Unit => Ok(expr.clone()), LispExpr::StringLit(_) => Ok(expr.clone()), + LispExpr::Char(_) => Ok(expr.clone()), LispExpr::Number(_) => Ok(expr.clone()), LispExpr::BoolLit(_) => Ok(expr.clone()), LispExpr::Ident(ref id) => lookup_extended(&app.lisp_env, id), @@ -26,6 +27,7 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result "define" => define_var(&li[1..], app), "set!" => set_var(&li[1..], app), "lambda" => create_lambda(&li[1..]), + "if" => eval_if(&li[1..], app), _ => { let func_expr = eval(&func_expr, app)?; match func_expr { @@ -37,17 +39,17 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result f.call(&args, app) } LispExpr::Function(f) => { - info!("eval custom func"); let mut args = Vec::new(); for item in li[1..].iter() { - args.push(eval(item, app)?); + let i = eval(item, app)?; + args.push(i); } if f.params.len() != args.len() { info!("too many or too little number of args"); - Err(EvalError::ArgumentCount(Some(f.params.len() as u32)) + Err(EvalError::ArgumentCount(Arity::Exact(f.params.len())) .into()) } else { - let mut nested_env: Environment = + let nested_env: Environment = f.params.into_iter().zip(args).collect(); app.lisp_env.push(nested_env); let result = if f.body.is_empty() { @@ -71,9 +73,9 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result } pub fn define_var(args: &[LispExpr], app: &mut AppState) -> Result { - if args.len() != 2 { - error!("Invalid arity for `define`"); - return Err(EvalError::ArgumentCount(Some(2)).into()); + let arity = Arity::Exact(2); + if !arity.is_valid(args) { + return Err(arity.to_error()); } match args { [LispExpr::Ident(id), expr] => { @@ -107,6 +109,7 @@ pub fn define_var(args: &[LispExpr], app: &mut AppState) -> Result Result Result { - if args.len() != 2 { - error!("Invalid arity for `define`"); - return Err(EvalError::ArgumentCount(Some(2)).into()); + let arity = Arity::Exact(2); + if !arity.is_valid(args) { + return Err(arity.to_error()); } match args { [LispExpr::Ident(id), expr] => { @@ -147,10 +150,9 @@ pub fn set_var(args: &[LispExpr], app: &mut AppState) -> Result Result { - if cdr.len() != 2 { - // needs params and body - error!("needs params and body"); - return Err(EvalError::ArgumentCount(Some(2)).into()); + let arity: Arity = Arity::Exact(2); + if !arity.is_valid(cdr) { + return Err(arity.to_error()); } info!("creating lambda"); match cdr { @@ -172,6 +174,27 @@ pub fn create_lambda(cdr: &[LispExpr]) -> Result { } } +pub fn eval_if(args: &[LispExpr], app: &mut AppState) -> Result { + let arity = Arity::Exact(3); + if !arity.is_valid(args) { + return Err(arity.to_error()); + } else { + match args { + [predicate, then, else_] => { + let predicate = eval(&predicate, app)?; + if matches!(predicate, LispExpr::BoolLit(false)) { + return eval(&else_, app); + } else { + return eval(&then, app); + } + } + _ => { + panic!("panicked at `if` expression") + } + } + } +} + pub fn lookup_extended(env_list: &[Environment], key: &str) -> Result { if env_list.is_empty() { return Err(EvalError::UnboundVariable(key.into()).into()); -- cgit v1.2.3