1mod address;
3mod address_cache;
5mod built_ins;
7mod evaluate;
9mod instruction;
11mod location;
13mod ram_value;
15mod stack_value;
17mod stringify;
19
20pub(crate) use address_cache::*;
21pub(crate) use instruction::*;
22pub(crate) use ram_value::*;
23pub use stack_value::*;
24
25pub use address::*;
26pub use built_ins::*;
27pub use location::*;
28
29use std::{collections::HashMap, io::Write, path::PathBuf};
30
31pub type Err = (String, Location);
33pub type Number = f32;
35
36#[derive(Debug, PartialEq, Clone)]
38pub enum Value {
39 Number(Number),
40 String(String),
41}
42
43#[derive(Debug, Copy, Clone, PartialEq)]
46pub(crate) enum ReadMode {
47 On,
48 Off,
49 SingleWord,
50}
51
52pub struct Interpreter<State> {
55 #[allow(unused)]
58 pub state: State,
59 address_cache: AddressCache,
61 break_loop: bool,
63 program_counter: usize,
65 program: Vec<Instruction>,
67 program_counter_stack: Vec<usize>,
69 compiling: bool,
71 program_debug_locations: Vec<Location>,
73 exit: bool,
75 read_mode: ReadMode,
77 repl_mode: bool,
79 next_address: Address,
81 ram: HashMap<Address, RamValue<State>>,
83 stack: Vec<StackValue>,
85 documentation_table: HashMap<Address, String>,
87 name_table: HashMap<String, Address>,
89}
90
91impl<State> Interpreter<State> {
92 pub fn new(state: State) -> Self {
95 let mut interpreter = Self {
96 state,
97 compiling: false,
98 break_loop: false,
99 address_cache: AddressCache::uninitalized(),
100 program_counter: 0,
101 program: vec![],
102 program_counter_stack: vec![],
103 program_debug_locations: vec![],
104 exit: false,
105 read_mode: ReadMode::Off,
106 repl_mode: false,
107 ram: HashMap::new(),
108 stack: vec![],
109 next_address: Address::default(),
110 documentation_table: HashMap::new(),
111 name_table: HashMap::new(),
112 };
113
114 interpreter.register_builtins();
115
116 AddressCache::initialize(&mut interpreter);
117
118 interpreter
119 }
120
121 pub fn exit(&self) -> bool {
123 self.exit
124 }
125
126 pub fn evaluate(&mut self, code: &str, path: Option<PathBuf>) -> Result<(), Err> {
128 self.load_program(code, path)?;
129 self.execute()?;
130 Ok(())
131 }
132
133 pub fn get_name(&self, address: Address) -> String {
135 for (name, addr) in &self.name_table {
137 if *addr == address {
138 return name.clone();
139 }
140 }
141
142 for (k, value) in &self.ram {
144 if let Some(addr) = value.address() {
145 if addr == address {
146 return format!("@{}", self.get_name(*k));
147 }
148 }
149 }
150
151 format!("@UNKNOWN-{:?}", address)
153 }
154
155 pub fn pop(&mut self) -> Result<StackValue, Err> {
157 self.stack
158 .pop()
159 .ok_or(("Stack is empty".to_string(), self.location()))
160 }
161
162 pub fn pop_bool(&mut self) -> Result<bool, Err> {
164 match self.pop()? {
165 StackValue::Value(Value::Number(number)) => Ok(number != 0.0),
166 _ => Err(("Expected a boolean/number".to_string(), self.location())),
167 }
168 }
169
170 pub fn pop_number(&mut self) -> Result<f32, Err> {
172 match self.pop()? {
173 StackValue::Value(Value::Number(number)) => Ok(number),
174 _ => Err(("Expected a number".to_string(), self.location())),
175 }
176 }
177
178 pub fn push_number(&mut self, number: f32) {
180 self.stack.push(StackValue::Value(Value::Number(number)));
181 }
182
183 pub fn push_address(&mut self, address: Address) {
185 self.stack.push(StackValue::Address(address));
186 }
187
188 pub fn pop_address(&mut self) -> Result<Address, Err> {
190 match self.pop()? {
191 StackValue::Address(address) => Ok(address),
192 _ => Err(("Expected an address".to_string(), self.location())),
193 }
194 }
195
196 pub fn push_string(&mut self, string: String) {
198 self.stack.push(StackValue::Value(Value::String(string)));
199 }
200
201 pub fn pop_string(&mut self) -> Result<String, Err> {
203 match self.pop()? {
204 StackValue::Value(Value::String(string)) => Ok(string),
205 _ => Err(("Expected a string".to_string(), self.location())),
206 }
207 }
208
209 pub fn start_repl(&mut self) -> Result<(), Err> {
211 self.repl_mode = true;
212 println!("Use 'repl-exit' to exit REPL mode.");
213
214 while !self.exit && self.repl_mode {
215 let mut input = String::new();
217 print!("> ");
218 std::io::stdout().flush().unwrap();
219 std::io::stdin().read_line(&mut input).unwrap();
220
221 let input = format!("{} print-stack", input.trim());
222
223 match self.evaluate(&input, None) {
225 Ok(_) => (),
226 Err((e, location)) => println!("{}: {}", location, e),
227 }
228 }
229 Ok(())
230 }
231
232 pub fn register_builtin(
234 &mut self,
235 name: &str,
236 stack_modification: &str,
237 documentation: &str,
238 example: &str,
239 func: BuiltIn<State>,
240 ) {
241 let address = self.get_address(name);
242 self.register_documentation(address, stack_modification, documentation, example);
243 self.ram.insert(address, RamValue::BuiltIn(func));
244 }
245
246 pub(crate) fn register_documentation(
248 &mut self,
249 address: Address,
250 stack_modification: &str,
251 documentation: &str,
252 example: &str,
253 ) {
254 let stack_modification = if stack_modification.is_empty() {
255 "".to_string()
256 } else {
257 format!("\t( {} )", stack_modification.replace("...", "..").trim())
258 };
259
260 let example = if example.is_empty() {
261 "".to_string()
262 } else {
263 format!("\n\tExample '{}'", example)
264 };
265 let documentation = documentation.trim();
266 let documentation = format!("{stack_modification}\n\t{}{}", documentation, example);
267
268 self.documentation_table.insert(address, documentation);
269 }
270
271 pub fn print_documentation(&self) {
273 println!("Documentation:");
274 let mut names = self.name_table.keys().cloned().collect::<Vec<_>>();
275 names.sort();
276 for name in names {
277 let address = self.name_table[&name];
278 if let Some(documentation) = self.documentation_table.get(&address) {
279 println!("{} {}\n", name, documentation);
280 }
281 }
282 println!();
283 }
284
285 pub(crate) fn get_address(&mut self, name: &str) -> Address {
287 if let Some(address) = self.name_table.get(name) {
288 address.clone()
289 } else {
290 let address = self.next_address;
291 self.next_address = self.next_address.next();
292 self.name_table.insert(name.to_string(), address);
293 address
294 }
295 }
296
297 pub(crate) fn chomp_instruction(&mut self) -> Result<Instruction, Err> {
299 if self.program_counter >= self.program.len() {
300 return Err(("No more instructions".to_string(), self.location()));
301 }
302
303 let instruction = self.program[self.program_counter].clone();
304 self.program_counter += 1;
305 Ok(instruction)
306 }
307
308 pub fn location(&self) -> Location {
310 if self.program_debug_locations.is_empty()
311 || self.program_counter >= self.program_debug_locations.len()
312 {
313 return Location::default();
314 }
315 self.program_debug_locations[self.program_counter].clone()
316 }
317}
318
319#[cfg(test)]
320mod tests {
321 use super::*;
322
323 #[test]
324 fn test_get_address() {
325 let mut interpreter = Interpreter::new(());
326 let expected = interpreter.next_address;
327 let actual = interpreter.get_address("test");
328 assert_eq!(expected, actual);
329 }
330
331 #[test]
332 fn pop_returns_err_if_stack_is_empty() {
333 let mut interpreter = Interpreter::new(());
334 let err = interpreter.pop().unwrap_err();
335 assert_eq!(err, ("Stack is empty".to_string(), Location::default()));
336 }
337
338 #[test]
339 fn pop_number_returns_err_if_not_number() {
340 let mut interpreter = Interpreter::new(());
341 interpreter.push_address(Address::default());
342 let err = interpreter.pop_number().unwrap_err();
343 assert_eq!(err, ("Expected a number".to_string(), Location::default()));
344 }
345
346 #[test]
347 fn pop_bool_returns_err_if_not_bool() {
348 let mut interpreter = Interpreter::new(());
349 interpreter.push_string("hello".to_string());
350 let err = interpreter.pop_bool().unwrap_err();
351 assert_eq!(
352 err,
353 ("Expected a boolean/number".to_string(), Location::default())
354 );
355 }
356
357 #[test]
358 fn pop_bool_returns_true() {
359 let mut interpreter = Interpreter::new(());
360 interpreter.push_number(0.1);
361 let value = interpreter.pop_bool().unwrap();
362 assert_eq!(value, true);
363 }
364
365 #[test]
366 fn pop_bool_returns_false() {
367 let mut interpreter = Interpreter::new(());
368 interpreter.push_number(0.0);
369 let value = interpreter.pop_bool().unwrap();
370 assert_eq!(value, false);
371 }
372
373 #[test]
374 fn pop_number_returns_value() {
375 let mut interpreter = Interpreter::new(());
376 interpreter.evaluate("1", None).unwrap();
377 let value = interpreter.pop_number().unwrap();
378 assert_eq!(value, 1.0);
379 }
380
381 #[test]
382 fn pop_string_returns_err_if_not_string() {
383 let mut interpreter = Interpreter::new(());
384 interpreter.evaluate("1", None).unwrap();
385 let err = interpreter.pop_string().unwrap_err();
386 assert_eq!(err, ("Expected a string".to_string(), Location::default()));
387 }
388
389 #[test]
390 fn pop_string_returns_value() {
391 let mut interpreter = Interpreter::new(());
392 interpreter.push_string("hello".to_string());
393 let value = interpreter.pop_string().unwrap();
394 assert_eq!(value, "hello");
395 }
396
397 #[test]
398 fn pop_address_returns_err_if_not_address() {
399 let mut interpreter = Interpreter::new(());
400 interpreter.evaluate("1", None).unwrap();
401
402 let err = interpreter.pop_address().unwrap_err();
403 assert_eq!(
404 err,
405 ("Expected an address".to_string(), Location::default())
406 );
407 }
408
409 #[test]
410 fn pop_address_returns_value() {
411 let mut interpreter = Interpreter::new(());
412 let address = interpreter.next_address;
413 interpreter.push_address(address.clone());
414 let value = interpreter.pop_address().unwrap();
415 assert_eq!(value, address);
416 }
417
418 #[test]
419 fn parse_string_returns_err_if_not_closed() {
420 let code = r#""hello"#;
421 let mut interpreter = Interpreter::new(());
422 let result = interpreter.evaluate(code, None);
423 assert!(result.is_err());
424 assert_eq!(result.unwrap_err().0, "Unclosed string");
425 }
426
427 #[test]
428 fn parse_string_puts_string_on_stack() {
429 let code = r#""hello""#;
430
431 let mut interpreter = Interpreter::new(());
432 interpreter.evaluate(code, None).unwrap();
433 let value = interpreter.pop_string().unwrap();
434 assert_eq!(value, "hello");
435 }
436
437 #[test]
438 fn var_only_creates_if_not_already_in_ram() {
439 let mut interpreter = Interpreter::new(());
440 let address = interpreter.next_address;
441 interpreter.evaluate("var test", None).unwrap();
442
443 let first_call = interpreter.ram.get(&address).unwrap().clone();
444
445 interpreter.evaluate("var test", None).unwrap();
446
447 let second_call = interpreter.ram.get(&address).unwrap().clone();
448 assert_eq!(first_call, second_call);
449 }
450
451 }