feat(tazjin/rlox): Initial bytecode representation
This is significantly simplified from the version in the book, since I'm using Rust's Vec and not implementing dynamic arrays manually. We'll see if I run into issues with that ... Change-Id: Ie3446ac3884b850f3ba73a4b1a6ca14e68054188 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2413 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									30a6fcccee
								
							
						
					
					
						commit
						49c4cc6c56
					
				
					 4 changed files with 80 additions and 1 deletions
				
			
		
							
								
								
									
										57
									
								
								users/tazjin/rlox/src/bytecode/chunk.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								users/tazjin/rlox/src/bytecode/chunk.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
use std::ops::Index;
 | 
			
		||||
 | 
			
		||||
use super::opcode::OpCode;
 | 
			
		||||
use super::value;
 | 
			
		||||
 | 
			
		||||
// In the book, this type is a hand-rolled dynamic array
 | 
			
		||||
// implementation in C. The main benefit of following that approach
 | 
			
		||||
// would be avoiding issues with OpCode variants not having equal
 | 
			
		||||
// sizes, but for the purpose of this I'm going to ignore that
 | 
			
		||||
// problem.
 | 
			
		||||
#[derive(Debug, Default)]
 | 
			
		||||
pub struct Chunk {
 | 
			
		||||
    code: Vec<OpCode>,
 | 
			
		||||
    constants: Vec<value::Value>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Chunk {
 | 
			
		||||
    pub fn add_op(&mut self, data: OpCode) -> usize {
 | 
			
		||||
        let idx = self.code.len();
 | 
			
		||||
        self.code.push(data);
 | 
			
		||||
        idx
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_constant(&mut self, data: value::Value) -> usize {
 | 
			
		||||
        let idx = self.constants.len();
 | 
			
		||||
        self.constants.push(data);
 | 
			
		||||
        idx
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Index<usize> for Chunk {
 | 
			
		||||
    type Output = OpCode;
 | 
			
		||||
 | 
			
		||||
    fn index(&self, offset: usize) -> &Self::Output {
 | 
			
		||||
        self.code.index(offset)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Disassembler
 | 
			
		||||
pub fn disassemble(chunk: &Chunk, name: &str) {
 | 
			
		||||
    println!("== {} ==", name);
 | 
			
		||||
 | 
			
		||||
    for (idx, _) in chunk.code.iter().enumerate() {
 | 
			
		||||
        disassemble_instruction(chunk, idx);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Print a single disassembled instruction at the specified offset.
 | 
			
		||||
/// Some instructions are printed "raw", others have special handling.
 | 
			
		||||
fn disassemble_instruction(chunk: &Chunk, offset: usize) {
 | 
			
		||||
    print!("{:04} ", offset);
 | 
			
		||||
 | 
			
		||||
    match &chunk[offset] {
 | 
			
		||||
        OpCode::OpConstant(idx) => println!("OpConstant idx '{:?}'", chunk.constants[*idx]),
 | 
			
		||||
        op => println!("{:?}", op),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,19 @@
 | 
			
		|||
//!
 | 
			
		||||
//! https://craftinginterpreters.com/chunks-of-bytecode.html
 | 
			
		||||
 | 
			
		||||
mod chunk;
 | 
			
		||||
mod opcode;
 | 
			
		||||
mod value;
 | 
			
		||||
 | 
			
		||||
use chunk::Chunk;
 | 
			
		||||
use opcode::OpCode;
 | 
			
		||||
 | 
			
		||||
pub fn main() {
 | 
			
		||||
    unimplemented!()
 | 
			
		||||
    let mut chunk: Chunk = Default::default();
 | 
			
		||||
 | 
			
		||||
    let constant = chunk.add_constant(1.2);
 | 
			
		||||
    chunk.add_op(OpCode::OpConstant(constant));
 | 
			
		||||
    chunk.add_op(OpCode::OpReturn);
 | 
			
		||||
 | 
			
		||||
    chunk::disassemble(&chunk, "test chunk");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								users/tazjin/rlox/src/bytecode/opcode.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								users/tazjin/rlox/src/bytecode/opcode.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
#[derive(Debug)]
 | 
			
		||||
pub enum OpCode {
 | 
			
		||||
    /// Access a constant for use.
 | 
			
		||||
    OpConstant(usize),
 | 
			
		||||
 | 
			
		||||
    /// Return from the current function.
 | 
			
		||||
    OpReturn,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								users/tazjin/rlox/src/bytecode/value.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								users/tazjin/rlox/src/bytecode/value.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
pub type Value = f64;
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue