diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index 4e5fde9..6c29268 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -224,6 +224,21 @@ impl Instruction { } pub fn disassembly_info(&self, chunk: Option<&Chunk>) -> Option { + let format_arguments = || { + let first_argument = if self.first_argument_is_constant() { + format!("C({})", self.first_argument()) + } else { + format!("R({})", self.first_argument()) + }; + let second_argument = if self.second_argument_is_constant() { + format!("C({})", self.second_argument()) + } else { + format!("R({})", self.second_argument()) + }; + + (first_argument, second_argument) + }; + let info = match self.operation() { Operation::Move => { format!("R({}) = R({})", self.destination(), self.first_argument()) @@ -306,106 +321,43 @@ impl Instruction { } Operation::Add => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} + {second_argument}",) } Operation::Subtract => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} - {second_argument}",) } Operation::Multiply => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} * {second_argument}",) } Operation::Divide => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} / {second_argument}",) } Operation::Modulo => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} % {second_argument}",) } Operation::And => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} && {second_argument}",) } Operation::Or => { let destination = self.destination(); - let first_argument = if self.first_argument_is_constant() { - format!("C({})", self.first_argument()) - } else { - format!("R({})", self.first_argument()) - }; - let second_argument = if self.second_argument_is_constant() { - format!("C({})", self.second_argument()) - } else { - format!("R({})", self.second_argument()) - }; + let (first_argument, second_argument) = format_arguments(); format!("R({destination}) = {first_argument} || {second_argument}",) } diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index b460729..1e495a8 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -96,7 +96,7 @@ impl<'src> Parser<'src> { let (new_token, position) = self.lexer.next_token()?; - log::trace!("Parsing token \"{new_token}\" at {position}"); + log::trace!("Parsing \"{new_token}\" at {position}"); self.previous_token = replace(&mut self.current_token, new_token); self.previous_position = replace(&mut self.current_position, position); @@ -271,7 +271,7 @@ impl<'src> Parser<'src> { TokenKind::Minus => Instruction::negate(destination, from_register), _ => { return Err(ParseError::ExpectedTokenMultiple { - expected: &[TokenKind::Minus], + expected: &[TokenKind::Bang, TokenKind::Minus], found: operator.to_owned(), position: operator_position, }) @@ -356,6 +356,9 @@ impl<'src> Parser<'src> { TokenKind::Minus, TokenKind::Star, TokenKind::Slash, + TokenKind::Percent, + TokenKind::DoubleAmpersand, + TokenKind::DoublePipe, ], found: operator.to_owned(), position: operator_position, @@ -475,13 +478,14 @@ impl<'src> Parser<'src> { } fn parse_list(&mut self, _allow_assignment: bool) -> Result<(), ParseError> { + let start = self.current_position.0; + self.advance()?; - let start = self.current_position.0; let mut length = 0; while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() { - self.parse_expression()?; + self.parse(Precedence::Assignment)?; // Do not allow assignment length += 1; @@ -535,7 +539,14 @@ impl<'src> Parser<'src> { Ok(()) } - fn parse_let_statement(&mut self, _allow_assignment: bool) -> Result<(), ParseError> { + fn parse_let_statement(&mut self, allow_assignment: bool) -> Result<(), ParseError> { + if !allow_assignment { + return Err(ParseError::ExpectedExpression { + found: self.current_token.to_owned(), + position: self.current_position, + }); + } + self.advance()?; let position = self.current_position; @@ -587,7 +598,7 @@ impl<'src> Parser<'src> { if let Some(prefix_parser) = ParseRule::from(&self.current_token.kind()).prefix { log::trace!( - "Parsing {} as prefix with precedence {precedence}", + "Parsing \"{}\" with prefix parser at precedence {precedence}", self.current_token, ); @@ -599,7 +610,7 @@ impl<'src> Parser<'src> { while precedence <= infix_rule.precedence { if let Some(infix_parser) = infix_rule.infix { log::trace!( - "Parsing {} as infix with precedence {precedence}", + "Parsing \"{}\" with infix parser at precedence {precedence}", self.current_token, ); diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index efe678f..95c261b 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -35,6 +35,26 @@ impl Vm { } pub fn run(&mut self) -> Result, VmError> { + let take_constants_or_clone = |vm: &mut Vm, + instruction: Instruction, + position: Span| + -> Result<(Value, Value), VmError> { + let left = if instruction.first_argument_is_constant() { + vm.chunk + .take_constant(instruction.first_argument(), position)? + } else { + vm.clone(instruction.first_argument(), position)? + }; + let right = if instruction.second_argument_is_constant() { + vm.chunk + .take_constant(instruction.second_argument(), position)? + } else { + vm.clone(instruction.second_argument(), position)? + }; + + Ok((left, right)) + }; + while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() { log::trace!("Running instruction {instruction} at {position}"); @@ -98,16 +118,7 @@ impl Vm { self.chunk.define_local(to_local, from_register, position)?; } Operation::Add => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let sum = left .add(&right) .map_err(|error| VmError::Value { error, position })?; @@ -115,16 +126,7 @@ impl Vm { self.insert(sum, instruction.destination(), position)?; } Operation::Subtract => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let difference = left .subtract(&right) .map_err(|error| VmError::Value { error, position })?; @@ -132,16 +134,7 @@ impl Vm { self.insert(difference, instruction.destination(), position)?; } Operation::Multiply => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let product = left .multiply(&right) .map_err(|error| VmError::Value { error, position })?; @@ -149,16 +142,7 @@ impl Vm { self.insert(product, instruction.destination(), position)?; } Operation::Divide => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let quotient = left .divide(&right) .map_err(|error| VmError::Value { error, position })?; @@ -166,16 +150,7 @@ impl Vm { self.insert(quotient, instruction.destination(), position)?; } Operation::Modulo => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let remainder = left .modulo(&right) .map_err(|error| VmError::Value { error, position })?; @@ -183,16 +158,7 @@ impl Vm { self.insert(remainder, instruction.destination(), position)?; } Operation::And => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let result = left .and(&right) .map_err(|error| VmError::Value { error, position })?; @@ -200,16 +166,7 @@ impl Vm { self.insert(result, instruction.destination(), position)?; } Operation::Or => { - let left = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; - let right = self.take_constant_or_clone_register( - instruction.second_argument(), - instruction.second_argument_is_constant(), - position, - )?; + let (left, right) = take_constants_or_clone(self, instruction, position)?; let result = left .or(&right) .map_err(|error| VmError::Value { error, position })?; @@ -217,11 +174,12 @@ impl Vm { self.insert(result, instruction.destination(), position)?; } Operation::Negate => { - let value = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; + let value = if instruction.first_argument_is_constant() { + self.chunk + .take_constant(instruction.first_argument(), position)? + } else { + self.clone(instruction.first_argument(), position)? + }; let negated = value .negate() .map_err(|error| VmError::Value { error, position })?; @@ -229,11 +187,12 @@ impl Vm { self.insert(negated, instruction.destination(), position)?; } Operation::Not => { - let value = self.take_constant_or_clone_register( - instruction.first_argument(), - instruction.first_argument_is_constant(), - position, - )?; + let value = if instruction.first_argument_is_constant() { + self.chunk + .take_constant(instruction.first_argument(), position)? + } else { + self.clone(instruction.first_argument(), position)? + }; let result = value .not() .map_err(|error| VmError::Value { error, position })?; @@ -289,19 +248,6 @@ impl Vm { } } - fn take_constant_or_clone_register( - &mut self, - index: u8, - is_constant: bool, - position: Span, - ) -> Result { - if is_constant { - Ok(self.chunk.take_constant(index, position)?) - } else { - self.clone(index, position) - } - } - fn pop(&mut self, position: Span) -> Result { if let Some(register) = self.register_stack.pop() { let value = register.ok_or(VmError::EmptyRegister {