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
use std::collections::HashMap; use std::fmt; use std::fmt::Formatter; use std::hash::{Hash, Hasher}; use std::rc::Rc; use parser::ast::{BlockStatement, IDENTIFIER}; use crate::environment::Env; pub mod environment; pub type EvalError = String; pub type BuiltinFunc = fn(Vec<Rc<Object>>) -> Rc<Object>; #[derive(Debug, Clone, PartialEq)] pub enum Object { Integer(i64), Boolean(bool), String(String), Array(Vec<Rc<Object>>), Hash(HashMap<Rc<Object>, Rc<Object>>), Null, ReturnValue(Rc<Object>), Function(Vec<IDENTIFIER>, BlockStatement, Env), Builtin(BuiltinFunc), Error(String), } impl fmt::Display for Object { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Object::Integer(i) => write!(f, "{}", i), Object::Boolean(b) => write!(f, "{}", b), Object::String(s) => write!(f, "{}", s), Object::Null => write!(f, "null"), Object::ReturnValue(expr) => write!(f, "{}", expr), Object::Function(params, body, _env) => { let func_params = params .iter() .map(|stmt| stmt.to_string()) .collect::<Vec<String>>() .join(", "); write!(f, "fn({}) {{ {} }}", func_params, body) }, Object::Builtin(_) => write!(f, "[builtin function]"), Object::Error(e) => write!(f, "{}", e), Object::Array(e) => write!(f, "[{}]", e.iter().map(|o|o.to_string()).collect::<Vec<String>>().join(", ")), Object::Hash(map) => write!(f, "[{}]", map .iter() .map(|(k, v)| format!("{}: {}", k, v)) .collect::<Vec<String>>() .join(", ") ) } } } impl Object { pub fn is_hashable(&self) -> bool { match self { Object::Integer(_) | Object::Boolean(_) | Object::String(_) => return true, _ => return false, } } } impl Eq for Object {} impl Hash for Object { fn hash<H: Hasher>(&self, state: &mut H) { match self { Object::Integer(i) => i.hash(state), Object::Boolean(b) => b.hash(state), Object::String(s) => s.hash(state), t => panic!(format!("can't hashable for {}" ,t)) } } }