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