1use crate::*;
2use std::rc::Rc;
3use std::collections::HashMap;
4use std::panic::{catch_unwind, AssertUnwindSafe};
5use std::io::{Cursor, Read, Write};
6use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
7
8pub struct Interpreter {
12 pub id: u64,
13 ip: usize, pub state: Ref<ProgramState>,
15 registers: Vec<Value>,
16 constants: Vec<Value>,
17 #[cfg(feature = "compiler")]
18 pub context: Option<CompileCtx>,
19 pub code: Vec<MechSourceCode>,
20 pub out: Value,
21 pub out_values: Ref<HashMap<u64, Value>>,
22 pub sub_interpreters: Ref<HashMap<u64, Box<Interpreter>>>,
23}
24
25impl Interpreter {
26 pub fn new(id: u64) -> Self {
27 let mut state = ProgramState::new();
28 load_stdkinds(&mut state.kinds);
29 #[cfg(feature = "functions")]
30 load_stdlib(&mut state.functions.borrow_mut());
31 Self {
32 id,
33 ip: 0,
34 state: Ref::new(state),
35 registers: Vec::new(),
36 constants: Vec::new(),
37 out: Value::Empty,
38 sub_interpreters: Ref::new(HashMap::new()),
39 out_values: Ref::new(HashMap::new()),
40 code: Vec::new(),
41 #[cfg(feature = "compiler")]
42 context: None,
43 }
44 }
45
46 pub fn clear(&mut self) {
47 let id = self.id;
48 *self = Interpreter::new(id);
49 }
50
51 #[cfg(feature = "pretty_print")]
52 pub fn pretty_print_symbols(&self) -> String {
53 let state_brrw = self.state.borrow();
54 let syms = state_brrw.symbol_table.borrow();
55 syms.pretty_print()
56 }
57
58 #[cfg(feature = "functions")]
59 pub fn plan(&self) -> Plan {
60 self.state.borrow().plan.clone()
61 }
62
63 #[cfg(feature = "symbol_table")]
64 pub fn symbols(&self) -> SymbolTableRef {
65 self.state.borrow().symbol_table.clone()
66 }
67
68 pub fn dictionary(&self) -> Ref<Dictionary> {
69 self.state.borrow().dictionary.clone()
70 }
71
72 #[cfg(feature = "functions")]
73 pub fn functions(&self) -> FunctionsRef {
74 self.state.borrow().functions.clone()
75 }
76
77 #[cfg(feature = "functions")]
78 pub fn set_functions(&mut self, functions: FunctionsRef) {
79 self.state.borrow_mut().functions = functions;
80 }
81
82 #[cfg(feature = "functions")]
83 pub fn step(&mut self, step_id: usize, step_count: u64) -> MResult<Value> {
84 let state_brrw = self.state.borrow();
85 let mut plan_brrw = state_brrw.plan.borrow_mut(); if plan_brrw.is_empty() {
88 return Err(MechError2::new(
89 NoStepsInPlanError,
90 None
91 ).with_compiler_loc()
92 );
93 }
94
95 let len = plan_brrw.len();
96
97 if step_id == 0 {
99 for _ in 0..step_count {
100 for fxn in plan_brrw.iter_mut() {
101 fxn.solve();
102 }
103 }
104 return Ok(plan_brrw[len - 1].out().clone());
105 }
106
107 let idx = step_id as usize;
109 if idx > len {
110 return Err(MechError2::new(
111 StepIndexOutOfBoundsError {
112 step_id,
113 plan_length: len,
114 },
115 None
116 ).with_compiler_loc());
117 }
118
119 let fxn = &mut plan_brrw[idx - 1];
120
121 let fxn_str = fxn.to_string();
122 if fxn_str.lines().count() > 30 {
123 let lines: Vec<&str> = fxn_str.lines().collect();
124 println!("Stepping function:");
125 for line in &lines[0..10] {
126 println!("{}", line);
127 }
128 println!("...");
129 for line in &lines[lines.len() - 10..] {
130 println!("{}", line);
131 }
132 } else {
133 println!("Stepping function:\n{}", fxn_str);
134 }
135
136 for _ in 0..step_count {
137 fxn.solve();
138 }
139
140 Ok(fxn.out().clone())
141 }
142
143
144
145 #[cfg(feature = "functions")]
146 pub fn interpret(&mut self, tree: &Program) -> MResult<Value> {
147 self.code.push(MechSourceCode::Tree(tree.clone()));
148 catch_unwind(AssertUnwindSafe(|| {
149 let result = program(tree, &self);
150 if let Some(last_step) = self.state.borrow().plan.borrow().last() {
151 self.out = last_step.out().clone();
152 } else {
153 self.out = Value::Empty;
154 }
155 result
156 }))
157 .map_err(|err| {
158 if let Some(raw_msg) = err.downcast_ref::<&'static str>() {
159 if raw_msg.contains("Index out of bounds") {
160 MechError2::new(
161 IndexOutOfBoundsError,
162 None,
163 ).with_compiler_loc()
164 } else if raw_msg.contains("attempt to subtract with overflow") {
165 MechError2::new(
166 OverflowSubtractionError,
167 None,
168 ).with_compiler_loc()
169 } else {
170 MechError2::new(
171 UnknownPanicError {
172 details: raw_msg.to_string(),
173 },
174 None,
175 ).with_compiler_loc()
176 }
177 } else {
178 MechError2::new(
179 UnknownPanicError {
180 details: "Non-string panic".to_string(),
181 },
182 None,
183 ).with_compiler_loc()
184 }
185 })?
186}
187
188
189 #[cfg(feature = "program")]
190 pub fn run_program(&mut self, program: &ParsedProgram) -> MResult<Value> {
191 self.ip = 0;
193 self.registers = vec![Value::Empty; program.header.reg_count as usize];
195 self.constants = vec![Value::Empty; program.const_entries.len()];
196 self.constants = program.decode_const_entries()?;
198 {
200 let mut state_brrw = self.state.borrow_mut();
201 let mut symbol_table = state_brrw.symbol_table.borrow_mut();
202 for (id, reg) in program.symbols.iter() {
203 let constant = self.constants[*reg as usize].clone();
204 self.out = constant.clone();
205 let mutable = program.mutable_symbols.contains(id);
206 symbol_table.insert(*id, constant, mutable);
207 }
208 }
209 {
211 let state_brrw = self.state.borrow();
212 let functions_table = state_brrw.functions.borrow();
213 while self.ip < program.instrs.len() {
214 let instr = &program.instrs[self.ip];
215 match instr {
216 DecodedInstr::ConstLoad { dst, const_id } => {
217 let value = self.constants[*const_id as usize].clone();
218 self.registers[*dst as usize] = value;
219 },
220 DecodedInstr::NullOp{ fxn_id, dst } => {
221 match functions_table.functions.get(fxn_id) {
222 Some(fxn_factory) => {
223 let out = &self.registers[*dst as usize];
224 let fxn = fxn_factory(FunctionArgs::Nullary(out.clone()))?;
225 self.out = fxn.out().clone();
226 state_brrw.add_plan_step(fxn);
227 },
228 None => {
229 return Err(MechError2::new(
230 UnknownNullaryFunctionError { fxn_id: *fxn_id },
231 None
232 ).with_compiler_loc());
233 }
234 }
235 },
236 DecodedInstr::UnOp{ fxn_id, dst, src } => {
237 match functions_table.functions.get(fxn_id) {
238 Some(fxn_factory) => {
239 let src = &self.registers[*src as usize];
240 let out = &self.registers[*dst as usize];
241 let fxn = fxn_factory(FunctionArgs::Unary(out.clone(), src.clone()))?;
242 self.out = fxn.out().clone();
243 state_brrw.add_plan_step(fxn);
244 },
245 None => {
246 return Err(MechError2::new(
247 UnknownUnaryFunctionError { fxn_id: *fxn_id },
248 None
249 ).with_compiler_loc());
250 }
251 }
252 },
253 DecodedInstr::BinOp{ fxn_id, dst, lhs, rhs } => {
254 match functions_table.functions.get(fxn_id) {
255 Some(fxn_factory) => {
256 let lhs = &self.registers[*lhs as usize];
257 let rhs = &self.registers[*rhs as usize];
258 let out = &self.registers[*dst as usize];
259 let fxn = fxn_factory(FunctionArgs::Binary(out.clone(), lhs.clone(), rhs.clone()))?;
260 self.out = fxn.out().clone();
261 state_brrw.add_plan_step(fxn);
262 },
263 None => {
264 return Err(MechError2::new(
265 UnknownBinaryFunctionError { fxn_id: *fxn_id },
266 None
267 ).with_compiler_loc());
268 }
269 }
270 },
271 DecodedInstr::TernOp{ fxn_id, dst, a, b, c } => {
272 match functions_table.functions.get(fxn_id) {
273 Some(fxn_factory) => {
274 let arg1 = &self.registers[*a as usize];
275 let arg2 = &self.registers[*b as usize];
276 let arg3 = &self.registers[*c as usize];
277 let out = &self.registers[*dst as usize];
278 let fxn = fxn_factory(FunctionArgs::Ternary(out.clone(), arg1.clone(), arg2.clone(), arg3.clone()))?;
279 self.out = fxn.out().clone();
280 state_brrw.add_plan_step(fxn);
281 },
282 None => {
283 return Err(MechError2::new(
284 UnknownTernaryFunctionError { fxn_id: *fxn_id },
285 None
286 ).with_compiler_loc());
287 }
288 }
289 },
290 DecodedInstr::QuadOp{ fxn_id, dst, a, b, c, d } => {
291 match functions_table.functions.get(fxn_id) {
292 Some(fxn_factory) => {
293 let arg1 = &self.registers[*a as usize];
294 let arg2 = &self.registers[*b as usize];
295 let arg3 = &self.registers[*c as usize];
296 let arg4 = &self.registers[*d as usize];
297 let out = &self.registers[*dst as usize];
298 let fxn = fxn_factory(FunctionArgs::Quaternary(out.clone(), arg1.clone(), arg2.clone(), arg3.clone(), arg4.clone()))?;
299 self.out = fxn.out().clone();
300 state_brrw.add_plan_step(fxn);
301 },
302 None => {
303 return Err(MechError2::new(
304 UnknownQuadFunctionError { fxn_id: *fxn_id },
305 None
306 ).with_compiler_loc());
307 }
308 }
309 },
310 DecodedInstr::VarArg{ fxn_id, dst, args } => {
311 match functions_table.functions.get(fxn_id) {
312 Some(fxn_factory) => {
313 let arg_values: Vec<Value> = args.iter().map(|r| self.registers[*r as usize].clone()).collect();
314 let out = &self.registers[*dst as usize];
315 let fxn = fxn_factory(FunctionArgs::Variadic(out.clone(), arg_values))?;
316 self.out = fxn.out().clone();
317 state_brrw.add_plan_step(fxn);
318 },
319 None => {
320 return Err(MechError2::new(
321 UnknownVariadicFunctionError { fxn_id: *fxn_id },
322 None
323 ).with_compiler_loc());
324 }
325 }
326 },
327 DecodedInstr::Ret{ src } => {
328 todo!();
329 },
330 x => {
331 return Err(MechError2::new(
332 UnknownInstructionError { instr: format!("{:?}", x) },
333 None
334 ).with_compiler_loc());
335 }
336 }
337 self.ip += 1;
338 }
339 }
340 {
342 let mut state_brrw = self.state.borrow_mut();
343 let mut symbol_table = state_brrw.symbol_table.borrow_mut();
344 for (id, name) in &program.dictionary {
345 symbol_table.dictionary.borrow_mut().insert(*id, name.clone());
346 state_brrw.dictionary.borrow_mut().insert(*id, name.clone());
347 }
348 }
349 Ok(self.out.clone())
350 }
351
352 #[cfg(feature = "compiler")]
353 pub fn compile(&mut self) -> MResult<Vec<u8>> {
354 let state_brrw = self.state.borrow();
355 let mut plan_brrw = state_brrw.plan.borrow_mut();
356 let mut ctx = CompileCtx::new();
357 for step in plan_brrw.iter() {
358 step.compile(&mut ctx)?;
359 }
360 let bytes = ctx.compile()?;
361 self.context = Some(ctx);
362 Ok(bytes)
363 }
364
365}
366
367#[derive(Debug, Clone)]
368pub struct UnknownInstructionError {
369 pub instr: String,
370}
371impl MechErrorKind2 for UnknownInstructionError {
372 fn name(&self) -> &str {
373 "UnknownInstruction"
374 }
375
376 fn message(&self) -> String {
377 format!("Unknown instruction: {}", self.instr)
378 }
379}
380
381#[derive(Debug, Clone)]
382pub struct UnknownVariadicFunctionError {
383 pub fxn_id: u64,
384}
385
386impl MechErrorKind2 for UnknownVariadicFunctionError {
387 fn name(&self) -> &str {
388 "UnknownVariadicFunction"
389 }
390 fn message(&self) -> String {
391 format!("Unknown variadic function ID: {}", self.fxn_id)
392 }
393}
394
395#[derive(Debug, Clone)]
396pub struct UnknownQuadFunctionError {
397 pub fxn_id: u64,
398}
399impl MechErrorKind2 for UnknownQuadFunctionError {
400 fn name(&self) -> &str {
401 "UnknownQuadFunction"
402 }
403 fn message(&self) -> String {
404 format!("Unknown quad function ID: {}", self.fxn_id)
405 }
406}
407
408#[derive(Debug, Clone)]
409pub struct UnknownTernaryFunctionError {
410 pub fxn_id: u64,
411}
412impl MechErrorKind2 for UnknownTernaryFunctionError {
413 fn name(&self) -> &str {
414 "UnknownTernaryFunction"
415 }
416 fn message(&self) -> String {
417 format!("Unknown ternary function ID: {}", self.fxn_id)
418 }
419}
420
421#[derive(Debug, Clone)]
422pub struct UnknownBinaryFunctionError {
423 pub fxn_id: u64,
424}
425impl MechErrorKind2 for UnknownBinaryFunctionError {
426 fn name(&self) -> &str {
427 "UnknownBinaryFunction"
428 }
429 fn message(&self) -> String {
430 format!("Unknown binary function ID: {}", self.fxn_id)
431 }
432}
433
434#[derive(Debug, Clone)]
435pub struct UnknownUnaryFunctionError {
436 pub fxn_id: u64,
437}
438impl MechErrorKind2 for UnknownUnaryFunctionError {
439 fn name(&self) -> &str {
440 "UnknownUnaryFunction"
441 }
442 fn message(&self) -> String {
443 format!("Unknown unary function ID: {}", self.fxn_id)
444 }
445}
446
447#[derive(Debug, Clone)]
448pub struct UnknownNullaryFunctionError {
449 pub fxn_id: u64,
450}
451impl MechErrorKind2 for UnknownNullaryFunctionError {
452 fn name(&self) -> &str {
453 "UnknownNullaryFunction"
454 }
455 fn message(&self) -> String {
456 format!("Unknown nullary function ID: {}", self.fxn_id)
457 }
458}
459
460#[derive(Debug, Clone)]
461pub struct IndexOutOfBoundsError;
462impl MechErrorKind2 for IndexOutOfBoundsError {
463 fn name(&self) -> &str { "IndexOutOfBounds" }
464 fn message(&self) -> String { "Index out of bounds".to_string() }
465}
466
467#[derive(Debug, Clone)]
468pub struct OverflowSubtractionError;
469impl MechErrorKind2 for OverflowSubtractionError {
470 fn name(&self) -> &str { "OverflowSubtraction" }
471 fn message(&self) -> String { "Attempted subtraction overflow".to_string() }
472}
473
474#[derive(Debug, Clone)]
475pub struct UnknownPanicError {
476 pub details: String
477}
478impl MechErrorKind2 for UnknownPanicError {
479 fn name(&self) -> &str { "UnknownPanic" }
480 fn message(&self) -> String { self.details.clone() }
481}
482
483#[derive(Debug, Clone)]
484struct StepIndexOutOfBoundsError{
485 pub step_id: usize,
486 pub plan_length: usize,
487}
488impl MechErrorKind2 for StepIndexOutOfBoundsError {
489 fn name(&self) -> &str { "StepIndexOutOfBounds" }
490 fn message(&self) -> String {
491 format!("Step id {} out of range (plan has {} steps)", self.step_id, self.plan_length)
492 }
493}
494
495#[derive(Debug, Clone)]
496struct NoStepsInPlanError;
497impl MechErrorKind2 for NoStepsInPlanError {
498 fn name(&self) -> &str { "NoStepsInPlan" }
499 fn message(&self) -> String {
500 "Plan contains no steps. This program doesn't do anything.".to_string()
501 }
502}