1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::fmt;
4use std::fmt::Formatter;
5use std::hash::{Hash, Hasher};
6use std::rc::Rc;
7
8use parser::ast::{BlockStatement, IDENTIFIER};
9
10#[macro_use]
11extern crate lazy_static;
12
13use crate::environment::Env;
14
15pub mod builtins;
16pub mod environment;
17
18pub type EvalError = String;
19pub type BuiltinFunc = fn(Vec<Rc<Object>>) -> Rc<Object>;
20
21pub type ClassRef = Rc<RefCell<ClassObject>>;
22pub type InstanceRef = Rc<RefCell<InstanceObject>>;
23
24#[derive(Clone)]
25pub enum Object {
26 Integer(i64),
27 Boolean(bool),
28 String(String),
29 Array(Vec<Rc<Object>>),
30 Hash(HashMap<Rc<Object>, Rc<Object>>),
31 Null,
32 ReturnValue(Rc<Object>),
33 Function(Vec<IDENTIFIER>, BlockStatement, Env),
34 Builtin(BuiltinFunc),
35 Error(String),
36 CompiledFunction(Rc<CompiledFunction>),
37 ClosureObj(Closure),
38 Class(ClassRef),
39 Instance(InstanceRef),
40 BoundMethod(Rc<BoundMethodObject>),
41}
42
43#[derive(Clone)]
44pub struct ClassObject {
45 pub name: String,
46 pub constructor: Option<Rc<Object>>,
47 pub methods: HashMap<String, Rc<Object>>,
48}
49
50#[derive(Clone)]
51pub struct InstanceObject {
52 pub class: ClassRef,
53 pub fields: HashMap<String, Rc<Object>>,
54}
55
56#[derive(Clone)]
57pub struct BoundMethodObject {
58 pub receiver: InstanceRef,
59 pub method: Rc<Object>,
60 pub name: String,
61}
62
63impl fmt::Display for Object {
64 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65 match self {
66 Object::Integer(i) => write!(f, "{}", i),
67 Object::Boolean(b) => write!(f, "{}", b),
68 Object::String(s) => write!(f, "{}", s),
69 Object::Null => write!(f, "null"),
70 Object::ReturnValue(expr) => write!(f, "{}", expr),
71 Object::Function(params, body, _env) => {
72 let func_params = params
73 .iter()
74 .map(|stmt| stmt.to_string())
75 .collect::<Vec<String>>()
76 .join(", ");
77 write!(f, "fn({}) {{ {} }}", func_params, body)
78 }
79 Object::Builtin(_) => write!(f, "[builtin function]"),
80 Object::Error(e) => write!(f, "{}", e),
81 Object::Array(e) => write!(
82 f,
83 "[{}]",
84 e.iter()
85 .map(|o| o.to_string())
86 .collect::<Vec<String>>()
87 .join(", ")
88 ),
89 Object::Hash(map) => write!(
90 f,
91 "[{}]",
92 map.iter()
93 .map(|(k, v)| format!("{}: {}", k, v))
94 .collect::<Vec<String>>()
95 .join(", ")
96 ),
97 Object::CompiledFunction(_) => {
98 write!(f, "[compiled function]")
99 }
100 Object::ClosureObj(_) => {
101 write!(f, "[closure function]")
102 }
103 Object::Class(class) => write!(f, "[class {}]", class.borrow().name),
104 Object::Instance(instance) => {
105 write!(f, "[object {}]", instance.borrow().class.borrow().name)
106 }
107 Object::BoundMethod(method) => {
108 let class_name = method.receiver.borrow().class.borrow().name.clone();
109 write!(f, "[bound method {}.{}]", class_name, method.name)
110 }
111 }
112 }
113}
114
115impl fmt::Debug for Object {
116 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
117 match self {
118 Object::Integer(value) => f.debug_tuple("Integer").field(value).finish(),
119 Object::Boolean(value) => f.debug_tuple("Boolean").field(value).finish(),
120 Object::String(value) => f.debug_tuple("String").field(value).finish(),
121 Object::Array(value) => f.debug_tuple("Array").field(value).finish(),
122 Object::Hash(value) => f.debug_tuple("Hash").field(value).finish(),
123 Object::Null => write!(f, "Null"),
124 Object::ReturnValue(value) => f.debug_tuple("ReturnValue").field(value).finish(),
125 Object::Function(params, body, _) => f
126 .debug_struct("Function")
127 .field("params", params)
128 .field("body", body)
129 .finish_non_exhaustive(),
130 Object::Builtin(_) => write!(f, "Builtin([function])"),
131 Object::Error(value) => f.debug_tuple("Error").field(value).finish(),
132 Object::CompiledFunction(value) => {
133 f.debug_tuple("CompiledFunction").field(value).finish()
134 }
135 Object::ClosureObj(value) => f.debug_tuple("ClosureObj").field(value).finish(),
136 Object::Class(_) | Object::Instance(_) | Object::BoundMethod(_) => {
137 write!(f, "{}", self)
138 }
139 }
140 }
141}
142
143impl PartialEq for Object {
144 fn eq(&self, other: &Self) -> bool {
145 match (self, other) {
146 (Object::Integer(left), Object::Integer(right)) => left == right,
147 (Object::Boolean(left), Object::Boolean(right)) => left == right,
148 (Object::String(left), Object::String(right)) => left == right,
149 (Object::Array(left), Object::Array(right)) => left == right,
150 (Object::Hash(left), Object::Hash(right)) => left == right,
151 (Object::Null, Object::Null) => true,
152 (Object::ReturnValue(left), Object::ReturnValue(right)) => left == right,
153 (
154 Object::Function(left_params, left_body, left_env),
155 Object::Function(right_params, right_body, right_env),
156 ) => {
157 left_params == right_params
158 && left_body == right_body
159 && Rc::ptr_eq(left_env, right_env)
160 }
161 (Object::Builtin(left), Object::Builtin(right)) => std::ptr::fn_addr_eq(*left, *right),
162 (Object::Error(left), Object::Error(right)) => left == right,
163 (Object::CompiledFunction(left), Object::CompiledFunction(right)) => left == right,
164 (Object::ClosureObj(left), Object::ClosureObj(right)) => left == right,
165 (Object::Class(left), Object::Class(right)) => Rc::ptr_eq(left, right),
166 (Object::Instance(left), Object::Instance(right)) => Rc::ptr_eq(left, right),
167 (Object::BoundMethod(left), Object::BoundMethod(right)) => Rc::ptr_eq(left, right),
168 _ => false,
169 }
170 }
171}
172
173impl Eq for Object {}
174
175impl Object {
176 pub fn is_hashable(&self) -> bool {
177 match self {
178 Object::Integer(_) | Object::Boolean(_) | Object::String(_) => return true,
179 _ => return false,
180 }
181 }
182}
183
184impl Hash for Object {
185 fn hash<H: Hasher>(&self, state: &mut H) {
186 match self {
187 Object::Integer(i) => i.hash(state),
188 Object::Boolean(b) => b.hash(state),
189 Object::String(s) => s.hash(state),
190 t => panic!("can't hashable for {}", t),
191 }
192 }
193}
194
195#[derive(Debug, Clone, Eq, PartialEq)]
196pub struct CompiledFunction {
197 pub name: String,
198 pub instructions: Vec<u8>,
199 pub num_locals: usize,
200 pub num_parameters: usize,
201}
202
203#[derive(Debug, Clone, Eq, PartialEq)]
204pub struct Closure {
205 pub func: Rc<CompiledFunction>,
206 pub free: Vec<Rc<Object>>,
207}