Skip to content

Commit

Permalink
[rvm] Initial Commit:
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaimeloeuf committed Mar 8, 2021
1 parent e40bcfa commit 565ed49
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 0 deletions.
1 change: 1 addition & 0 deletions rvm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
5 changes: 5 additions & 0 deletions rvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions rvm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "rvm"
version = "0.1.0"
authors = ["Jaime <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
4 changes: 4 additions & 0 deletions rvm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# RVM [Rust VM]
Reference Bytecode Virtual Machine implemented in Rust.

WIP experiment based off Clox.
31 changes: 31 additions & 0 deletions rvm/src/chunk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::opcode::OpCode;
use crate::value::Value;

#[derive(Debug)]
pub struct Chunk {
pub codes: Vec<OpCode>,

// Constant Pool: Vector storing all the constant values dynamically and accessed using index stored in 'codes' vector
pub constants: Vec<Value>,

// Optimize storing line info: https://en.wikipedia.org/wiki/Run-length_encoding
pub lines: Vec<usize>,
}

impl Chunk {
// Associated function to create a new Chunk
pub fn new() -> Chunk {
Chunk {
// codes: Vec::<OpCode>::new(),
codes: Vec::<OpCode>::with_capacity(6),
constants: Vec::new(),
lines: Vec::new(),
}
}

// Method to write a new OpCode
pub fn write(&mut self, byte: OpCode, line_number: usize) {
self.codes.push(byte);
self.lines.push(line_number);
}
}
58 changes: 58 additions & 0 deletions rvm/src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::chunk::Chunk;
use crate::opcode::OpCode;

// pub fn disassemble_chunk(chunk: Chunk, name: &String) {
pub fn disassemble_chunk(chunk: &Chunk, name: &str) {
// println!("{:?} ", chunk);
println!("== {} ==", name);

let mut offset: usize = 0;
while offset < chunk.codes.len() {
offset = disassemble_instruction(&chunk, offset);
}
}

fn disassemble_instruction(chunk: &Chunk, offset: usize) -> usize {
// Prints the offset (bytecode index of a chunk) with 0 padding up to 3 digits
// https://stackoverflow.com/a/41821049
print!("{:0width$}", offset, width = 3);

// Print line number or | for bytecodes on the same line
if offset > 0 && chunk.lines[offset] == chunk.lines[offset - 1] {
print!(" | ");
} else {
print!("{:4} ", chunk.lines[offset]);
}

match chunk.codes[offset] {
OpCode::RETURN => simple_instruction("RETURN", &chunk, offset),
OpCode::CONSTANT => constant_instruction("CONSTANT", &chunk, offset),
// OpCode::ConstantIndex(index) => simple_instruction("ConstantIndex", offset),
//
ref instruction => {
println!("Unknown opcode {:?}\n", instruction);
offset + 1
}
}
}
/*
Printing should be of the format
Line number OpCode index OpCode string representation add. data if any
*/

// fn simple_instruction(name: &str, offset: usize) -> usize {
// println!("{}", name);
// offset + 1
// }
fn simple_instruction(name: &str, chunk: &Chunk, offset: usize) -> usize {
println!("{:?}", chunk.codes[offset]);
offset + 1
}

fn constant_instruction(name: &str, chunk: &Chunk, offset: usize) -> usize {
let constant = &chunk.constants[offset];

// println!("{} -> {:?}", name, constant);
println!("{:?} -> {:?}", chunk.codes[offset], constant);
offset + 2
}
24 changes: 24 additions & 0 deletions rvm/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
mod chunk;
mod debug;
mod opcode;
mod value;
mod vm;

use chunk::Chunk;
use debug::disassemble_chunk;
use opcode::OpCode;
use value::Value;
use vm::VM;

fn main() {
let mut chunk = Chunk::new();

chunk.write(OpCode::CONSTANT, 2);
chunk.constants.push(Value::Number(1.2));
chunk.write(OpCode::ConstantIndex(chunk.constants.len()), 2);

chunk.write(OpCode::RETURN, 2);

disassemble_chunk(&chunk, "test");
// println!("{:?}", chunk);
}
13 changes: 13 additions & 0 deletions rvm/src/opcode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// There are 2 types of OpCodes
// First type are the instruction OpCodes, that are denoted by their all CAPS spelling
// Secondly there are special OpCodes, that are variants with additional values like 'ConstantIndex(usize)'
//
// Clox differentiate OpCode from Data using OP_ prefix, and also all their data types is just a single byte anyways

#[derive(Debug)]
pub enum OpCode {
RETURN,
CONSTANT,

ConstantIndex(usize),
}
9 changes: 9 additions & 0 deletions rvm/src/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// type Value = f64;

#[derive(Debug)]
pub enum Value {
Number(f64),
String(String),
Bool(bool),
Null,
}
20 changes: 20 additions & 0 deletions rvm/src/vm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::chunk::Chunk;
use crate::opcode::OpCode;

pub struct VM {
pub chunks: Vec<Chunk>,
}

// Change this to error or something
pub enum InterpretResult {
Ok,
CompileError,
RuntimeError,
}

impl VM {
// CHange this to result type
pub fn interpret(chunk: &Chunk) -> InterpretResult {
InterpretResult::Ok
}
}

0 comments on commit 565ed49

Please sign in to comment.