add untracked from opening bytecode branch
This commit is contained in:
parent
9c3205d4c1
commit
096d8d00bc
68
src/main.rs
Normal file
68
src/main.rs
Normal 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
87
src/vm.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user