add return and const instructions.
This commit is contained in:
commit
5cee345e8b
|
@ -0,0 +1 @@
|
||||||
|
/target
|
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mox"
|
||||||
|
version = "0.1.0"
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "mox"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,44 @@
|
||||||
|
use mox::value::Value;
|
||||||
|
use mox::{Chunk, ConversionError, OptCode};
|
||||||
|
|
||||||
|
pub fn disassemble_chunk(chunk: &Chunk, name: &str) {
|
||||||
|
// println!("{:?}", chunk);
|
||||||
|
println!("== {} ==", name);
|
||||||
|
let mut offset = 0;
|
||||||
|
while offset < chunk.code.len() {
|
||||||
|
offset = disassemble_instruction(&chunk, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn disassemble_instruction(chunk: &Chunk, offset: usize) -> usize {
|
||||||
|
print!("{:04} ", offset);
|
||||||
|
let instruction: Result<OptCode, ConversionError> = chunk.code[offset].try_into();
|
||||||
|
match instruction {
|
||||||
|
Ok(code) => match code {
|
||||||
|
OptCode::OpConstant => {
|
||||||
|
return constant_instruction("OpConstant", chunk, offset);
|
||||||
|
}
|
||||||
|
OptCode::OpReturn => {
|
||||||
|
return simple_instruction("OpReturn", offset);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
println!("Unknown optcode {:?}", e);
|
||||||
|
return offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simple_instruction(name: &str, offset: usize) -> usize {
|
||||||
|
println!("{}", name);
|
||||||
|
return offset + 1;
|
||||||
|
}
|
||||||
|
fn constant_instruction(name: &str, chunk: &Chunk, offset: usize) -> usize {
|
||||||
|
let constant: u8 = chunk.code[offset + 1];
|
||||||
|
print!("{:<16} {:>4} ", name, constant);
|
||||||
|
print_value(chunk.constants[constant as usize]);
|
||||||
|
println!();
|
||||||
|
return offset + 2;
|
||||||
|
}
|
||||||
|
fn print_value(value: Value) {
|
||||||
|
print!("{:}", value);
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
pub mod value;
|
||||||
|
|
||||||
|
use value::Value;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum OptCode {
|
||||||
|
OpReturn,
|
||||||
|
OpConstant,
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Chunk {
|
||||||
|
pub code: Vec<u8>,
|
||||||
|
pub constants: Vec<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OptCode> for u8 {
|
||||||
|
fn from(code: OptCode) -> Self {
|
||||||
|
match code {
|
||||||
|
OptCode::OpReturn => 0,
|
||||||
|
OptCode::OpConstant => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConversionError;
|
||||||
|
|
||||||
|
impl TryFrom<u8> for OptCode {
|
||||||
|
type Error = ConversionError;
|
||||||
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
||||||
|
match code {
|
||||||
|
0 => Ok(OptCode::OpReturn),
|
||||||
|
1 => Ok(OptCode::OpConstant),
|
||||||
|
_ => Err(ConversionError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chunk {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
code: vec![],
|
||||||
|
constants: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn write(&mut self, byte: u8) {
|
||||||
|
self.code.push(byte);
|
||||||
|
}
|
||||||
|
pub fn write_value(&mut self, add: Value) -> u8 {
|
||||||
|
self.constants.push(add);
|
||||||
|
return (self.constants.len() - 1).try_into().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn u8_to_optcode() {
|
||||||
|
let pred: OptCode = 0.try_into().unwrap();
|
||||||
|
assert_eq!(pred, OptCode::OpReturn);
|
||||||
|
let pred: OptCode = 1.try_into().unwrap();
|
||||||
|
assert_eq!(pred, OptCode::OpConstant);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn basic_write() {
|
||||||
|
let mut chunk = Chunk::new();
|
||||||
|
let constant_idx: u8 = chunk.write_value(1.2);
|
||||||
|
assert_eq!(constant_idx, 0);
|
||||||
|
chunk.write(OptCode::OpConstant.into());
|
||||||
|
chunk.write(constant_idx);
|
||||||
|
let pred: OptCode = chunk.code[0].try_into().unwrap();
|
||||||
|
assert_eq!(pred, OptCode::OpConstant);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn try_into_constant() {
|
||||||
|
let mut chunk = Chunk::new();
|
||||||
|
let constant_idx: u8 = chunk.write_value(1.2);
|
||||||
|
chunk.write(OptCode::OpConstant.into());
|
||||||
|
chunk.write(constant_idx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
use mox::Chunk;
|
||||||
|
use mox::OptCode;
|
||||||
|
mod debug;
|
||||||
|
|
||||||
|
use debug::disassemble_chunk;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut chunk = Chunk::new();
|
||||||
|
let constant_idx: u8 = chunk.write_value(1.2);
|
||||||
|
chunk.write(OptCode::OpConstant.into());
|
||||||
|
chunk.write(constant_idx);
|
||||||
|
chunk.write(OptCode::OpReturn.into());
|
||||||
|
|
||||||
|
disassemble_chunk(&chunk, "test chunk");
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub type Value = f64;
|
Loading…
Reference in New Issue