Playing around with non enum based bytecode
This commit is contained in:
parent
85211b127d
commit
6096bb431a
@ -2,6 +2,8 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use crate::ast::{Ast, Expr, Stmt, BinOpType};
|
use crate::ast::{Ast, Expr, Stmt, BinOpType};
|
||||||
|
|
||||||
|
type OpcodeSize = u32;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum OP {
|
pub enum OP {
|
||||||
@ -35,8 +37,6 @@ pub enum OP {
|
|||||||
|
|
||||||
JumpFalse,
|
JumpFalse,
|
||||||
|
|
||||||
Value(u32),
|
|
||||||
|
|
||||||
Print,
|
Print,
|
||||||
|
|
||||||
DbgPrint,
|
DbgPrint,
|
||||||
@ -44,7 +44,7 @@ pub enum OP {
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
ops: Vec<OP>,
|
ops: Vec<u32>,
|
||||||
global_vars: HashMap<String, u64>,
|
global_vars: HashMap<String, u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ impl Compiler {
|
|||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Expr(expr) => {
|
Stmt::Expr(expr) => {
|
||||||
self.compile_expr(expr);
|
self.compile_expr(expr);
|
||||||
self.ops.push(OP::Pop);
|
self.ops.push(OP::Pop as OpcodeSize);
|
||||||
}
|
}
|
||||||
Stmt::Let(name, rhs) => {
|
Stmt::Let(name, rhs) => {
|
||||||
let id = self.global_vars.len() as u64;
|
let id = self.global_vars.len() as u64;
|
||||||
@ -71,13 +71,13 @@ impl Compiler {
|
|||||||
let idx_start = self.ops.len();
|
let idx_start = self.ops.len();
|
||||||
self.compile_expr(cond);
|
self.compile_expr(cond);
|
||||||
|
|
||||||
self.ops.push(OP::JumpFalse);
|
self.ops.push(OP::JumpFalse as OpcodeSize);
|
||||||
let idx_jmp = self.ops.len();
|
let idx_jmp = self.ops.len();
|
||||||
self.gen_i64(0);
|
self.gen_i64(0);
|
||||||
|
|
||||||
self.compile(body);
|
self.compile(body);
|
||||||
|
|
||||||
self.ops.push(OP::Jump);
|
self.ops.push(OP::Jump as OpcodeSize);
|
||||||
self.gen_i64(idx_start as i64);
|
self.gen_i64(idx_start as i64);
|
||||||
|
|
||||||
self.overwrite_i64(idx_jmp, self.ops.len() as i64);
|
self.overwrite_i64(idx_jmp, self.ops.len() as i64);
|
||||||
@ -86,13 +86,13 @@ impl Compiler {
|
|||||||
Stmt::If(cond, if_block, else_block) => {
|
Stmt::If(cond, if_block, else_block) => {
|
||||||
self.compile_expr(cond);
|
self.compile_expr(cond);
|
||||||
|
|
||||||
self.ops.push(OP::JumpFalse);
|
self.ops.push(OP::JumpFalse as OpcodeSize);
|
||||||
let idx_if = self.ops.len();
|
let idx_if = self.ops.len();
|
||||||
self.gen_i64(0);
|
self.gen_i64(0);
|
||||||
|
|
||||||
self.compile(if_block);
|
self.compile(if_block);
|
||||||
|
|
||||||
self.ops.push(OP::Jump);
|
self.ops.push(OP::Jump as OpcodeSize);
|
||||||
let idx_else = self.ops.len();
|
let idx_else = self.ops.len();
|
||||||
self.gen_i64(0);
|
self.gen_i64(0);
|
||||||
|
|
||||||
@ -105,24 +105,24 @@ impl Compiler {
|
|||||||
},
|
},
|
||||||
Stmt::DbgPrint(expr) => {
|
Stmt::DbgPrint(expr) => {
|
||||||
self.compile_expr(expr);
|
self.compile_expr(expr);
|
||||||
self.ops.push(OP::DbgPrint);
|
self.ops.push(OP::DbgPrint as OpcodeSize);
|
||||||
}
|
}
|
||||||
Stmt::Print(expr) => {
|
Stmt::Print(expr) => {
|
||||||
self.compile_expr(expr);
|
self.compile_expr(expr);
|
||||||
self.ops.push(OP::Print);
|
self.ops.push(OP::Print as OpcodeSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_ops(self) -> Vec<OP> {
|
pub fn into_ops(self) -> Vec<u32> {
|
||||||
self.ops
|
self.ops
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_expr(&mut self, expr: &Expr) {
|
pub fn compile_expr(&mut self, expr: &Expr) {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::I64(val) => {
|
Expr::I64(val) => {
|
||||||
self.ops.push(OP::Push);
|
self.ops.push(OP::Push as OpcodeSize);
|
||||||
self.gen_i64(*val)
|
self.gen_i64(*val)
|
||||||
}
|
}
|
||||||
Expr::Ident(name) => {
|
Expr::Ident(name) => {
|
||||||
@ -155,48 +155,56 @@ impl Compiler {
|
|||||||
self.compile_expr(rhs);
|
self.compile_expr(rhs);
|
||||||
|
|
||||||
match bo {
|
match bo {
|
||||||
BinOpType::Add => self.ops.push(OP::Add),
|
BinOpType::Add => self.ops.push(OP::Add as OpcodeSize),
|
||||||
BinOpType::Sub => self.ops.push(OP::Subtract),
|
BinOpType::Sub => self.ops.push(OP::Subtract as OpcodeSize),
|
||||||
BinOpType::Mul => self.ops.push(OP::Multiply),
|
BinOpType::Mul => self.ops.push(OP::Multiply as OpcodeSize),
|
||||||
BinOpType::Div => self.ops.push(OP::Divide),
|
BinOpType::Div => self.ops.push(OP::Divide as OpcodeSize),
|
||||||
BinOpType::Mod => self.ops.push(OP::Modulo),
|
BinOpType::Mod => self.ops.push(OP::Modulo as OpcodeSize),
|
||||||
BinOpType::BOr => self.ops.push(OP::BOr),
|
BinOpType::BOr => self.ops.push(OP::BOr as OpcodeSize),
|
||||||
BinOpType::BAnd => self.ops.push(OP::BAnd),
|
BinOpType::BAnd => self.ops.push(OP::BAnd as OpcodeSize),
|
||||||
BinOpType::BXor => self.ops.push(OP::BXor),
|
BinOpType::BXor => self.ops.push(OP::BXor as OpcodeSize),
|
||||||
BinOpType::Shl => self.ops.push(OP::Shl),
|
BinOpType::Shl => self.ops.push(OP::Shl as OpcodeSize),
|
||||||
BinOpType::Shr => self.ops.push(OP::Shr),
|
BinOpType::Shr => self.ops.push(OP::Shr as OpcodeSize),
|
||||||
BinOpType::Equ => self.ops.push(OP::Eq),
|
BinOpType::Equ => self.ops.push(OP::Eq as OpcodeSize),
|
||||||
BinOpType::Neq => self.ops.push(OP::Neq),
|
BinOpType::Neq => self.ops.push(OP::Neq as OpcodeSize),
|
||||||
BinOpType::Gt => self.ops.push(OP::Gt),
|
BinOpType::Gt => self.ops.push(OP::Gt as OpcodeSize),
|
||||||
BinOpType::Ge => self.ops.push(OP::Ge),
|
BinOpType::Ge => self.ops.push(OP::Ge as OpcodeSize),
|
||||||
BinOpType::Lt => self.ops.push(OP::Lt),
|
BinOpType::Lt => self.ops.push(OP::Lt as OpcodeSize),
|
||||||
BinOpType::Le => self.ops.push(OP::Le),
|
BinOpType::Le => self.ops.push(OP::Le as OpcodeSize),
|
||||||
BinOpType::Assign => unreachable!(),
|
BinOpType::Assign => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_i64(&mut self, val: i64) {
|
fn gen_i64(&mut self, val: i64) {
|
||||||
self.ops.push(OP::Value((val & u32::MAX as i64) as u32));
|
// for i in 0 .. 8 {
|
||||||
self.ops.push(OP::Value((val >> 32) as u32));
|
// self.ops.push(((val >> i*8) & 0xff) as OpcodeSize);
|
||||||
|
// }
|
||||||
|
for i in 0 .. 2 {
|
||||||
|
self.ops.push(((val >> i*32) & 0xffffffff) as OpcodeSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overwrite_i64(&mut self, idx: usize, val: i64) {
|
fn overwrite_i64(&mut self, idx: usize, val: i64) {
|
||||||
self.ops[idx] = OP::Value((val & u32::MAX as i64) as u32);
|
// for i in 0 .. 8 {
|
||||||
self.ops[idx+1] = OP::Value((val >> 32) as u32);
|
// self.ops[idx+i] = ((val >> i*8) & 0xff) as OpcodeSize;
|
||||||
|
// }
|
||||||
|
for i in 0 .. 2 {
|
||||||
|
self.ops[idx+i] = ((val >> i*32) & 0xffffffff) as OpcodeSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_load(&mut self, addr: u64) {
|
fn gen_load(&mut self, addr: u64) {
|
||||||
self.ops.push(OP::Load);
|
self.ops.push(OP::Load as OpcodeSize);
|
||||||
self.gen_i64(addr as i64)
|
self.gen_i64(addr as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_store(&mut self, addr: u64) {
|
fn gen_store(&mut self, addr: u64) {
|
||||||
self.ops.push(OP::Store);
|
self.ops.push(OP::Store as OpcodeSize);
|
||||||
self.gen_i64(addr as i64)
|
self.gen_i64(addr as i64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(ast: &Ast) -> Vec<OP> {
|
pub fn compile(ast: &Ast) -> Vec<u32> {
|
||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
compiler.compile(ast);
|
compiler.compile(ast);
|
||||||
compiler.into_ops()
|
compiler.into_ops()
|
||||||
|
|||||||
35
src/vm.rs
35
src/vm.rs
@ -2,7 +2,7 @@ use crate::{bytecode::OP, interpreter::Value};
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Vm {
|
pub struct Vm {
|
||||||
prog: Vec<OP>,
|
prog: Vec<u32>,
|
||||||
ip: usize,
|
ip: usize,
|
||||||
stack: Vec<Value>,
|
stack: Vec<Value>,
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ pub struct Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
pub fn new(prog: Vec<OP>) -> Self {
|
pub fn new(prog: Vec<u32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
prog,
|
prog,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -19,7 +19,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
while let Some(op) = self.prog.get(self.ip).copied() {
|
while let Some(op) = self.prog.get(self.ip).copied().map(|op| unsafe { std::mem::transmute::<u32, OP>(op) }) {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
@ -136,9 +136,6 @@ impl Vm {
|
|||||||
let vals = self.pop2_i64();
|
let vals = self.pop2_i64();
|
||||||
self.stack.push(Value::I64(vals.0 >> vals.1))
|
self.stack.push(Value::I64(vals.0 >> vals.1))
|
||||||
}
|
}
|
||||||
OP::Value(_) => {
|
|
||||||
panic!("This is not an instruction, but data. This should never be evaluated")
|
|
||||||
}
|
|
||||||
OP::Jump => {
|
OP::Jump => {
|
||||||
self.ip = self.read_i64() as usize;
|
self.ip = self.read_i64() as usize;
|
||||||
}
|
}
|
||||||
@ -168,22 +165,22 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_i64(&mut self) -> i64 {
|
fn read_i64(&mut self) -> i64 {
|
||||||
let mut val = if let Some(OP::Value(val)) = self.prog.get(self.ip).copied() {
|
let mut val = *self.prog.get(self.ip).unwrap() as i64;
|
||||||
val
|
val |= (*self.prog.get(self.ip + 1).unwrap() as i64) << 32;
|
||||||
} else {
|
|
||||||
panic!("Expected Value as next OP")
|
|
||||||
} as i64;
|
|
||||||
|
|
||||||
self.ip += 1;
|
// let mut bytes = [0; 8];
|
||||||
|
// bytes.copy_from_slice(&self.prog[self.ip..self.ip+8]);
|
||||||
|
// val = i64::from_le_bytes(bytes);
|
||||||
|
|
||||||
val |= (if let Some(OP::Value(val)) = self.prog.get(self.ip).copied() {
|
// for i in 0 .. 8 {
|
||||||
val
|
// if let Some(tmp) = self.prog.get(self.ip + i).copied() {
|
||||||
} else {
|
// val |= ((tmp as i64) << i*8) as i64;
|
||||||
panic!("Expected Value as next OP")
|
// } else {
|
||||||
} as i64)
|
// panic!("Expected Value as next OP")
|
||||||
<< 32;
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
self.ip += 1;
|
self.ip += 2;
|
||||||
|
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user