2024-12-16 04:50:12 +00:00
|
|
|
use crate::compiler::{Chunk, Op};
|
|
|
|
use crate::parser::Ast;
|
|
|
|
use crate::spans::Spanned;
|
|
|
|
use crate::value::Value;
|
|
|
|
use chumsky::prelude::SimpleSpan;
|
|
|
|
use num_traits::FromPrimitive;
|
2024-12-18 04:45:39 +00:00
|
|
|
use std::mem::swap;
|
2024-12-16 04:50:12 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct Panic {
|
|
|
|
pub input: &'static str,
|
|
|
|
pub src: &'static str,
|
|
|
|
pub msg: String,
|
|
|
|
pub span: SimpleSpan,
|
|
|
|
pub trace: Vec<Trace>,
|
|
|
|
pub extra: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct Trace {
|
|
|
|
pub callee: Spanned<Ast>,
|
|
|
|
pub caller: Spanned<Ast>,
|
|
|
|
pub function: Value,
|
|
|
|
pub arguments: Value,
|
|
|
|
pub input: &'static str,
|
|
|
|
pub src: &'static str,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Vm<'a> {
|
|
|
|
pub stack: Vec<Value>,
|
|
|
|
pub chunk: &'a Chunk<'a>,
|
|
|
|
pub ip: usize,
|
2024-12-18 04:45:39 +00:00
|
|
|
pub return_register: Value,
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Vm<'a> {
|
|
|
|
pub fn new(chunk: &'a Chunk) -> Vm<'a> {
|
|
|
|
Vm {
|
|
|
|
chunk,
|
|
|
|
stack: vec![],
|
|
|
|
ip: 0,
|
2024-12-18 04:45:39 +00:00
|
|
|
return_register: Value::Nil,
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push(&mut self, value: Value) {
|
|
|
|
self.stack.push(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop(&mut self) -> Value {
|
2024-12-18 06:28:23 +00:00
|
|
|
self.stack.pop().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_stack(&self) {
|
|
|
|
let inner = self
|
|
|
|
.stack
|
|
|
|
.iter()
|
|
|
|
.map(|val| val.to_string())
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join("|");
|
|
|
|
println!("{:04}: [{inner}] {}", self.ip, self.return_register);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_debug(&self) {
|
|
|
|
self.chunk.dissasemble_instr(self.ip);
|
|
|
|
self.print_stack();
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn interpret(&mut self) -> Result<Value, Panic> {
|
2024-12-18 04:45:39 +00:00
|
|
|
let Some(byte) = self.chunk.bytecode.get(self.ip) else {
|
|
|
|
return Ok(self.stack.pop().unwrap());
|
|
|
|
};
|
2024-12-18 06:28:23 +00:00
|
|
|
if crate::DEBUG_RUN {
|
|
|
|
self.print_debug();
|
|
|
|
}
|
2024-12-18 04:45:39 +00:00
|
|
|
let op = Op::from_u8(*byte).unwrap();
|
2024-12-16 04:50:12 +00:00
|
|
|
use Op::*;
|
|
|
|
match op {
|
|
|
|
Constant => {
|
|
|
|
let const_idx = self.chunk.bytecode[self.ip + 1];
|
|
|
|
let value = self.chunk.constants[const_idx as usize].clone();
|
|
|
|
self.push(value);
|
|
|
|
self.ip += 2;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
Jump => {
|
|
|
|
let jump_len = self.chunk.bytecode[self.ip + 1];
|
|
|
|
self.ip += jump_len as usize;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
JumpIfFalse => {
|
|
|
|
let jump_len = self.chunk.bytecode[self.ip + 1];
|
2024-12-18 04:45:39 +00:00
|
|
|
let cond = self.pop();
|
2024-12-16 04:50:12 +00:00
|
|
|
match cond {
|
|
|
|
Value::Nil | Value::False => {
|
|
|
|
self.ip += jump_len as usize + 2;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.ip += 2;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-12-18 04:45:39 +00:00
|
|
|
Pop => {
|
|
|
|
self.pop();
|
|
|
|
self.ip += 1;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
PushBinding => {
|
|
|
|
let binding_idx = self.chunk.bytecode[self.ip + 1] as usize;
|
|
|
|
let binding_value = self.stack[binding_idx].clone();
|
|
|
|
self.push(binding_value);
|
|
|
|
self.ip += 2;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
Store => {
|
|
|
|
self.return_register = self.pop();
|
|
|
|
self.push(Value::Nil);
|
|
|
|
self.ip += 1;
|
|
|
|
self.interpret()
|
|
|
|
}
|
|
|
|
Load => {
|
|
|
|
let mut value = Value::Nil;
|
2024-12-18 06:28:23 +00:00
|
|
|
// println!(
|
|
|
|
// "before swap, return register holds: {}",
|
|
|
|
// self.return_register
|
|
|
|
// );
|
2024-12-18 04:45:39 +00:00
|
|
|
swap(&mut self.return_register, &mut value);
|
2024-12-18 06:28:23 +00:00
|
|
|
// println!(
|
|
|
|
// "before swap, return register holds: {}",
|
|
|
|
// self.return_register
|
|
|
|
// );
|
|
|
|
// println!("now local value holds {value}");
|
2024-12-18 04:45:39 +00:00
|
|
|
self.push(value);
|
|
|
|
self.ip += 1;
|
|
|
|
self.interpret()
|
|
|
|
}
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|