diff options
-rw-r--r-- | src/lisp/expr.rs | 87 | ||||
-rw-r--r-- | src/lisp/mod.rs | 43 |
2 files changed, 90 insertions, 40 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 {} | ||
diff --git a/src/lisp/mod.rs b/src/lisp/mod.rs index 5d8965f..b863bba 100644 --- a/src/lisp/mod.rs +++ b/src/lisp/mod.rs | |||
@@ -1,46 +1,9 @@ | |||
1 | use std::fmt; | ||
2 | |||
3 | use number::LispNumber; | ||
4 | |||
5 | mod error; | 1 | mod error; |
2 | mod expr; | ||
6 | mod lex; | 3 | mod lex; |
7 | mod number; | 4 | mod number; |
5 | mod parse; | ||
8 | 6 | ||
9 | #[derive(Debug, PartialEq)] | 7 | use expr::LispExpr; |
10 | pub enum LispExpr { | ||
11 | Number(LispNumber), | ||
12 | List(Vec<LispExpr>), | ||
13 | StringLit(String), | ||
14 | BoolLit(bool), | ||
15 | Ident(String), | ||
16 | Function(LispFunction), | ||
17 | } | ||
18 | |||
19 | impl fmt::Display for LispExpr { | ||
20 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
21 | match self { | ||
22 | LispExpr::Number(n) => write!(f, "{}", n)?, | ||
23 | LispExpr::List(l) => { | ||
24 | for expr in l.iter() { | ||
25 | write!(f, " {} ", expr)? | ||
26 | } | ||
27 | } | ||
28 | LispExpr::StringLit(s) => write!(f, "{:?}", s)?, | ||
29 | LispExpr::BoolLit(b) => { | ||
30 | if *b { | ||
31 | write!(f, "#t")? | ||
32 | } else { | ||
33 | write!(f, "#f")? | ||
34 | } | ||
35 | } | ||
36 | LispExpr::Ident(s) => write!(f, "{}", s)?, | ||
37 | LispExpr::Function(_) => write!(f, "<#procedure>")?, | ||
38 | }; | ||
39 | Ok(()) | ||
40 | } | ||
41 | } | ||
42 | 8 | ||
43 | pub type Environment = Vec<(String, LispExpr)>; | 9 | pub type Environment = Vec<(String, LispExpr)>; |
44 | |||
45 | #[derive(Debug, PartialEq)] | ||
46 | struct LispFunction {} | ||