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