diff options
-rw-r--r-- | src/lisp/expr.rs | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs index 40b39eb..acd3365 100644 --- a/src/lisp/expr.rs +++ b/src/lisp/expr.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | use std::fmt; | 1 | use std::{convert::TryFrom, fmt}; |
2 | 2 | ||
3 | use crate::app::AppState; | 3 | use crate::app::AppState; |
4 | use crate::lisp::{error::LispError, number::LispNumber}; | 4 | use crate::lisp::{ |
5 | error::{EvalError, LispError}, | ||
6 | number::LispNumber, | ||
7 | }; | ||
5 | 8 | ||
6 | #[derive(Clone)] | 9 | #[derive(Clone)] |
7 | pub struct PrimitiveFunc { | 10 | pub struct PrimitiveFunc { |
@@ -13,13 +16,16 @@ impl PrimitiveFunc { | |||
13 | pub fn call(&self, args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> { | 16 | pub fn call(&self, args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> { |
14 | if let Some(arity) = self.arity { | 17 | if let Some(arity) = self.arity { |
15 | if args.len() < arity { | 18 | if args.len() < arity { |
16 | return Err(LispError::EvalError); | 19 | return Err(EvalError::ArgumentCount(self.arity.map(|u| u as u32)).into()); |
17 | } | 20 | } |
18 | } | 21 | } |
19 | (self.closure)(args, app) | 22 | (self.closure)(args, app) |
20 | } | 23 | } |
21 | } | 24 | } |
22 | 25 | ||
26 | pub type Ident = String; | ||
27 | pub type BoolLit = bool; | ||
28 | |||
23 | #[derive(Clone)] | 29 | #[derive(Clone)] |
24 | pub struct LispFunction { | 30 | pub struct LispFunction { |
25 | pub params: Vec<String>, | 31 | pub params: Vec<String>, |
@@ -33,7 +39,7 @@ pub enum LispExpr { | |||
33 | List(Vec<LispExpr>), | 39 | List(Vec<LispExpr>), |
34 | StringLit(String), | 40 | StringLit(String), |
35 | BoolLit(bool), | 41 | BoolLit(bool), |
36 | Ident(String), | 42 | Ident(Ident), |
37 | PrimitiveFunc(PrimitiveFunc), | 43 | PrimitiveFunc(PrimitiveFunc), |
38 | Function(LispFunction), | 44 | Function(LispFunction), |
39 | 45 | ||
@@ -110,3 +116,51 @@ impl fmt::Display for LispExpr { | |||
110 | Ok(()) | 116 | Ok(()) |
111 | } | 117 | } |
112 | } | 118 | } |
119 | |||
120 | impl TryFrom<LispExpr> for LispNumber { | ||
121 | type Error = LispError; | ||
122 | fn try_from(value: LispExpr) -> Result<Self, Self::Error> { | ||
123 | match value { | ||
124 | LispExpr::Number(i) => Ok(i), | ||
125 | _ => Err(LispError::Eval(EvalError::TypeMismatch)), | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | impl<'a> TryFrom<&'a LispExpr> for &'a LispNumber { | ||
131 | type Error = LispError; | ||
132 | fn try_from(value: &'a LispExpr) -> Result<Self, Self::Error> { | ||
133 | match value { | ||
134 | LispExpr::Number(i) => Ok(i), | ||
135 | _ => Err(LispError::Eval(EvalError::TypeMismatch)), | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | |||
140 | impl TryFrom<LispExpr> for Ident { | ||
141 | type Error = LispError; | ||
142 | fn try_from(value: LispExpr) -> Result<Self, Self::Error> { | ||
143 | match value { | ||
144 | LispExpr::Ident(i) => Ok(i), | ||
145 | _ => Err(LispError::Eval(EvalError::TypeMismatch)), | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | impl TryFrom<LispExpr> for BoolLit { | ||
151 | type Error = LispError; | ||
152 | fn try_from(value: LispExpr) -> Result<Self, Self::Error> { | ||
153 | match value { | ||
154 | LispExpr::BoolLit(i) => Ok(i), | ||
155 | _ => Err(LispError::Eval(EvalError::TypeMismatch)), | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | pub fn is_ident<E: AsRef<LispExpr>>(expr: E) -> bool { | ||
161 | matches!(expr.as_ref(), LispExpr::Ident(_)) | ||
162 | } | ||
163 | |||
164 | pub fn is_number<E: AsRef<LispExpr>>(expr: E) -> bool { | ||
165 | matches!(expr.as_ref(), LispExpr::Number(_)) | ||
166 | } | ||