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
use crate::{Symbol, Tag, Value};
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
None,
Value(Value),
Word(Symbol),
List(Vec<Stmt>),
Map(Vec<(Symbol, Stmt)>),
Call(Box<Stmt>, Vec<Stmt>),
Return(Box<Stmt>),
If(Vec<(Stmt, Vec<Stmt>)>),
For(Option<Symbol>, Symbol, Box<Stmt>, Vec<Stmt>),
While(Box<Stmt>, Vec<Stmt>),
Assign(Symbol, Box<Stmt>, bool),
Tag(Tag),
Fn(Vec<Symbol>, Vec<Stmt>),
Args(Vec<(Symbol, Stmt)>),
}
impl From<Tag> for Stmt {
fn from(tag: Tag) -> Stmt {
Stmt::Tag(tag)
}
}
impl From<String> for Stmt {
fn from(s: String) -> Stmt {
Stmt::Value(s.into())
}
}
impl From<&str> for Stmt {
fn from(s: &str) -> Stmt {
Stmt::Value(s.into())
}
}
impl Stmt {
pub fn is_some(&self) -> bool {
!self.is_none()
}
pub fn is_none(&self) -> bool {
matches!(self, Stmt::None)
}
pub fn to_str(&self) -> &str {
match self {
Stmt::Value(Value::String(s)) => s.to_str(),
Stmt::Word(s) => s.to_str(),
_ => "",
}
}
pub fn to_string(&self) -> String {
match self {
Stmt::None => "Stmt::None".to_string(),
Stmt::Value(Value::String(s)) => format!(r#""{}""#, s),
Stmt::Value(v) => format!("{}", v),
Stmt::Word(s) => s.to_string(),
Stmt::Tag(tag) => format!("{:?}", tag),
Stmt::Return(ex) => format!("return {:?}", ex),
Stmt::Args(args) => args
.iter()
.map(|(k, v)| format!("{}: {:?}", k, v))
.collect::<Vec<_>>()
.join(", "),
Stmt::List(list) => format!(
"[{}]",
list.iter()
.map(|ex| ex.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Stmt::Map(map) => format!(
"{{{}}}",
map.iter()
.map(|(k, v)| format!("{}: {}", k.to_string(), v.to_string()))
.collect::<Vec<_>>()
.join(", ")
),
Stmt::Assign(var, expr, re) => {
format!("{} {}= {:?}", var, if *re { ":" } else { "" }, expr)
}
Stmt::If(..) => format!("{}", "IF: Coming Soon™"),
Stmt::For(..) => format!("{}", "FOR: Coming Soon™"),
Stmt::While(test, body) => format!("while({:?}) {:?}", test, body),
Stmt::Fn(args, body) => format!("fn({:?}) {:?}", args, body),
Stmt::Call(name, args) => format!(
"{}({})",
name.to_string(),
args.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", ")
),
}
}
}