diff options
author | Akshay <[email protected]> | 2021-03-29 07:42:15 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2021-03-29 07:42:15 +0100 |
commit | f6e89e13d6b4db769f30b64408fc4b5995ab6cbb (patch) | |
tree | 0c24aee57b48ec2185f2c176b1b09e8d94fbae40 /src/lisp | |
parent | 992141878227439cd517d05b68f15e57d77452a5 (diff) |
functions are first class
Diffstat (limited to 'src/lisp')
-rw-r--r-- | src/lisp/eval.rs | 74 |
1 files changed, 40 insertions, 34 deletions
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index f49efb9..3a3a61e 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs | |||
@@ -30,42 +30,47 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result<LispExpr, LispError> | |||
30 | "lambda" => create_lambda(&li[1..]), | 30 | "lambda" => create_lambda(&li[1..]), |
31 | "if" => eval_if(&li[1..], app), | 31 | "if" => eval_if(&li[1..], app), |
32 | _ => { | 32 | _ => { |
33 | let func_expr = eval(&func_expr, app)?; | 33 | let mut new_ls = vec![eval(&func_expr, app)?]; |
34 | match func_expr { | 34 | new_ls.extend(li[1..].to_vec()); |
35 | LispExpr::PrimitiveFunc(f) => { | 35 | eval(&(LispExpr::List(new_ls)), app) |
36 | let mut args = Vec::new(); | ||
37 | for item in li[1..].iter() { | ||
38 | args.push(eval(item, app)?); | ||
39 | } | ||
40 | f.call(&args, app) | ||
41 | } | ||
42 | LispExpr::Function(f) => { | ||
43 | let mut args = Vec::new(); | ||
44 | for item in li[1..].iter() { | ||
45 | let i = eval(item, app)?; | ||
46 | args.push(i); | ||
47 | } | ||
48 | if f.params.len() != args.len() { | ||
49 | info!("too many or too little number of args"); | ||
50 | Err(EvalError::ArgumentCount(Arity::Exact(f.params.len())) | ||
51 | .into()) | ||
52 | } else { | ||
53 | let nested_env: Environment = | ||
54 | f.params.into_iter().zip(args).collect(); | ||
55 | app.lisp_env.push(nested_env); | ||
56 | let result = if f.body.is_empty() { | ||
57 | Ok(LispExpr::Unit) | ||
58 | } else { | ||
59 | eval(&LispExpr::List(f.body), app) | ||
60 | }; | ||
61 | app.lisp_env.pop(); | ||
62 | return result; | ||
63 | } | ||
64 | } | ||
65 | _ => Err(EvalError::BadForm.into()), | ||
66 | } | ||
67 | } | 36 | } |
68 | }, | 37 | }, |
38 | LispExpr::PrimitiveFunc(f) => { | ||
39 | let mut args = Vec::new(); | ||
40 | for item in li[1..].iter() { | ||
41 | args.push(eval(item, app)?); | ||
42 | } | ||
43 | f.call(&args, app) | ||
44 | } | ||
45 | LispExpr::Function(f) => { | ||
46 | let mut args = Vec::new(); | ||
47 | for item in li[1..].iter() { | ||
48 | let i = eval(item, app)?; | ||
49 | args.push(i); | ||
50 | } | ||
51 | if f.params.len() != args.len() { | ||
52 | info!("too many or too little number of args"); | ||
53 | Err(EvalError::ArgumentCount(Arity::Exact(f.params.len())).into()) | ||
54 | } else { | ||
55 | let nested_env: Environment = | ||
56 | f.params.clone().into_iter().zip(args).collect(); | ||
57 | app.lisp_env.push(nested_env); | ||
58 | let result = if f.body.is_empty() { | ||
59 | Ok(LispExpr::Unit) | ||
60 | } else { | ||
61 | eval(&LispExpr::List(f.body.clone()), app) | ||
62 | }; | ||
63 | app.lisp_env.pop(); | ||
64 | return result; | ||
65 | } | ||
66 | } | ||
67 | LispExpr::List(_) => { | ||
68 | info!("list as funciton"); | ||
69 | let func_expr = eval(&func_expr, app)?; | ||
70 | let mut new_ls = vec![func_expr]; | ||
71 | new_ls.extend(li[1..].to_vec()); | ||
72 | eval(&(LispExpr::List(new_ls)), app) | ||
73 | } | ||
69 | _ => Err(EvalError::BadForm.into()), | 74 | _ => Err(EvalError::BadForm.into()), |
70 | } | 75 | } |
71 | } | 76 | } |
@@ -74,6 +79,7 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result<LispExpr, LispError> | |||
74 | } | 79 | } |
75 | 80 | ||
76 | pub fn define_var(args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> { | 81 | pub fn define_var(args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> { |
82 | info!("defining"); | ||
77 | let arity = Arity::Exact(2); | 83 | let arity = Arity::Exact(2); |
78 | if !arity.is_valid(args) { | 84 | if !arity.is_valid(args) { |
79 | return Err(arity.to_error()); | 85 | return Err(arity.to_error()); |