refactor(tazjin/rlox): Introduce newtypes for various indices
Since this code is essentially a fairly plain translation from C, it is a bit confusing to deal with the original untyped code. This is an attempt to try and clean some of it up. Change-Id: Icd21f531932e1a811c0d6dbf2e9acba61ca9c45d Reviewed-on: https://cl.tvl.fyi/c/depot/+/3734 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
		
							parent
							
								
									e92a951f6c
								
							
						
					
					
						commit
						050a2b473c
					
				
					 4 changed files with 31 additions and 25 deletions
				
			
		|  | @ -1,6 +1,6 @@ | |||
| use std::ops::Index; | ||||
| 
 | ||||
| use super::opcode::OpCode; | ||||
| use super::opcode::{ConstantIdx, OpCode}; | ||||
| use super::value; | ||||
| 
 | ||||
| // In the book, this type is a hand-rolled dynamic array
 | ||||
|  | @ -38,8 +38,8 @@ impl Chunk { | |||
|         idx | ||||
|     } | ||||
| 
 | ||||
|     pub fn constant(&self, idx: usize) -> &value::Value { | ||||
|         self.constants.index(idx) | ||||
|     pub fn constant(&self, idx: ConstantIdx) -> &value::Value { | ||||
|         self.constants.index(idx.0) | ||||
|     } | ||||
| 
 | ||||
|     fn add_line(&mut self, line: usize) { | ||||
|  | @ -79,7 +79,7 @@ pub fn disassemble_instruction(chunk: &Chunk, offset: usize) { | |||
| 
 | ||||
|     match chunk.code.index(offset) { | ||||
|         OpCode::OpConstant(idx) => { | ||||
|             println!("OpConstant({}) '{:?}'", *idx, chunk.constant(*idx)) | ||||
|             println!("OpConstant({:?}) '{:?}'", idx, chunk.constant(*idx)) | ||||
|         } | ||||
|         op => println!("{:?}", op), | ||||
|     } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| use super::chunk::Chunk; | ||||
| use super::errors::{Error, ErrorKind, LoxResult}; | ||||
| use super::interner::{InternedStr, Interner}; | ||||
| use super::opcode::OpCode; | ||||
| use super::opcode::{ConstantIdx, OpCode, StackIdx}; | ||||
| use super::value::Value; | ||||
| use crate::scanner::{self, Token, TokenKind}; | ||||
| 
 | ||||
|  | @ -234,7 +234,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
|         self.define_variable(global) | ||||
|     } | ||||
| 
 | ||||
|     fn define_variable(&mut self, var: usize) -> LoxResult<()> { | ||||
|     fn define_variable(&mut self, var: ConstantIdx) -> LoxResult<()> { | ||||
|         if self.locals.scope_depth == 0 { | ||||
|             self.emit_op(OpCode::OpDefineGlobal(var)); | ||||
|         } else { | ||||
|  | @ -493,12 +493,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
|         Ok(self.strings.intern(ident)) | ||||
|     } | ||||
| 
 | ||||
|     fn identifier_constant(&mut self) -> LoxResult<usize> { | ||||
|     fn identifier_constant(&mut self) -> LoxResult<ConstantIdx> { | ||||
|         let ident = self.identifier_str(Self::previous)?; | ||||
|         Ok(self.emit_constant(Value::String(ident.into()), false)) | ||||
|     } | ||||
| 
 | ||||
|     fn resolve_local(&mut self) -> Option<usize> { | ||||
|     fn resolve_local(&mut self) -> Option<StackIdx> { | ||||
|         dbg!(&self.locals); | ||||
|         for (idx, local) in self.locals.locals.iter().enumerate().rev() { | ||||
|             if self.previous().lexeme == local.name.lexeme { | ||||
|  | @ -506,21 +506,20 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
|                     // TODO(tazjin): *return* err
 | ||||
|                     panic!("can't read variable in its own initialiser"); | ||||
|                 } | ||||
|                 return Some(idx); | ||||
|                 return Some(StackIdx(idx)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     fn add_local(&mut self, name: Token) -> LoxResult<()> { | ||||
|     fn add_local(&mut self, name: Token) { | ||||
|         let local = Local { | ||||
|             name, | ||||
|             depth: Depth::Unitialised, | ||||
|         }; | ||||
| 
 | ||||
|         self.locals.locals.push(local); | ||||
|         Ok(()) // TODO(tazjin): needed?
 | ||||
|     } | ||||
| 
 | ||||
|     fn declare_variable(&mut self) -> LoxResult<()> { | ||||
|  | @ -543,10 +542,11 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         self.add_local(name) | ||||
|         self.add_local(name); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_variable(&mut self) -> LoxResult<usize> { | ||||
|     fn parse_variable(&mut self) -> LoxResult<ConstantIdx> { | ||||
|         consume!( | ||||
|             self, | ||||
|             TokenKind::Identifier(_), | ||||
|  | @ -555,7 +555,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
| 
 | ||||
|         self.declare_variable()?; | ||||
|         if self.locals.scope_depth > 0 { | ||||
|             return Ok(0); // TODO(tazjin): grr sentinel
 | ||||
|             return Ok(ConstantIdx(0)); // TODO(tazjin): grr sentinel
 | ||||
|         } | ||||
| 
 | ||||
|         let id = self.identifier_str(Self::previous)?; | ||||
|  | @ -583,8 +583,8 @@ impl<T: Iterator<Item = Token>> Compiler<T> { | |||
|         self.current_chunk().add_op(op, line); | ||||
|     } | ||||
| 
 | ||||
|     fn emit_constant(&mut self, val: Value, with_op: bool) -> usize { | ||||
|         let idx = self.chunk.add_constant(val); | ||||
|     fn emit_constant(&mut self, val: Value, with_op: bool) -> ConstantIdx { | ||||
|         let idx = ConstantIdx(self.chunk.add_constant(val)); | ||||
| 
 | ||||
|         if with_op { | ||||
|             self.emit_op(OpCode::OpConstant(idx)); | ||||
|  |  | |||
|  | @ -1,7 +1,13 @@ | |||
| #[derive(Clone, Copy, Debug)] | ||||
| pub struct ConstantIdx(pub usize); | ||||
| 
 | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| pub struct StackIdx(pub usize); | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum OpCode { | ||||
|     /// Push a constant onto the stack.
 | ||||
|     OpConstant(usize), | ||||
|     OpConstant(ConstantIdx), | ||||
| 
 | ||||
|     // Literal pushes
 | ||||
|     OpNil, | ||||
|  | @ -31,9 +37,9 @@ pub enum OpCode { | |||
|     OpPop, | ||||
| 
 | ||||
|     // Variable management
 | ||||
|     OpDefineGlobal(usize), | ||||
|     OpGetGlobal(usize), | ||||
|     OpSetGlobal(usize), | ||||
|     OpGetLocal(usize), | ||||
|     OpSetLocal(usize), | ||||
|     OpDefineGlobal(ConstantIdx), | ||||
|     OpGetGlobal(ConstantIdx), | ||||
|     OpSetGlobal(ConstantIdx), | ||||
|     OpGetLocal(StackIdx), | ||||
|     OpSetLocal(StackIdx), | ||||
| } | ||||
|  |  | |||
|  | @ -196,13 +196,13 @@ impl VM { | |||
|                 } | ||||
| 
 | ||||
|                 OpCode::OpGetLocal(local_idx) => { | ||||
|                     let value = self.stack[*local_idx].clone(); | ||||
|                     let value = self.stack[local_idx.0].clone(); | ||||
|                     self.push(value); | ||||
|                 } | ||||
| 
 | ||||
|                 OpCode::OpSetLocal(local_idx) => { | ||||
|                     debug_assert!(self.stack.len() > *local_idx, "stack is not currently large enough for local"); | ||||
|                     self.stack[*local_idx] = self.stack.last().unwrap().clone(); | ||||
|                     debug_assert!(self.stack.len() > local_idx.0, "stack is not currently large enough for local"); | ||||
|                     self.stack[local_idx.0] = self.stack.last().unwrap().clone(); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue