Pass tests

This commit is contained in:
Jeff 2024-09-17 12:08:40 -04:00
parent 71a4f863e3
commit fd4ffeec7c
2 changed files with 71 additions and 57 deletions

View File

@ -498,7 +498,8 @@ impl AnnotatedError for ChunkError {
ChunkError::IdentifierNotFound { identifier, .. } => { ChunkError::IdentifierNotFound { identifier, .. } => {
Some(format!("Identifier: {}", 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::ConstantAlreadyUsed { position, .. } => *position,
ChunkError::ConstantIndexOutOfBounds { position, .. } => *position, ChunkError::ConstantIndexOutOfBounds { position, .. } => *position,
ChunkError::IdentifierNotFound { position, .. } => *position, ChunkError::IdentifierNotFound { position, .. } => *position,
_ => todo!(), ChunkError::InstructionUnderflow { position, .. } => *position,
ChunkError::LocalIndexOutOfBounds { position, .. } => *position,
ChunkError::IdentifierOverflow { position, .. } => *position,
ChunkError::ConstantOverflow { position, .. } => *position,
} }
} }
} }

View File

@ -223,7 +223,12 @@ impl<'src> Parser<'src> {
fn parse_grouped(&mut self, _allow_assignment: bool) -> Result<(), ParseError> { fn parse_grouped(&mut self, _allow_assignment: bool) -> Result<(), ParseError> {
self.parse_expression()?; 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> { 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> { 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) = let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?; self.chunk.pop_instruction(self.current_position)?;
let mut push_back_left = false; let mut push_back_left = false;
let mut left_is_constant = false; let mut left_is_constant = false;
let left = match left_instruction.operation() { let left = match left_instruction.operation() {
@ -272,48 +309,17 @@ impl<'src> Parser<'src> {
} }
}; };
if push_back_left { let destination = if left_is_constant && right_is_constant {
self.emit_instruction(left_instruction, left_position); self.current_register.saturating_sub(1)
} } else {
self.current_register
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
}
}; };
if push_back_right {
self.emit_instruction(right_instruction, right_position);
}
let mut instruction = match operator { let mut instruction = match operator {
TokenKind::Plus => Instruction::add(self.current_register, left, right), TokenKind::Plus => Instruction::add(destination, left, right),
TokenKind::Minus => Instruction::subtract(self.current_register, left, right), TokenKind::Minus => Instruction::subtract(destination, left, right),
TokenKind::Star => Instruction::multiply(self.current_register, left, right), TokenKind::Star => Instruction::multiply(destination, left, right),
TokenKind::Slash => Instruction::divide(self.current_register, left, right), TokenKind::Slash => Instruction::divide(destination, left, right),
_ => { _ => {
return Err(ParseError::ExpectedTokenMultiple { return Err(ParseError::ExpectedTokenMultiple {
expected: vec![ expected: vec![
@ -336,8 +342,16 @@ impl<'src> Parser<'src> {
instruction.set_second_argument_to_constant(); 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.emit_instruction(instruction, operator_position);
self.increment_register()?;
Ok(()) Ok(())
} }
@ -457,7 +471,7 @@ impl<'src> Parser<'src> {
(true, false) (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 { if is_expression_statement && !contains_block && !has_semicolon {
let end = self.previous_position.1; let end = self.previous_position.1;
@ -524,8 +538,8 @@ impl<'src> Parser<'src> {
prefix prefix
} else { } else {
return Err(ParseError::ExpectedExpression { return Err(ParseError::ExpectedExpression {
found: self.previous_token.to_owned(), found: self.current_token.to_owned(),
position: self.previous_position, position: self.current_position,
}); });
}; };
let allow_assignment = precedence < Precedence::Assignment; let allow_assignment = precedence < Precedence::Assignment;
@ -533,12 +547,10 @@ impl<'src> Parser<'src> {
self.advance()?; self.advance()?;
prefix_parser(self, allow_assignment)?; prefix_parser(self, allow_assignment)?;
let mut infix_rule = ParseRule::from(&self.current_token.kind()); while precedence <= ParseRule::from(&self.current_token.kind()).precedence {
while precedence < infix_rule.precedence {
self.advance()?; self.advance()?;
if let Some(infix_parser) = infix_rule.infix { if let Some(infix_parser) = ParseRule::from(&self.previous_token.kind()).infix {
log::trace!( log::trace!(
"Parsing {} as infix with precedence {precedence}", "Parsing {} as infix with precedence {precedence}",
self.previous_token, self.previous_token,
@ -555,8 +567,6 @@ impl<'src> Parser<'src> {
} else { } else {
break; break;
} }
infix_rule = ParseRule::from(&self.current_token.kind());
} }
Ok(()) Ok(())
@ -811,10 +821,10 @@ impl AnnotatedError for ParseError {
Self::UndefinedVariable { .. } => "Undefined variable", Self::UndefinedVariable { .. } => "Undefined variable",
Self::RegisterOverflow { .. } => "Register overflow", Self::RegisterOverflow { .. } => "Register overflow",
Self::RegisterUnderflow { .. } => "Register underflow", Self::RegisterUnderflow { .. } => "Register underflow",
Self::Chunk { .. } => "Chunk error",
Self::Lex(_) => "Lex error",
Self::ParseFloatError { .. } => "Failed to parse float", Self::ParseFloatError { .. } => "Failed to parse float",
Self::ParseIntError { .. } => "Failed to parse integer", 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::RegisterOverflow { .. } => None,
Self::RegisterUnderflow { .. } => None, Self::RegisterUnderflow { .. } => None,
Self::Chunk(error) => error.details(),
Self::Lex(error) => error.details(),
Self::ParseFloatError { error, .. } => Some(error.to_string()), Self::ParseFloatError { error, .. } => Some(error.to_string()),
Self::ParseIntError { error, .. } => Some(error.to_string()), Self::ParseIntError { error, .. } => Some(error.to_string()),
Self::Chunk(error) => error.details(),
Self::Lex(error) => error.details(),
} }
} }