From fd4ffeec7cf429eff9f65f9a5621af099fecdc36 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 17 Sep 2024 12:08:40 -0400 Subject: [PATCH] Pass tests --- dust-lang/src/chunk.rs | 8 ++- dust-lang/src/parser/mod.rs | 120 +++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index d7863a3..bf6c22a 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -498,7 +498,8 @@ impl AnnotatedError for ChunkError { ChunkError::IdentifierNotFound { identifier, .. } => { Some(format!("Identifier: {}", identifier)) } - _ => None, + ChunkError::IdentifierOverflow { .. } => Some("Identifier overflow".to_string()), + ChunkError::ConstantOverflow { .. } => Some("Constant overflow".to_string()), } } @@ -508,7 +509,10 @@ impl AnnotatedError for ChunkError { ChunkError::ConstantAlreadyUsed { position, .. } => *position, ChunkError::ConstantIndexOutOfBounds { position, .. } => *position, ChunkError::IdentifierNotFound { position, .. } => *position, - _ => todo!(), + ChunkError::InstructionUnderflow { position, .. } => *position, + ChunkError::LocalIndexOutOfBounds { position, .. } => *position, + ChunkError::IdentifierOverflow { position, .. } => *position, + ChunkError::ConstantOverflow { position, .. } => *position, } } } diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index 396921a..8e7d374 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -223,7 +223,12 @@ impl<'src> Parser<'src> { fn parse_grouped(&mut self, _allow_assignment: bool) -> Result<(), ParseError> { self.parse_expression()?; - self.expect(TokenKind::RightParenthesis) + + if self.previous_token == Token::RightParenthesis { + Ok(()) + } else { + self.expect(TokenKind::RightParenthesis) + } } fn parse_unary(&mut self, _allow_assignment: bool) -> Result<(), ParseError> { @@ -249,9 +254,41 @@ impl<'src> Parser<'src> { } fn parse_binary(&mut self) -> Result<(), ParseError> { + let operator_position = self.previous_position; + let operator = self.previous_token.kind(); + let rule = ParseRule::from(&operator); + + self.parse(rule.precedence.increment())?; + + let (right_instruction, right_position) = + self.chunk.pop_instruction(self.current_position)?; + let mut push_back_right = false; + let mut right_is_constant = false; + let right = match right_instruction.operation() { + Operation::LoadConstant => { + right_is_constant = true; + + self.decrement_register()?; + right_instruction.first_argument() + } + Operation::GetLocal => { + self.decrement_register()?; + right_instruction.first_argument() + } + operation if operation.is_binary() => { + push_back_right = true; + + self.current_register - 2 + } + _ => { + push_back_right = true; + + self.current_register - 1 + } + }; + let (left_instruction, left_position) = self.chunk.pop_instruction(self.current_position)?; - let mut push_back_left = false; let mut left_is_constant = false; let left = match left_instruction.operation() { @@ -272,48 +309,17 @@ impl<'src> Parser<'src> { } }; - if push_back_left { - self.emit_instruction(left_instruction, left_position); - } - - let operator_position = self.previous_position; - let operator = self.previous_token.kind(); - let rule = ParseRule::from(&operator); - - self.parse(rule.precedence)?; - - let (right_instruction, right_position) = - self.chunk.pop_instruction(self.current_position)?; - - let mut push_back_right = false; - let mut right_is_constant = false; - let right = match right_instruction.operation() { - Operation::LoadConstant => { - right_is_constant = true; - - self.decrement_register()?; - right_instruction.first_argument() - } - Operation::GetLocal => { - self.decrement_register()?; - right_instruction.first_argument() - } - _ => { - push_back_right = true; - - self.current_register - 1 - } + let destination = if left_is_constant && right_is_constant { + self.current_register.saturating_sub(1) + } else { + self.current_register }; - if push_back_right { - self.emit_instruction(right_instruction, right_position); - } - let mut instruction = match operator { - TokenKind::Plus => Instruction::add(self.current_register, left, right), - TokenKind::Minus => Instruction::subtract(self.current_register, left, right), - TokenKind::Star => Instruction::multiply(self.current_register, left, right), - TokenKind::Slash => Instruction::divide(self.current_register, left, right), + TokenKind::Plus => Instruction::add(destination, left, right), + TokenKind::Minus => Instruction::subtract(destination, left, right), + TokenKind::Star => Instruction::multiply(destination, left, right), + TokenKind::Slash => Instruction::divide(destination, left, right), _ => { return Err(ParseError::ExpectedTokenMultiple { expected: vec![ @@ -336,8 +342,16 @@ impl<'src> Parser<'src> { instruction.set_second_argument_to_constant(); } - self.increment_register()?; + if push_back_right { + self.emit_instruction(right_instruction, right_position); + } + + if push_back_left { + self.emit_instruction(left_instruction, left_position); + } + self.emit_instruction(instruction, operator_position); + self.increment_register()?; Ok(()) } @@ -457,7 +471,7 @@ impl<'src> Parser<'src> { (true, false) } }; - let has_semicolon = self.allow(TokenKind::Semicolon)?; + let has_semicolon = self.previous_token == Token::Semicolon; if is_expression_statement && !contains_block && !has_semicolon { let end = self.previous_position.1; @@ -524,8 +538,8 @@ impl<'src> Parser<'src> { prefix } else { return Err(ParseError::ExpectedExpression { - found: self.previous_token.to_owned(), - position: self.previous_position, + found: self.current_token.to_owned(), + position: self.current_position, }); }; let allow_assignment = precedence < Precedence::Assignment; @@ -533,12 +547,10 @@ impl<'src> Parser<'src> { self.advance()?; prefix_parser(self, allow_assignment)?; - let mut infix_rule = ParseRule::from(&self.current_token.kind()); - - while precedence < infix_rule.precedence { + while precedence <= ParseRule::from(&self.current_token.kind()).precedence { self.advance()?; - if let Some(infix_parser) = infix_rule.infix { + if let Some(infix_parser) = ParseRule::from(&self.previous_token.kind()).infix { log::trace!( "Parsing {} as infix with precedence {precedence}", self.previous_token, @@ -555,8 +567,6 @@ impl<'src> Parser<'src> { } else { break; } - - infix_rule = ParseRule::from(&self.current_token.kind()); } Ok(()) @@ -811,10 +821,10 @@ impl AnnotatedError for ParseError { Self::UndefinedVariable { .. } => "Undefined variable", Self::RegisterOverflow { .. } => "Register overflow", Self::RegisterUnderflow { .. } => "Register underflow", - Self::Chunk { .. } => "Chunk error", - Self::Lex(_) => "Lex error", Self::ParseFloatError { .. } => "Failed to parse float", Self::ParseIntError { .. } => "Failed to parse integer", + Self::Chunk(error) => error.description(), + Self::Lex(error) => error.description(), } } @@ -835,10 +845,10 @@ impl AnnotatedError for ParseError { } Self::RegisterOverflow { .. } => None, Self::RegisterUnderflow { .. } => None, - Self::Chunk(error) => error.details(), - Self::Lex(error) => error.details(), Self::ParseFloatError { error, .. } => Some(error.to_string()), Self::ParseIntError { error, .. } => Some(error.to_string()), + Self::Chunk(error) => error.details(), + Self::Lex(error) => error.details(), } }