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
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::cell::RefCell;
use std::fs::File;
use std::io::{self, BufReader, Seek};
use rustyline::error::ReadlineError;
use rustyline::Editor;
use crate::compiler::Compiler;
use crate::reader::Reader;
use crate::value::RefValue;
use crate::vm::Runtime;
pub enum Stream {
String(String),
File(File),
Stdin,
}
impl Stream {
pub fn get_reader(&mut self) -> Reader {
match self {
Stream::String(string) => Reader::new(Box::new(io::Cursor::new(string.clone()))),
Stream::File(file) => {
let mut file = file.try_clone().expect("File cannot be cloned?");
file.seek(std::io::SeekFrom::Start(0))
.expect("Unable to seek to file's starting position");
Reader::new(Box::new(BufReader::new(file)))
}
Stream::Stdin => Reader::new(Box::new(BufReader::new(io::stdin()))),
}
}
}
pub fn repl(streams: Vec<(&str, RefCell<Stream>)>, debug: bool) {
let mut globals: Vec<RefValue> = Vec::new();
let mut compiler = Compiler::new();
compiler.interactive = true;
compiler.debug = debug;
let mut readline = Editor::<()>::new();
if cfg!(debug_assertions) {
readline.load_history(".tokayhist").ok();
}
loop {
let code = match readline.readline(">>> ") {
Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
Err(err) => {
println!("Error {:?}", err);
break;
}
Ok(code) => code,
};
if code.trim().is_empty() {
continue;
}
readline.add_history_entry(code.as_str());
match code.as_str() {
"#debug" => {
compiler.debug = true;
println!("<<< Debug switched on")
}
"#nodebug" => {
compiler.debug = false;
println!("<<< Debug switched off")
}
_ => {
if let Ok(program) = compiler.compile(Reader::new(Box::new(io::Cursor::new(code))))
{
for (name, stream) in &streams {
let mut reader = stream.borrow_mut().get_reader();
let mut runtime = Runtime::new(&program, &mut reader);
runtime.debug = compiler.debug;
runtime.load_stack(globals);
let ret = program.run(&mut runtime);
if streams.len() > 1 {
print!("{}: ", name);
}
match ret {
Ok(None) => {
if streams.len() > 1 {
print!("\n")
}
}
Ok(Some(value)) => println!("{}", value.borrow()),
Err(error) => println!("{}", error),
}
globals = runtime.save_stack();
}
}
}
}
}
if cfg!(debug_assertions) {
readline.save_history(".tokayhist").unwrap();
}
}