1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
use std::fmt;
use crate::app::AppState;
use crate::lisp::{error::LispError, number::LispNumber};
#[derive(Clone)]
pub enum LispExpr {
Unit,
Number(LispNumber),
List(Vec<LispExpr>),
StringLit(String),
BoolLit(bool),
Ident(String),
PrimitiveFunc(PrimitiveFunc),
Function(LispFunction),
// none of these depths should be zero
Quasiquote(Box<LispExpr>, u32),
Comma(Box<LispExpr>, u32),
CommaAt(Box<LispExpr>, u32),
Quote(Box<LispExpr>, u32),
}
#[derive(Clone)]
pub struct PrimitiveFunc {
pub arity: Option<usize>,
pub closure: fn(&[LispExpr], &mut AppState) -> Result<LispExpr, LispError>,
}
impl PrimitiveFunc {
pub fn call(&self, args: &[LispExpr], app: &mut AppState) -> Result<LispExpr, LispError> {
if let Some(arity) = self.arity {
if args.len() < arity {
return Err(LispError::EvalError);
}
}
(self.closure)(args, app)
}
}
impl LispExpr {
pub fn comma(self, n: u32) -> LispExpr {
match self {
LispExpr::Comma(v, i) => LispExpr::Comma(v, i.checked_add(n).expect("comma overflow")),
LispExpr::CommaAt(v, i) => LispExpr::CommaAt(v, i + n),
v => LispExpr::Comma(Box::new(v), n),
}
}
pub fn comma_at(self, n: u32) -> LispExpr {
match self {
LispExpr::CommaAt(v, i) => {
LispExpr::CommaAt(v, i.checked_add(n).expect("comma_at overflow"))
}
v => LispExpr::CommaAt(Box::new(v), n),
}
}
pub fn quote(self, n: u32) -> LispExpr {
match self {
LispExpr::Quote(v, i) => LispExpr::Quote(v, i.checked_add(n).expect("quote overflow")),
v => LispExpr::Quote(Box::new(v), n),
}
}
pub fn quasiquote(self, n: u32) -> LispExpr {
match self {
LispExpr::Quasiquote(v, i) => {
LispExpr::Quasiquote(v, i.checked_add(n).expect("quasiquote overflow"))
}
v => LispExpr::Quasiquote(Box::new(v), n),
}
}
}
impl fmt::Display for LispExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LispExpr::Unit => write!(f, "()")?,
LispExpr::Number(n) => write!(f, "{}", n)?,
LispExpr::List(l) => {
for expr in l.iter() {
write!(f, " {} ", expr)?
}
}
LispExpr::StringLit(s) => write!(f, "{:?}", s)?,
LispExpr::BoolLit(b) => {
if *b {
write!(f, "#t")?
} else {
write!(f, "#f")?
}
}
LispExpr::Ident(s) => write!(f, "{}", s)?,
LispExpr::PrimitiveFunc(_) => write!(f, "<#primitive>")?,
LispExpr::Function(_) => write!(f, "<#procedure>")?,
LispExpr::Quasiquote(val, depth) => {
write!(f, "{}{}", "`".repeat(*depth as usize), val)?
}
LispExpr::Comma(val, depth) => write!(f, "{}{}", ",".repeat(*depth as usize), val)?,
LispExpr::CommaAt(val, depth) => write!(f, "{}@{}", ",".repeat(*depth as usize), val)?,
LispExpr::Quote(val, depth) => write!(f, "{}{}", "'".repeat(*depth as usize), val)?,
};
Ok(())
}
}
#[derive(Debug, PartialEq, Clone)]
enum LispFunction {}
|