Refactor to fix bugs with loops; Add close instructions while calling functions
This commit is contained in:
parent
13b4cfffcc
commit
f15cf84c4d
@ -47,6 +47,10 @@ impl Chunk {
|
|||||||
self.instructions.is_empty()
|
self.instructions.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn instructions_mut(&mut self) -> &mut Vec<(Instruction, Span)> {
|
||||||
|
&mut self.instructions
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_instruction(
|
pub fn get_instruction(
|
||||||
&self,
|
&self,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
@ -61,6 +65,24 @@ impl Chunk {
|
|||||||
self.instructions.push((instruction, position));
|
self.instructions.push((instruction, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert_instruction(
|
||||||
|
&mut self,
|
||||||
|
index: usize,
|
||||||
|
instruction: Instruction,
|
||||||
|
position: Span,
|
||||||
|
) -> Result<(), ChunkError> {
|
||||||
|
if index > self.instructions.len() {
|
||||||
|
Err(ChunkError::InstructionIndexOfBounds {
|
||||||
|
offset: index,
|
||||||
|
position,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
self.instructions.insert(index, (instruction, position));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn take_constants(self) -> Vec<Value> {
|
pub fn take_constants(self) -> Vec<Value> {
|
||||||
self.constants
|
self.constants
|
||||||
}
|
}
|
||||||
@ -267,8 +289,8 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
const INSTRUCTION_HEADER: [&'static str; 4] = [
|
const INSTRUCTION_HEADER: [&'static str; 4] = [
|
||||||
"Instructions",
|
"Instructions",
|
||||||
"------------",
|
"------------",
|
||||||
"INDEX BYTECODE OPERATION INFO JUMP POSITION",
|
"INDEX BYTECODE OPERATION INFO JUMP POSITION ",
|
||||||
"----- -------- --------------- ------------------------- -------- --------",
|
"----- -------- --------------- -------------------- -------- -------------",
|
||||||
];
|
];
|
||||||
|
|
||||||
const CONSTANT_HEADER: [&'static str; 4] =
|
const CONSTANT_HEADER: [&'static str; 4] =
|
||||||
@ -494,7 +516,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
};
|
};
|
||||||
let bytecode = u32::from(instruction);
|
let bytecode = u32::from(instruction);
|
||||||
let instruction_display = format!(
|
let instruction_display = format!(
|
||||||
"{index:<5} {bytecode:<08X} {operation:15} {info:25} {jump_offset:8} {position:8}"
|
"{index:<5} {bytecode:<08X} {operation:15} {info:20} {jump_offset:8} {position:13}"
|
||||||
);
|
);
|
||||||
|
|
||||||
push_details(&instruction_display, &mut disassembly);
|
push_details(&instruction_display, &mut disassembly);
|
||||||
|
@ -9,8 +9,8 @@ use colored::Colorize;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Identifier, Instruction, LexError,
|
instruction, operation, AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Identifier,
|
||||||
Lexer, Operation, Span, Token, TokenKind, TokenOwned, Type, Value,
|
Instruction, LexError, Lexer, Operation, Span, Token, TokenKind, TokenOwned, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
||||||
@ -27,7 +27,7 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
|||||||
.map_err(|error| DustError::Parse { error, source })?;
|
.map_err(|error| DustError::Parse { error, source })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(parser.take_chunk())
|
Ok(parser.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize)]
|
||||||
@ -70,7 +70,7 @@ impl<'src> Parser<'src> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_chunk(self) -> Chunk {
|
pub fn finish(self) -> Chunk {
|
||||||
log::info!("End chunk");
|
log::info!("End chunk");
|
||||||
|
|
||||||
self.chunk
|
self.chunk
|
||||||
@ -172,11 +172,33 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_previous_jump_mut(&mut self) -> Option<&mut Instruction> {
|
fn get_previous_jump_mut(&mut self) -> Option<&mut Instruction> {
|
||||||
self.current_statement
|
let staged_jump = self
|
||||||
|
.current_statement
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|(instruction, _)| matches!(instruction.operation(), Operation::Jump))
|
.find_map(|(instruction, _)| {
|
||||||
.map(|(instruction, _)| instruction)
|
if matches!(instruction.operation(), Operation::Jump) {
|
||||||
|
Some(instruction)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if staged_jump.is_some() {
|
||||||
|
staged_jump
|
||||||
|
} else {
|
||||||
|
self.chunk
|
||||||
|
.instructions_mut()
|
||||||
|
.iter_mut()
|
||||||
|
.rev()
|
||||||
|
.find_map(|(instruction, _)| {
|
||||||
|
if matches!(instruction.operation(), Operation::Jump) {
|
||||||
|
Some(instruction)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> {
|
fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> {
|
||||||
@ -435,7 +457,7 @@ impl<'src> Parser<'src> {
|
|||||||
_ => {
|
_ => {
|
||||||
push_back = true;
|
push_back = true;
|
||||||
|
|
||||||
instruction.a()
|
self.next_register()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -495,17 +517,17 @@ impl<'src> Parser<'src> {
|
|||||||
self.next_register()
|
self.next_register()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_instruction = match operator.kind() {
|
let mut new_instruction = match operator {
|
||||||
TokenKind::Plus => Instruction::add(register, left, right),
|
Token::Plus => Instruction::add(register, left, right),
|
||||||
TokenKind::PlusEqual => Instruction::add(register, left, right),
|
Token::PlusEqual => Instruction::add(register, left, right),
|
||||||
TokenKind::Minus => Instruction::subtract(register, left, right),
|
Token::Minus => Instruction::subtract(register, left, right),
|
||||||
TokenKind::MinusEqual => Instruction::subtract(register, left, right),
|
Token::MinusEqual => Instruction::subtract(register, left, right),
|
||||||
TokenKind::Star => Instruction::multiply(register, left, right),
|
Token::Star => Instruction::multiply(register, left, right),
|
||||||
TokenKind::StarEqual => Instruction::multiply(register, left, right),
|
Token::StarEqual => Instruction::multiply(register, left, right),
|
||||||
TokenKind::Slash => Instruction::divide(register, left, right),
|
Token::Slash => Instruction::divide(register, left, right),
|
||||||
TokenKind::SlashEqual => Instruction::divide(register, left, right),
|
Token::SlashEqual => Instruction::divide(register, left, right),
|
||||||
TokenKind::Percent => Instruction::modulo(register, left, right),
|
Token::Percent => Instruction::modulo(register, left, right),
|
||||||
TokenKind::PercentEqual => Instruction::modulo(register, left, right),
|
Token::PercentEqual => Instruction::modulo(register, left, right),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::ExpectedTokenMultiple {
|
return Err(ParseError::ExpectedTokenMultiple {
|
||||||
expected: &[
|
expected: &[
|
||||||
@ -536,6 +558,15 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
self.emit_instruction(new_instruction, operator_position);
|
self.emit_instruction(new_instruction, operator_position);
|
||||||
|
|
||||||
|
if let Token::PlusEqual
|
||||||
|
| Token::MinusEqual
|
||||||
|
| Token::StarEqual
|
||||||
|
| Token::SlashEqual
|
||||||
|
| Token::PercentEqual = operator
|
||||||
|
{
|
||||||
|
self.commit_current_statement();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,12 +608,12 @@ impl<'src> Parser<'src> {
|
|||||||
self.handle_binary_argument(&right_instruction)?;
|
self.handle_binary_argument(&right_instruction)?;
|
||||||
|
|
||||||
let mut instruction = match operator {
|
let mut instruction = match operator {
|
||||||
Token::DoubleEqual => Instruction::equal(true, left.saturating_sub(1), right),
|
Token::DoubleEqual => Instruction::equal(true, left, right),
|
||||||
Token::BangEqual => Instruction::equal(false, left.saturating_sub(1), right),
|
Token::BangEqual => Instruction::equal(false, left, right),
|
||||||
Token::Less => Instruction::less(true, left.saturating_sub(1), right),
|
Token::Less => Instruction::less(true, left, right),
|
||||||
Token::LessEqual => Instruction::less_equal(true, left.saturating_sub(1), right),
|
Token::LessEqual => Instruction::less_equal(true, left, right),
|
||||||
Token::Greater => Instruction::less_equal(false, left.saturating_sub(1), right),
|
Token::Greater => Instruction::less_equal(false, left, right),
|
||||||
Token::GreaterEqual => Instruction::less(false, left.saturating_sub(1), right),
|
Token::GreaterEqual => Instruction::less(false, left, right),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParseError::ExpectedTokenMultiple {
|
return Err(ParseError::ExpectedTokenMultiple {
|
||||||
@ -800,7 +831,6 @@ impl<'src> Parser<'src> {
|
|||||||
let expected_register = self.next_register();
|
let expected_register = self.next_register();
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
self.commit_current_statement();
|
|
||||||
|
|
||||||
let actual_register = self.next_register() - 1;
|
let actual_register = self.next_register() - 1;
|
||||||
|
|
||||||
@ -893,9 +923,6 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
fn parse_while(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
fn parse_while(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let jump_start = self.chunk.len() + self.current_statement.len();
|
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
if let Some(
|
if let Some(
|
||||||
@ -904,8 +931,11 @@ impl<'src> Parser<'src> {
|
|||||||
{
|
{
|
||||||
self.current_statement.pop();
|
self.current_statement.pop();
|
||||||
self.current_statement.pop();
|
self.current_statement.pop();
|
||||||
|
self.current_statement.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let jump_start = self.chunk.len() + self.current_statement.len();
|
||||||
|
|
||||||
self.parse_block(Allowed {
|
self.parse_block(Allowed {
|
||||||
assignment: true,
|
assignment: true,
|
||||||
explicit_return: allowed.explicit_return,
|
explicit_return: allowed.explicit_return,
|
||||||
@ -913,16 +943,17 @@ impl<'src> Parser<'src> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let jump_end = self.chunk.len() + self.current_statement.len();
|
let jump_end = self.chunk.len() + self.current_statement.len();
|
||||||
let jump_distance = jump_end.abs_diff(jump_start) as u8;
|
let jump_distance = jump_end.abs_diff(jump_start) as u8 + 1;
|
||||||
let jump_back = Instruction::jump(jump_distance, false);
|
let jump_back = Instruction::jump(jump_distance + 1, false);
|
||||||
|
|
||||||
if let Some(jump_over) = self.get_previous_jump_mut() {
|
|
||||||
*jump_over = Instruction::jump(jump_distance - 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
self.emit_instruction(jump_back, self.current_position);
|
||||||
self.commit_current_statement();
|
self.commit_current_statement();
|
||||||
self.chunk
|
|
||||||
.push_instruction(jump_back, self.current_position);
|
self.chunk.insert_instruction(
|
||||||
|
jump_start,
|
||||||
|
Instruction::jump(jump_distance, true),
|
||||||
|
self.current_position,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1223,7 +1254,19 @@ impl<'src> Parser<'src> {
|
|||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
while !self.allow(Token::RightParenthesis)? {
|
while !self.allow(Token::RightParenthesis)? {
|
||||||
|
let expected_register = self.next_register();
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
|
let actual_register = self.next_register() - 1;
|
||||||
|
|
||||||
|
if expected_register < actual_register {
|
||||||
|
self.emit_instruction(
|
||||||
|
Instruction::close(expected_register, actual_register),
|
||||||
|
self.current_position,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.allow(Token::Comma)?;
|
self.allow(Token::Comma)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ impl Value {
|
|||||||
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotSubtract(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let difference = left
|
let difference = left
|
||||||
.subtract(right)
|
.subtract(right)
|
||||||
@ -133,7 +133,7 @@ impl Value {
|
|||||||
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotMultiply(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let product = left
|
let product = left
|
||||||
.multiply(right)
|
.multiply(right)
|
||||||
@ -145,7 +145,7 @@ impl Value {
|
|||||||
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotDivide(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let quotient = left
|
let quotient = left
|
||||||
.divide(right)
|
.divide(right)
|
||||||
@ -157,7 +157,7 @@ impl Value {
|
|||||||
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotModulo(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let remainder = left
|
let remainder = left
|
||||||
.modulo(right)
|
.modulo(right)
|
||||||
@ -169,7 +169,7 @@ impl Value {
|
|||||||
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotCompare(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::boolean(left < right))
|
Ok(Value::boolean(left < right))
|
||||||
@ -178,18 +178,16 @@ impl Value {
|
|||||||
pub fn less_than_or_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn less_than_or_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotCompare(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
left.less_than_or_equal(right)
|
Ok(Value::boolean(left <= right))
|
||||||
.ok_or_else(|| ValueError::CannotLessThanOrEqual(self.clone(), other.clone()))
|
|
||||||
.map(Value::Primitive)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn equal(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotCompare(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::boolean(left == right))
|
Ok(Value::boolean(left == right))
|
||||||
@ -198,7 +196,7 @@ impl Value {
|
|||||||
pub fn not_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn not_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
let (left, right) = match (self, other) {
|
||||||
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
(Value::Primitive(left), Value::Primitive(right)) => (left, right),
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotCompare(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::boolean(left != right))
|
Ok(Value::boolean(left != right))
|
||||||
@ -931,13 +929,12 @@ impl Display for Object {
|
|||||||
pub enum ValueError {
|
pub enum ValueError {
|
||||||
CannotAdd(Value, Value),
|
CannotAdd(Value, Value),
|
||||||
CannotAnd(Value, Value),
|
CannotAnd(Value, Value),
|
||||||
|
CannotCompare(Value, Value),
|
||||||
CannotDisplay {
|
CannotDisplay {
|
||||||
value: Value,
|
value: Value,
|
||||||
vm_error: Box<VmError>,
|
vm_error: Box<VmError>,
|
||||||
},
|
},
|
||||||
CannotDivide(Value, Value),
|
CannotDivide(Value, Value),
|
||||||
CannotLessThan(Value, Value),
|
|
||||||
CannotLessThanOrEqual(Value, Value),
|
|
||||||
CannotModulo(Value, Value),
|
CannotModulo(Value, Value),
|
||||||
CannotMultiply(Value, Value),
|
CannotMultiply(Value, Value),
|
||||||
CannotNegate(Value),
|
CannotNegate(Value),
|
||||||
@ -973,6 +970,12 @@ impl Display for ValueError {
|
|||||||
left_display, right_display
|
left_display, right_display
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
ValueError::CannotCompare(left, right) => {
|
||||||
|
let left_display = get_value_display(left);
|
||||||
|
let right_display = get_value_display(right);
|
||||||
|
|
||||||
|
write!(f, "Cannot compare {} and {}", left_display, right_display)
|
||||||
|
}
|
||||||
ValueError::CannotDisplay { value, vm_error } => {
|
ValueError::CannotDisplay { value, vm_error } => {
|
||||||
let value_display = get_value_display(value);
|
let value_display = get_value_display(value);
|
||||||
|
|
||||||
@ -984,18 +987,6 @@ impl Display for ValueError {
|
|||||||
|
|
||||||
write!(f, "Cannot divide {} by {}", left_display, right_display)
|
write!(f, "Cannot divide {} by {}", left_display, right_display)
|
||||||
}
|
}
|
||||||
ValueError::CannotLessThan(left, right) => {
|
|
||||||
let left_display = get_value_display(left);
|
|
||||||
let right_display = get_value_display(right);
|
|
||||||
|
|
||||||
write!(f, "Cannot compare {} and {}", left_display, right_display)
|
|
||||||
}
|
|
||||||
ValueError::CannotLessThanOrEqual(left, right) => {
|
|
||||||
let left_display = get_value_display(left);
|
|
||||||
let right_display = get_value_display(right);
|
|
||||||
|
|
||||||
write!(f, "Cannot compare {} and {}", left_display, right_display)
|
|
||||||
}
|
|
||||||
ValueError::CannotModulo(left, right) => {
|
ValueError::CannotModulo(left, right) => {
|
||||||
let left_display = get_value_display(left);
|
let left_display = get_value_display(left);
|
||||||
let right_display = get_value_display(right);
|
let right_display = get_value_display(right);
|
||||||
|
@ -364,7 +364,11 @@ impl Vm {
|
|||||||
for argument_index in
|
for argument_index in
|
||||||
first_argument_index..first_argument_index + argument_count
|
first_argument_index..first_argument_index + argument_count
|
||||||
{
|
{
|
||||||
let argument = self.get(argument_index, position)?.clone();
|
let argument = match self.get(argument_index, position) {
|
||||||
|
Ok(value) => value.clone(),
|
||||||
|
Err(VmError::EmptyRegister { .. }) => continue,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
let top_of_stack = function_vm.stack.len() as u8;
|
let top_of_stack = function_vm.stack.len() as u8;
|
||||||
|
|
||||||
function_vm.set(top_of_stack, argument, position)?;
|
function_vm.set(top_of_stack, argument, position)?;
|
||||||
|
@ -1049,7 +1049,7 @@ fn r#while() {
|
|||||||
*Instruction::less(true, 0, 1).set_c_is_constant(),
|
*Instruction::less(true, 0, 1).set_c_is_constant(),
|
||||||
Span(23, 24)
|
Span(23, 24)
|
||||||
),
|
),
|
||||||
(Instruction::jump(2, true), Span(23, 24)),
|
(Instruction::jump(2, true), Span(41, 42)),
|
||||||
(*Instruction::add(0, 0, 2).set_c_is_constant(), Span(39, 40)),
|
(*Instruction::add(0, 0, 2).set_c_is_constant(), Span(39, 40)),
|
||||||
(Instruction::jump(3, false), Span(41, 42)),
|
(Instruction::jump(3, false), Span(41, 42)),
|
||||||
(Instruction::get_local(1, 0), Span(41, 42)),
|
(Instruction::get_local(1, 0), Span(41, 42)),
|
||||||
|
Loading…
Reference in New Issue
Block a user