diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index d36a728..40b27cb 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -1,7 +1,4 @@ -use std::{ - fmt::{self, Debug, Display, Formatter}, - rc::Weak, -}; +use std::fmt::{self, Debug, Display, Formatter}; use serde::{Deserialize, Serialize}; @@ -43,17 +40,13 @@ impl Chunk { self.code.is_empty() } - pub fn capacity(&self) -> usize { - self.code.capacity() - } - - pub fn read(&self, offset: usize) -> Result<&(u8, Span), ChunkError> { + pub fn get_code(&self, offset: usize) -> Result<&(u8, Span), ChunkError> { self.code .get(offset) .ok_or(ChunkError::CodeIndextOfBounds(offset)) } - pub fn write(&mut self, instruction: u8, position: Span) { + pub fn push_code(&mut self, instruction: u8, position: Span) { self.code.push((instruction, position)); } @@ -123,7 +116,7 @@ impl Chunk { for (offset, (byte, position)) in self.code.iter().enumerate() { if let Some(Instruction::Constant) = previous { let display = format!("{offset:04} CONSTANT_INDEX {byte}"); - let display_with_postion = format!("{display:26} {position}\n"); + let display_with_postion = format!("{display:27} {position}\n"); previous = None; output.push_str(&display_with_postion); @@ -136,7 +129,7 @@ impl Chunk { ) = previous { let display = format!("{offset:04} IDENTIFIER_INDEX {byte}"); - let display_with_postion = format!("{display:26} {position}\n"); + let display_with_postion = format!("{display:27} {position}\n"); previous = None; @@ -147,7 +140,7 @@ impl Chunk { let instruction = Instruction::from_byte(*byte).unwrap(); let display = format!("{offset:04} {}", instruction.disassemble(self, offset)); - let display_with_postion = format!("{display:26} {position}\n"); + let display_with_postion = format!("{display:27} {position}\n"); previous = Some(instruction); diff --git a/dust-lang/src/identifier_stack.rs b/dust-lang/src/identifier_stack.rs index 4f717d1..d7d0504 100644 --- a/dust-lang/src/identifier_stack.rs +++ b/dust-lang/src/identifier_stack.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::Identifier; -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct IdentifierStack { locals: Vec, scope_depth: usize, @@ -44,11 +44,20 @@ impl IdentifierStack { } pub fn get_index(&self, identifier: &Identifier) -> Option { - self.locals - .iter() - .rev() - .position(|local| &local.identifier == identifier) - .map(|index| index as u8) + self.locals.iter().enumerate().rev().find_map( + |( + index, + Local { + identifier: local, .. + }, + )| { + if local == identifier { + Some(index as u8) + } else { + None + } + }, + ) } pub fn begin_scope(&mut self) { @@ -77,6 +86,14 @@ impl Default for IdentifierStack { } } +impl Eq for IdentifierStack {} + +impl PartialEq for IdentifierStack { + fn eq(&self, other: &Self) -> bool { + self.locals == other.locals + } +} + #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct Local { pub identifier: Identifier, diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 71d1a3f..df83045 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -54,6 +54,10 @@ impl<'src> Parser<'src> { } fn advance(&mut self) -> Result<(), ParseError> { + if self.is_eof() { + return Ok(()); + } + let (new_token, position) = self.lexer.next_token()?; log::trace!("Advancing to token {new_token} at {position}"); @@ -87,7 +91,7 @@ impl<'src> Parser<'src> { } fn emit_byte(&mut self, byte: u8, position: Span) { - self.chunk.write(byte, position); + self.chunk.push_code(byte, position); } fn emit_constant(&mut self, value: Value) -> Result<(), ParseError> { @@ -168,6 +172,8 @@ impl<'src> Parser<'src> { } fn parse_binary(&mut self) -> Result<(), ParseError> { + log::trace!("Parsing binary expression"); + let operator_position = self.previous_position; let operator = self.previous_token.kind(); let rule = ParseRule::from(&operator); @@ -199,14 +205,11 @@ impl<'src> Parser<'src> { } fn parse_variable(&mut self, allow_assignment: bool) -> Result<(), ParseError> { - self.parse_named_variable_from(self.previous_token.to_owned(), allow_assignment) + self.parse_named_variable_from(allow_assignment) } - fn parse_named_variable_from( - &mut self, - token: TokenOwned, - allow_assignment: bool, - ) -> Result<(), ParseError> { + fn parse_named_variable_from(&mut self, allow_assignment: bool) -> Result<(), ParseError> { + let token = self.previous_token.to_owned(); let identifier_index = self.parse_identifier_from(token)?; if allow_assignment && self.allow(TokenKind::Equal)? { @@ -223,8 +226,6 @@ impl<'src> Parser<'src> { fn parse_identifier_from(&mut self, token: TokenOwned) -> Result { if let TokenOwned::Identifier(text) = token { - self.advance()?; - let identifier = Identifier::new(text); let identifier_index = self.chunk.get_identifier_index(&identifier)?; @@ -564,30 +565,26 @@ mod tests { #[test] fn add_variables() { - let source = " - let x = 42; - let y = 42; - x + y - "; + let source = "let x = 42; let y = 42; x + y"; let test_chunk = parse(source); assert_eq!( test_chunk, Ok(Chunk::with_data( vec![ - (Instruction::Constant as u8, Span(21, 23)), - (0, Span(21, 23)), - (Instruction::DefineVariable as u8, Span(17, 18)), - (0, Span(17, 18)), - (Instruction::Constant as u8, Span(44, 46)), - (1, Span(44, 46)), - (Instruction::DefineVariable as u8, Span(40, 41)), - (1, Span(40, 41)), - (Instruction::GetVariable as u8, Span(61, 62)), - (0, Span(61, 62)), - (Instruction::GetVariable as u8, Span(52, 53)), - (1, Span(52, 53)), - (Instruction::Add as u8, Span(48, 53)) + (Instruction::DefineVariable as u8, Span(4, 5)), + (0, Span(4, 5)), + (Instruction::Constant as u8, Span(8, 10)), + (0, Span(8, 10)), + (Instruction::DefineVariable as u8, Span(16, 17)), + (1, Span(16, 17)), + (Instruction::Constant as u8, Span(20, 22)), + (1, Span(20, 22)), + (Instruction::GetVariable as u8, Span(24, 25)), + (0, Span(24, 25)), + (Instruction::GetVariable as u8, Span(28, 29)), + (1, Span(28, 29)), + (Instruction::Add as u8, Span(26, 27)) ], vec![Value::integer(42), Value::integer(42)], vec![ @@ -599,14 +596,6 @@ mod tests { identifier: Identifier::new("y"), depth: 0 }, - Local { - identifier: Identifier::new("x"), - depth: 0 - }, - Local { - identifier: Identifier::new("y"), - depth: 0 - }, ], )) ); diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 4bafa2f..8ae8063 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -193,7 +193,7 @@ impl Vm { } fn read(&mut self) -> Result<&(u8, Span), VmError> { - let current = self.chunk.read(self.ip)?; + let current = self.chunk.get_code(self.ip)?; self.ip += 1; @@ -289,21 +289,21 @@ impl Instruction { pub fn disassemble(&self, chunk: &Chunk, offset: usize) -> String { match self { Instruction::Constant => { - let (index_display, value_display) = if let Ok((index, _)) = chunk.read(offset + 1) - { - let index_string = index.to_string(); - let value_string = chunk - .get_constant(*index) - .map(|value| value.to_string()) - .unwrap_or_else(|error| format!("{:?}", error)); + let (index_display, value_display) = + if let Ok((index, _)) = chunk.get_code(offset + 1) { + let index_string = index.to_string(); + let value_string = chunk + .get_constant(*index) + .map(|value| value.to_string()) + .unwrap_or_else(|error| format!("{:?}", error)); - (index_string, value_string) - } else { - let index = "ERROR".to_string(); - let value = "ERROR".to_string(); + (index_string, value_string) + } else { + let index = "ERROR".to_string(); + let value = "ERROR".to_string(); - (index, value) - }; + (index, value) + }; format!("CONSTANT {index_display} {value_display}") } @@ -312,7 +312,7 @@ impl Instruction { // Variables Instruction::DefineVariable => { - let (index, _) = chunk.read(offset + 1).unwrap(); + let (index, _) = chunk.get_code(offset + 1).unwrap(); let identifier_display = match chunk.get_identifier(*index) { Ok(identifier) => identifier.to_string(), Err(error) => format!("{:?}", error), @@ -321,7 +321,7 @@ impl Instruction { format!("DEFINE_VARIABLE {identifier_display} {index}") } Instruction::GetVariable => { - let (index, _) = chunk.read(offset + 1).unwrap(); + let (index, _) = chunk.get_code(offset + 1).unwrap(); let identifier_display = match chunk.get_identifier(*index) { Ok(identifier) => identifier.to_string(), Err(error) => format!("{:?}", error), @@ -331,7 +331,7 @@ impl Instruction { } Instruction::SetVariable => { - let (index, _) = chunk.read(offset + 1).unwrap(); + let (index, _) = chunk.get_code(offset + 1).unwrap(); let identifier_display = match chunk.get_identifier(*index) { Ok(identifier) => identifier.to_string(), Err(error) => format!("{:?}", error), @@ -376,10 +376,10 @@ pub mod tests { let mut chunk = Chunk::new(); let constant = chunk.push_constant(Value::integer(42)).unwrap(); - chunk.write(Instruction::Constant as u8, Span(0, 1)); - chunk.write(constant, Span(2, 3)); - chunk.write(Instruction::Negate as u8, Span(4, 5)); - chunk.write(Instruction::Return as u8, Span(2, 3)); + chunk.push_code(Instruction::Constant as u8, Span(0, 1)); + chunk.push_code(constant, Span(2, 3)); + chunk.push_code(Instruction::Negate as u8, Span(4, 5)); + chunk.push_code(Instruction::Return as u8, Span(2, 3)); let mut vm = Vm::new(chunk); let result = vm.run(); @@ -393,12 +393,12 @@ pub mod tests { let left = chunk.push_constant(Value::integer(42)).unwrap(); let right = chunk.push_constant(Value::integer(23)).unwrap(); - chunk.write(Instruction::Constant as u8, Span(0, 1)); - chunk.write(left, Span(2, 3)); - chunk.write(Instruction::Constant as u8, Span(4, 5)); - chunk.write(right, Span(6, 7)); - chunk.write(Instruction::Add as u8, Span(8, 9)); - chunk.write(Instruction::Return as u8, Span(10, 11)); + chunk.push_code(Instruction::Constant as u8, Span(0, 1)); + chunk.push_code(left, Span(2, 3)); + chunk.push_code(Instruction::Constant as u8, Span(4, 5)); + chunk.push_code(right, Span(6, 7)); + chunk.push_code(Instruction::Add as u8, Span(8, 9)); + chunk.push_code(Instruction::Return as u8, Span(10, 11)); let mut vm = Vm::new(chunk); let result = vm.run(); @@ -412,12 +412,12 @@ pub mod tests { let left = chunk.push_constant(Value::integer(42)).unwrap(); let right = chunk.push_constant(Value::integer(23)).unwrap(); - chunk.write(Instruction::Constant as u8, Span(0, 1)); - chunk.write(left, Span(2, 3)); - chunk.write(Instruction::Constant as u8, Span(4, 5)); - chunk.write(right, Span(6, 7)); - chunk.write(Instruction::Subtract as u8, Span(8, 9)); - chunk.write(Instruction::Return as u8, Span(10, 11)); + chunk.push_code(Instruction::Constant as u8, Span(0, 1)); + chunk.push_code(left, Span(2, 3)); + chunk.push_code(Instruction::Constant as u8, Span(4, 5)); + chunk.push_code(right, Span(6, 7)); + chunk.push_code(Instruction::Subtract as u8, Span(8, 9)); + chunk.push_code(Instruction::Return as u8, Span(10, 11)); let mut vm = Vm::new(chunk); let result = vm.run(); @@ -431,12 +431,12 @@ pub mod tests { let left = chunk.push_constant(Value::integer(42)).unwrap(); let right = chunk.push_constant(Value::integer(23)).unwrap(); - chunk.write(Instruction::Constant as u8, Span(0, 1)); - chunk.write(left, Span(2, 3)); - chunk.write(Instruction::Constant as u8, Span(4, 5)); - chunk.write(right, Span(6, 7)); - chunk.write(Instruction::Multiply as u8, Span(8, 9)); - chunk.write(Instruction::Return as u8, Span(10, 11)); + chunk.push_code(Instruction::Constant as u8, Span(0, 1)); + chunk.push_code(left, Span(2, 3)); + chunk.push_code(Instruction::Constant as u8, Span(4, 5)); + chunk.push_code(right, Span(6, 7)); + chunk.push_code(Instruction::Multiply as u8, Span(8, 9)); + chunk.push_code(Instruction::Return as u8, Span(10, 11)); let mut vm = Vm::new(chunk); let result = vm.run(); @@ -451,12 +451,12 @@ pub mod tests { let left = chunk.push_constant(Value::integer(42)).unwrap(); let right = chunk.push_constant(Value::integer(23)).unwrap(); - chunk.write(Instruction::Constant as u8, Span(0, 1)); - chunk.write(left, Span(2, 3)); - chunk.write(Instruction::Constant as u8, Span(4, 5)); - chunk.write(right, Span(6, 7)); - chunk.write(Instruction::Divide as u8, Span(8, 9)); - chunk.write(Instruction::Return as u8, Span(10, 11)); + chunk.push_code(Instruction::Constant as u8, Span(0, 1)); + chunk.push_code(left, Span(2, 3)); + chunk.push_code(Instruction::Constant as u8, Span(4, 5)); + chunk.push_code(right, Span(6, 7)); + chunk.push_code(Instruction::Divide as u8, Span(8, 9)); + chunk.push_code(Instruction::Return as u8, Span(10, 11)); let mut vm = Vm::new(chunk); let result = vm.run();