diff options
Diffstat (limited to 'src/lisp/expr.rs')
-rw-r--r-- | src/lisp/expr.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs new file mode 100644 index 0000000..94e778f --- /dev/null +++ b/src/lisp/expr.rs | |||
@@ -0,0 +1,87 @@ | |||
1 | use std::fmt; | ||
2 | |||
3 | use crate::lisp::number::LispNumber; | ||
4 | |||
5 | #[derive(Debug, PartialEq, Clone)] | ||
6 | pub enum LispExpr { | ||
7 | Number(LispNumber), | ||
8 | List(Vec<LispExpr>), | ||
9 | StringLit(String), | ||
10 | BoolLit(bool), | ||
11 | Ident(String), | ||
12 | Function(LispFunction), | ||
13 | |||
14 | // none of these depths should be zero | ||
15 | Quasiquote(Box<LispExpr>, u32), | ||
16 | Comma(Box<LispExpr>, u32), | ||
17 | CommaAt(Box<LispExpr>, u32), | ||
18 | Quote(Box<LispExpr>, u32), | ||
19 | } | ||
20 | |||
21 | impl LispExpr { | ||
22 | pub fn comma(self, n: u32) -> LispExpr { | ||
23 | match self { | ||
24 | LispExpr::Comma(v, i) => LispExpr::Comma(v, i.checked_add(n).expect("comma overflow")), | ||
25 | LispExpr::CommaAt(v, i) => LispExpr::CommaAt(v, i + n), | ||
26 | v => LispExpr::Comma(Box::new(v), n), | ||
27 | } | ||
28 | } | ||
29 | |||
30 | pub fn comma_at(self, n: u32) -> LispExpr { | ||
31 | match self { | ||
32 | LispExpr::CommaAt(v, i) => { | ||
33 | LispExpr::CommaAt(v, i.checked_add(n).expect("comma_at overflow")) | ||
34 | } | ||
35 | v => LispExpr::CommaAt(Box::new(v), n), | ||
36 | } | ||
37 | } | ||
38 | |||
39 | pub fn quote(self, n: u32) -> LispExpr { | ||
40 | match self { | ||
41 | LispExpr::Quote(v, i) => LispExpr::Quote(v, i.checked_add(n).expect("quote overflow")), | ||
42 | v => LispExpr::Quote(Box::new(v), n), | ||
43 | } | ||
44 | } | ||
45 | |||
46 | pub fn quasiquote(self, n: u32) -> LispExpr { | ||
47 | match self { | ||
48 | LispExpr::Quasiquote(v, i) => { | ||
49 | LispExpr::Quasiquote(v, i.checked_add(n).expect("quasiquote overflow")) | ||
50 | } | ||
51 | v => LispExpr::Quasiquote(Box::new(v), n), | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | impl fmt::Display for LispExpr { | ||
57 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
58 | match self { | ||
59 | LispExpr::Number(n) => write!(f, "{}", n)?, | ||
60 | LispExpr::List(l) => { | ||
61 | for expr in l.iter() { | ||
62 | write!(f, " {} ", expr)? | ||
63 | } | ||
64 | } | ||
65 | LispExpr::StringLit(s) => write!(f, "{:?}", s)?, | ||
66 | LispExpr::BoolLit(b) => { | ||
67 | if *b { | ||
68 | write!(f, "#t")? | ||
69 | } else { | ||
70 | write!(f, "#f")? | ||
71 | } | ||
72 | } | ||
73 | LispExpr::Ident(s) => write!(f, "{}", s)?, | ||
74 | LispExpr::Function(_) => write!(f, "<#procedure>")?, | ||
75 | LispExpr::Quasiquote(val, depth) => { | ||
76 | write!(f, "{}{}", "`".repeat(*depth as usize), val)? | ||
77 | } | ||
78 | LispExpr::Comma(val, depth) => write!(f, "{}{}", ",".repeat(*depth as usize), val)?, | ||
79 | LispExpr::CommaAt(val, depth) => write!(f, "{}@{}", ",".repeat(*depth as usize), val)?, | ||
80 | LispExpr::Quote(val, depth) => write!(f, "{}{}", "'".repeat(*depth as usize), val)?, | ||
81 | }; | ||
82 | Ok(()) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #[derive(Debug, PartialEq, Clone)] | ||
87 | struct LispFunction {} | ||