aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lisp/expr.rs62
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 @@
1use std::fmt; 1use std::{convert::TryFrom, fmt};
2 2
3use crate::app::AppState; 3use crate::app::AppState;
4use crate::lisp::{error::LispError, number::LispNumber}; 4use crate::lisp::{
5 error::{EvalError, LispError},
6 number::LispNumber,
7};
5 8
6#[derive(Clone)] 9#[derive(Clone)]
7pub struct PrimitiveFunc { 10pub 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
26pub type Ident = String;
27pub type BoolLit = bool;
28
23#[derive(Clone)] 29#[derive(Clone)]
24pub struct LispFunction { 30pub 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
120impl 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
130impl<'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
140impl 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
150impl 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
160pub fn is_ident<E: AsRef<LispExpr>>(expr: E) -> bool {
161 matches!(expr.as_ref(), LispExpr::Ident(_))
162}
163
164pub fn is_number<E: AsRef<LispExpr>>(expr: E) -> bool {
165 matches!(expr.as_ref(), LispExpr::Number(_))
166}