add untracked from opening bytecode branch

This commit is contained in:
Scott Richmond 2024-12-15 23:50:12 -05:00
parent 9c3205d4c1
commit 096d8d00bc
2 changed files with 155 additions and 0 deletions

68
src/main.rs Normal file
View File

@ -0,0 +1,68 @@
use chumsky::{input::Stream, prelude::*};
mod spans;
mod lexer;
use crate::lexer::lexer;
mod parser;
use crate::parser::parser;
mod validator;
mod compiler;
use crate::compiler::Chunk;
mod value;
mod vm;
use vm::Vm;
pub fn run(src: &'static str) {
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
if !lex_errs.is_empty() {
println!("{:?}", lex_errs);
return;
}
let tokens = tokens.unwrap();
let (parse_result, parse_errors) = parser()
.parse(Stream::from_iter(tokens).map((0..src.len()).into(), |(t, s)| (t, s)))
.into_output_errors();
if !parse_errors.is_empty() {
println!("{:?}", parse_errors);
return;
}
let parsed = parse_result.unwrap();
let mut chunk = Chunk::new(&parsed, "test", src);
chunk.compile();
chunk.disassemble();
let mut vm = Vm::new(&chunk);
let result = vm.interpret();
let output = match result {
Ok(val) => val.show(&chunk),
Err(panic) => format!("{:?}", panic),
};
println!("{output}");
}
pub fn main() {
let src = "
if false
then {
:foo
:bar
:baz
}
else {
1
2
3
}
";
run(src);
}

87
src/vm.rs Normal file
View File

@ -0,0 +1,87 @@
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;
#[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,
pub bindings: Vec<(u8, usize)>,
}
impl<'a> Vm<'a> {
pub fn new(chunk: &'a Chunk) -> Vm<'a> {
Vm {
chunk,
stack: vec![],
ip: 0,
bindings: vec![],
}
}
pub fn push(&mut self, value: Value) {
self.stack.push(value);
}
pub fn pop(&mut self) -> Value {
self.stack.pop().unwrap()
}
pub fn interpret(&mut self) -> Result<Value, Panic> {
let byte = self.chunk.bytecode[self.ip];
let op = Op::from_u8(byte).unwrap();
use Op::*;
match op {
Return => Ok(self.stack.pop().unwrap()),
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];
let cond = self.stack.pop().unwrap();
match cond {
Value::Nil | Value::False => {
self.ip += jump_len as usize + 2;
self.interpret()
}
_ => {
self.ip += 2;
self.interpret()
}
}
}
}
}
}