1use crate::ast;
5
6use std::collections::HashMap;
7use std::error;
8use std::fmt;
9use std::result;
10
11#[derive(Clone, Debug, PartialEq)]
14pub enum Object {
15 Null,
16 Integer(i64),
17 Float(f64),
18 Boolean(bool),
19 String(String),
20 ReturnValue(Box<Object>),
21 Function(Function),
22 Builtin(Builtin),
23 Array(Array),
24 Hash(Hash),
25}
26
27impl fmt::Display for Object {
28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 match self {
30 Object::Null => write!(f, "null"),
31 Object::Integer(i) => i.fmt(f),
32 Object::Float(fl) => fl.fmt(f),
33 Object::Boolean(b) => b.fmt(f),
34 Object::String(s) => s.fmt(f),
35 Object::ReturnValue(r) => write!(f, "return({})", r),
36 Object::Function(func) => func.fmt(f),
37 Object::Builtin(b) => b.fmt(f),
38 Object::Array(a) => a.fmt(f),
39 Object::Hash(h) => h.fmt(f),
40 }
41 }
42}
43
44#[derive(Clone, Debug, Default, PartialEq)]
46pub struct Environment {
47 store: HashMap<String, Object>,
48 outer: Option<Box<Environment>>,
49}
50
51impl Environment {
52 pub fn new() -> Self {
54 Environment {
55 store: HashMap::new(),
56 outer: None,
57 }
58 }
59
60 pub fn new_enclosed(outer: Self) -> Self {
62 let mut env = Self::new();
63 env.outer = Some(Box::new(outer));
64 env
65 }
66
67 pub fn get(&self, name: &str) -> Option<&Object> {
70 match (self.store.get(name), &self.outer) {
71 (Some(obj), _) => Some(obj),
74 (None, Some(outer)) => outer.get(name),
76 (None, _) => None,
78 }
79 }
80
81 pub fn set(&mut self, name: String, obj: &Object) -> Object {
83 self.store.insert(name, obj.clone());
84 obj.clone()
85 }
86}
87
88#[derive(Clone, Debug, PartialEq)]
90pub struct Function {
91 pub parameters: Vec<String>,
92 pub body: ast::BlockStatement,
93 pub env: Environment,
94}
95
96impl fmt::Display for Function {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 let params = self.parameters.join(", ");
99
100 write!(f, "fn({}) {{\n{}\n}}", params, self.body)
101 }
102}
103
104#[derive(Clone, Debug, PartialEq)]
106pub enum Builtin {
107 First,
108 Last,
109 Len,
110 Push,
111 Puts,
112 Rest,
113}
114
115impl Builtin {
116 pub fn lookup(name: &str) -> Option<Self> {
118 match name {
119 "first" => Some(Builtin::First),
120 "last" => Some(Builtin::Last),
121 "len" => Some(Builtin::Len),
122 "push" => Some(Builtin::Push),
123 "puts" => Some(Builtin::Puts),
124 "rest" => Some(Builtin::Rest),
125
126 _ => None,
127 }
128 }
129
130 pub fn apply(&self, args: &[Object]) -> Result<Object> {
133 match self {
134 Builtin::First => builtin_first(&args),
135 Builtin::Last => builtin_last(&args),
136 Builtin::Len => builtin_len(&args),
137 Builtin::Push => builtin_push(&args),
138 Builtin::Puts => builtin_puts(&args),
139 Builtin::Rest => builtin_rest(&args),
140 }
141 }
142}
143
144impl fmt::Display for Builtin {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 match self {
147 Builtin::First => write!(f, "first"),
148 Builtin::Last => write!(f, "last"),
149 Builtin::Len => write!(f, "len"),
150 Builtin::Push => write!(f, "push"),
151 Builtin::Puts => write!(f, "puts"),
152 Builtin::Rest => write!(f, "rest"),
153 }
154 }
155}
156
157fn builtin_first(args: &[Object]) -> Result<Object> {
158 if args.len() != 1 {
159 return Err(Error::Builtin(
160 Builtin::First,
161 format!("expected 1 argument, but got {}", args.len()),
162 ));
163 }
164
165 if let Object::Array(a) = &args[0] {
166 if !a.elements.is_empty() {
167 Ok(a.elements.first().unwrap().clone())
168 } else {
169 Ok(Object::Null)
170 }
171 } else {
172 Err(Error::Builtin(
173 Builtin::First,
174 format!("argument {} is not an array", &args[0]),
175 ))
176 }
177}
178
179fn builtin_last(args: &[Object]) -> Result<Object> {
180 if args.len() != 1 {
181 return Err(Error::Builtin(
182 Builtin::Last,
183 format!("expected 1 argument, but got {}", args.len()),
184 ));
185 }
186
187 if let Object::Array(a) = &args[0] {
188 if !a.elements.is_empty() {
189 Ok(a.elements.last().unwrap().clone())
190 } else {
191 Ok(Object::Null)
192 }
193 } else {
194 Err(Error::Builtin(
195 Builtin::Last,
196 format!("argument {} is not an array", &args[0]),
197 ))
198 }
199}
200
201fn builtin_len(args: &[Object]) -> Result<Object> {
202 if args.len() != 1 {
203 return Err(Error::Builtin(
204 Builtin::Len,
205 format!("expected 1 argument, but got {}", args.len()),
206 ));
207 }
208
209 match &args[0] {
210 Object::Array(a) => Ok(Object::Integer(a.elements.len() as i64)),
211 Object::String(s) => Ok(Object::Integer(s.len() as i64)),
212 _ => Err(Error::Builtin(
213 Builtin::Len,
214 format!("argument {} cannot be used", &args[0]),
215 )),
216 }
217}
218
219fn builtin_push(args: &[Object]) -> Result<Object> {
220 if args.len() != 2 {
221 return Err(Error::Builtin(
222 Builtin::Push,
223 format!("expected 2 argument, but got {}", args.len()),
224 ));
225 }
226
227 let arr = if let Object::Array(a) = &args[0] {
228 a
229 } else {
230 return Err(Error::Builtin(
231 Builtin::Push,
232 format!("first argument {} is not an array", &args[0]),
233 ));
234 };
235
236 let mut out = arr.elements.clone();
237 out.push(args[1].clone());
238
239 Ok(Object::Array(Array { elements: out }))
240}
241
242fn builtin_puts(args: &[Object]) -> Result<Object> {
243 for a in args {
244 println!("{}", a);
245 }
246 Ok(Object::Null)
247}
248
249fn builtin_rest(args: &[Object]) -> Result<Object> {
250 if args.len() != 1 {
251 return Err(Error::Builtin(
252 Builtin::Rest,
253 format!("expected 1 argument, but got {}", args.len()),
254 ));
255 }
256
257 if let Object::Array(a) = &args[0] {
258 if !a.elements.is_empty() {
259 Ok(Object::Array(Array {
260 elements: a.elements.iter().skip(1).cloned().collect(),
261 }))
262 } else {
263 Ok(Object::Null)
264 }
265 } else {
266 Err(Error::Builtin(
267 Builtin::Rest,
268 format!("argument {} is not an array", &args[0]),
269 ))
270 }
271}
272
273#[derive(Clone, Debug, PartialEq)]
275pub struct Array {
276 pub elements: Vec<Object>,
277}
278
279impl fmt::Display for Array {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 write!(
282 f,
283 "[{}]",
284 self.elements
285 .iter()
286 .map(|e| format!("{}", e))
287 .collect::<Vec<String>>()
288 .join(", ")
289 )
290 }
291}
292
293#[derive(Clone, Debug, Eq, Hash, PartialEq)]
295pub enum Hashable {
296 Integer(i64),
297 Boolean(bool),
298 String(String),
299}
300
301impl fmt::Display for Hashable {
302 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
303 match self {
304 Hashable::Integer(i) => i.fmt(f),
305 Hashable::Boolean(b) => b.fmt(f),
306 Hashable::String(s) => s.fmt(f),
307 }
308 }
309}
310
311#[derive(Clone, Debug, PartialEq)]
313pub struct Hash {
314 pub pairs: HashMap<Hashable, Object>,
315}
316
317impl fmt::Display for Hash {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319 let mut pairs = vec![];
320 for pair in &self.pairs {
321 pairs.push(format!(r#"{}: {}"#, pair.0, pair.1));
322 }
323
324 pairs.sort();
326 write!(f, "{{{}}}", pairs.join(", "))
327 }
328}
329
330pub type Result<T> = result::Result<T, Error>;
332
333#[derive(Debug, PartialEq)]
335pub enum Error {
336 Builtin(Builtin, String),
337}
338
339impl fmt::Display for Error {
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 match self {
342 Error::Builtin(b, err) => write!(f, "built-in {}: {}", b, err),
343 }
344 }
345}
346
347impl error::Error for Error {
348 fn cause(&self) -> Option<&dyn error::Error> {
349 None
350 }
351}