Refine LoadList instruction; Improve logs; Refactor
This commit is contained in:
parent
60df8b4d64
commit
daca836db1
@ -76,11 +76,18 @@ impl Chunk {
|
|||||||
.ok_or(ChunkError::InstructionUnderflow { position })
|
.ok_or(ChunkError::InstructionUnderflow { position })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_last_instruction(&self) -> Option<&(Instruction, Span)> {
|
pub fn get_last_instruction(&self) -> Result<(&Instruction, &Span), ChunkError> {
|
||||||
self.instructions.last()
|
let (instruction, position) =
|
||||||
|
self.instructions
|
||||||
|
.last()
|
||||||
|
.ok_or_else(|| ChunkError::InstructionUnderflow {
|
||||||
|
position: Span(0, 0),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok((instruction, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_last_operation(&self) -> Option<Operation> {
|
pub fn get_last_operation(&self) -> Result<Operation, ChunkError> {
|
||||||
self.get_last_instruction()
|
self.get_last_instruction()
|
||||||
.map(|(instruction, _)| instruction.operation())
|
.map(|(instruction, _)| instruction.operation())
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
//! Key used to identify a value or type.
|
//! Key used to identify a value or type.
|
||||||
//!
|
//!
|
||||||
//! Identifiers are used to uniquely identify values and types in Dust programs. They are
|
//! Identifiers are used to uniquely identify values and types in Dust programs.
|
||||||
//! cached to avoid duplication. This means that two identifiers with the same text are the same
|
|
||||||
//! object in memory.
|
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//! ```
|
//! ```
|
||||||
//! # use dust_lang::Identifier;
|
//! # use dust_lang::Identifier;
|
||||||
//! let foo = Identifier::new("foo");
|
//! let foo = Identifier::new("foo");
|
||||||
//! let also_foo = Identifier::new("foo");
|
//! let also_foo = foo.clone();
|
||||||
//! let another_foo = Identifier::new("foo");
|
//! let another_foo = also_foo.clone();
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(foo.strong_count(), 4); // One for each of the above and one for the cache.
|
//! assert_eq!(foo.strong_count(), 3); // One for each of the above.
|
||||||
//! ```
|
//! ```
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
@ -27,7 +25,6 @@ use serde::{de::Visitor, Deserialize, Serialize};
|
|||||||
pub struct Identifier(Arc<String>);
|
pub struct Identifier(Arc<String>);
|
||||||
|
|
||||||
impl Identifier {
|
impl Identifier {
|
||||||
/// Creates a new identifier or returns a clone of an existing one from a cache.
|
|
||||||
pub fn new<T: ToString>(text: T) -> Self {
|
pub fn new<T: ToString>(text: T) -> Self {
|
||||||
let string = text.to_string();
|
let string = text.to_string();
|
||||||
|
|
||||||
|
@ -41,12 +41,12 @@ impl Instruction {
|
|||||||
instruction
|
instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_list(to_register: u8, start_register: u8, list_length: u8) -> Instruction {
|
pub fn load_list(to_register: u8, start_register: u8, end_register: u8) -> Instruction {
|
||||||
let mut instruction = Instruction(Operation::LoadList as u32);
|
let mut instruction = Instruction(Operation::LoadList as u32);
|
||||||
|
|
||||||
instruction.set_a(to_register);
|
instruction.set_a(to_register);
|
||||||
instruction.set_b(start_register);
|
instruction.set_b(start_register);
|
||||||
instruction.set_c(list_length);
|
instruction.set_c(end_register);
|
||||||
|
|
||||||
instruction
|
instruction
|
||||||
}
|
}
|
||||||
@ -371,12 +371,9 @@ impl Instruction {
|
|||||||
Operation::LoadList => {
|
Operation::LoadList => {
|
||||||
let destination = self.a();
|
let destination = self.a();
|
||||||
let first_index = self.b();
|
let first_index = self.b();
|
||||||
let last_index = destination.saturating_sub(1);
|
let last_index = self.c();
|
||||||
|
|
||||||
Some(format!(
|
Some(format!("R{destination} = [R{first_index}..=R{last_index}]",))
|
||||||
"R{} = [R{}..=R{}]",
|
|
||||||
destination, first_index, last_index
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
Operation::DefineLocal => {
|
Operation::DefineLocal => {
|
||||||
let destination = self.a();
|
let destination = self.a();
|
||||||
|
@ -40,7 +40,7 @@ impl<'src> Parser<'src> {
|
|||||||
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, ParseError> {
|
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, ParseError> {
|
||||||
let (current_token, current_position) = lexer.next_token()?;
|
let (current_token, current_position) = lexer.next_token()?;
|
||||||
|
|
||||||
log::trace!("Starting parser with token \"{current_token}\" at {current_position}");
|
log::info!("Starting parser with token \"{current_token}\" at {current_position}");
|
||||||
|
|
||||||
Ok(Parser {
|
Ok(Parser {
|
||||||
lexer,
|
lexer,
|
||||||
@ -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 \"{new_token}\" at {position}");
|
log::info!("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);
|
||||||
@ -438,7 +438,7 @@ impl<'src> Parser<'src> {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(operation) = self.chunk.get_last_operation() {
|
while let Ok(operation) = self.chunk.get_last_operation() {
|
||||||
if operation.is_math() {
|
if operation.is_math() {
|
||||||
let (instruction, position) = self.chunk.pop_instruction(self.current_position)?;
|
let (instruction, position) = self.chunk.pop_instruction(self.current_position)?;
|
||||||
|
|
||||||
@ -688,14 +688,13 @@ impl<'src> Parser<'src> {
|
|||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let start_register = self.current_register;
|
let start_register = self.current_register;
|
||||||
let mut length = 0;
|
|
||||||
|
|
||||||
while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() {
|
while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() {
|
||||||
let next_register = self.current_register;
|
let next_register = self.current_register;
|
||||||
|
|
||||||
self.parse(Precedence::Assignment)?; // Do not allow assignment
|
self.parse(Precedence::Assignment)?; // Do not allow assignment
|
||||||
|
|
||||||
if let Some(Operation::LoadConstant) = self.chunk.get_last_operation() {
|
if let Operation::LoadConstant = self.chunk.get_last_operation()? {
|
||||||
self.increment_register()?;
|
self.increment_register()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,19 +705,16 @@ impl<'src> Parser<'src> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
length += 1;
|
|
||||||
|
|
||||||
if !self.allow(TokenKind::Comma)? {
|
if !self.allow(TokenKind::Comma)? {
|
||||||
self.expect(TokenKind::RightSquareBrace)?;
|
self.expect(TokenKind::RightSquareBrace)?;
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let end_register = self.current_register - 1;
|
||||||
let end = self.current_position.1;
|
let end = self.current_position.1;
|
||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
Instruction::load_list(self.current_register, start_register, length),
|
Instruction::load_list(self.current_register, start_register, end_register),
|
||||||
Span(start, end),
|
Span(start, end),
|
||||||
);
|
);
|
||||||
self.increment_register()?;
|
self.increment_register()?;
|
||||||
@ -864,17 +860,11 @@ impl<'src> Parser<'src> {
|
|||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
self.increment_register()?;
|
self.increment_register()?;
|
||||||
|
|
||||||
let (previous_instruction, previous_position) = *self
|
let (previous_instruction, previous_position) = self.chunk.get_last_instruction()?;
|
||||||
.chunk
|
|
||||||
.get_last_instruction()
|
|
||||||
.ok_or_else(|| ParseError::ExpectedExpression {
|
|
||||||
found: self.current_token.to_owned(),
|
|
||||||
position,
|
|
||||||
})?;
|
|
||||||
let register = previous_instruction.a();
|
let register = previous_instruction.a();
|
||||||
let local_index =
|
let local_index =
|
||||||
self.chunk
|
self.chunk
|
||||||
.declare_local(identifier, is_mutable, register, previous_position)?;
|
.declare_local(identifier, is_mutable, register, *previous_position)?;
|
||||||
|
|
||||||
// Optimize for assignment to a comparison
|
// Optimize for assignment to a comparison
|
||||||
// if let Operation::Jump = previous_instruction.operation() {
|
// if let Operation::Jump = previous_instruction.operation() {
|
||||||
@ -909,8 +899,8 @@ impl<'src> Parser<'src> {
|
|||||||
let allow_return = precedence == Precedence::None;
|
let allow_return = precedence == Precedence::None;
|
||||||
|
|
||||||
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::debug!(
|
||||||
"Parsing \"{}\" as prefix at precedence {precedence}",
|
"Prefix \"{}\" has precedence {precedence}",
|
||||||
self.current_token,
|
self.current_token,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -921,8 +911,8 @@ 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::debug!(
|
||||||
"Parsing \"{}\" as infix at precedence {precedence}",
|
"Infix \"{}\" has precedence {precedence}",
|
||||||
self.current_token,
|
self.current_token,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ fn list_with_complex_expression() {
|
|||||||
),
|
),
|
||||||
(Instruction::subtract(3, 1, 2), Span(10, 11)),
|
(Instruction::subtract(3, 1, 2), Span(10, 11)),
|
||||||
(Instruction::close(1, 3), Span(17, 18)),
|
(Instruction::close(1, 3), Span(17, 18)),
|
||||||
(Instruction::load_list(4, 0, 2), Span(0, 18)),
|
(Instruction::load_list(4, 0, 3), Span(0, 18)),
|
||||||
(Instruction::end(true), Span(18, 18)),
|
(Instruction::end(true), Span(18, 18)),
|
||||||
],
|
],
|
||||||
vec![
|
vec![
|
||||||
@ -352,7 +352,7 @@ fn list_with_simple_expression() {
|
|||||||
Span(6, 7)
|
Span(6, 7)
|
||||||
),
|
),
|
||||||
(Instruction::load_constant(2, 3), Span(11, 12)),
|
(Instruction::load_constant(2, 3), Span(11, 12)),
|
||||||
(Instruction::load_list(3, 0, 3), Span(0, 13)),
|
(Instruction::load_list(3, 0, 2), Span(0, 13)),
|
||||||
(Instruction::end(true), Span(13, 13)),
|
(Instruction::end(true), Span(13, 13)),
|
||||||
],
|
],
|
||||||
vec![
|
vec![
|
||||||
@ -377,7 +377,7 @@ fn list() {
|
|||||||
(Instruction::load_constant(0, 0), Span(1, 2)),
|
(Instruction::load_constant(0, 0), Span(1, 2)),
|
||||||
(Instruction::load_constant(1, 1), Span(4, 5)),
|
(Instruction::load_constant(1, 1), Span(4, 5)),
|
||||||
(Instruction::load_constant(2, 2), Span(7, 8)),
|
(Instruction::load_constant(2, 2), Span(7, 8)),
|
||||||
(Instruction::load_list(3, 0, 3), Span(0, 9)),
|
(Instruction::load_list(3, 0, 2), Span(0, 9)),
|
||||||
(Instruction::end(true), Span(9, 9)),
|
(Instruction::end(true), Span(9, 9)),
|
||||||
],
|
],
|
||||||
vec![Value::integer(1), Value::integer(2), Value::integer(3),],
|
vec![Value::integer(1), Value::integer(2), Value::integer(3),],
|
||||||
|
@ -56,7 +56,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() {
|
while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() {
|
||||||
log::trace!(
|
log::info!(
|
||||||
"Running IP {} {} at {position}",
|
"Running IP {} {} at {position}",
|
||||||
self.ip - 1,
|
self.ip - 1,
|
||||||
instruction.operation()
|
instruction.operation()
|
||||||
@ -68,6 +68,8 @@ impl Vm {
|
|||||||
let to = instruction.a();
|
let to = instruction.a();
|
||||||
let value = self.take(from, position)?;
|
let value = self.take(from, position)?;
|
||||||
|
|
||||||
|
log::debug!("R{from} -{{{value}}}-> R{to}");
|
||||||
|
|
||||||
self.insert(value, to, position)?;
|
self.insert(value, to, position)?;
|
||||||
}
|
}
|
||||||
Operation::Close => {
|
Operation::Close => {
|
||||||
@ -100,13 +102,14 @@ impl Vm {
|
|||||||
Operation::LoadList => {
|
Operation::LoadList => {
|
||||||
let to_register = instruction.a();
|
let to_register = instruction.a();
|
||||||
let first_register = instruction.b();
|
let first_register = instruction.b();
|
||||||
let length = instruction.c();
|
let last_register = instruction.c();
|
||||||
let last_register = first_register + length + 1;
|
let length = last_register - first_register + 1;
|
||||||
|
|
||||||
let mut list = Vec::with_capacity(length as usize);
|
let mut list = Vec::with_capacity(length as usize);
|
||||||
|
|
||||||
|
log::debug!("R{to_register} = [R{first_register}..=R{last_register}]");
|
||||||
|
|
||||||
for register_index in first_register..=last_register {
|
for register_index in first_register..=last_register {
|
||||||
let value = match self.clone(register_index, position) {
|
let value = match self.take(register_index, position) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(VmError::EmptyRegister { .. }) => continue,
|
Err(VmError::EmptyRegister { .. }) => continue,
|
||||||
Err(error) => return Err(error),
|
Err(error) => return Err(error),
|
||||||
@ -126,81 +129,91 @@ impl Vm {
|
|||||||
Operation::GetLocal => {
|
Operation::GetLocal => {
|
||||||
let register_index = instruction.a();
|
let register_index = instruction.a();
|
||||||
let local_index = instruction.b();
|
let local_index = instruction.b();
|
||||||
let local = self.chunk.get_local(local_index, position)?.clone();
|
let local = self.chunk.get_local(local_index, position)?;
|
||||||
let value = self.clone_as_variable(local, position)?;
|
let value = if let Some(index) = local.register_index {
|
||||||
|
self.take(index, position)?
|
||||||
|
} else {
|
||||||
|
return Err(VmError::UndefinedVariable {
|
||||||
|
identifier: local.identifier.clone(),
|
||||||
|
position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
self.insert(value, register_index, position)?;
|
self.insert(value, register_index, position)?;
|
||||||
}
|
}
|
||||||
Operation::SetLocal => {
|
Operation::SetLocal => {
|
||||||
let register_index = instruction.a();
|
let register_index = instruction.a();
|
||||||
let local_index = instruction.b();
|
let local_index = instruction.b();
|
||||||
let local = self.chunk.get_local(local_index, position)?.clone();
|
let local = self.chunk.get_local(local_index, position)?;
|
||||||
let value = self.clone_as_variable(local, position)?;
|
let value = if let Some(index) = local.register_index {
|
||||||
|
self.take(index, position)?
|
||||||
|
} else {
|
||||||
|
return Err(VmError::UndefinedVariable {
|
||||||
|
identifier: local.identifier.clone(),
|
||||||
|
position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
let new_value = if instruction.b_is_constant() {
|
let new_value = if instruction.b_is_constant() {
|
||||||
self.chunk.take_constant(register_index, position)?
|
self.chunk.take_constant(register_index, position)?
|
||||||
} else {
|
} else {
|
||||||
self.clone(register_index, position)?
|
self.take(register_index, position)?
|
||||||
};
|
};
|
||||||
|
|
||||||
value
|
value
|
||||||
.mutate(new_value)
|
.mutate(new_value)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
self.insert(value, register_index, position)?;
|
self.insert(value, register_index, position)?;
|
||||||
}
|
}
|
||||||
Operation::Add => {
|
Operation::Add => {
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
log::debug!("{left} + {right}");
|
|
||||||
|
|
||||||
let sum = left
|
let sum = left
|
||||||
.add(right)
|
.add(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("{left} + {right} = {sum}");
|
||||||
|
|
||||||
self.insert(sum, instruction.a(), position)?;
|
self.insert(sum, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Subtract => {
|
Operation::Subtract => {
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
log::debug!("{left} - {right}");
|
|
||||||
|
|
||||||
let difference = left
|
let difference = left
|
||||||
.subtract(right)
|
.subtract(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("{left} - {right} = {difference}");
|
||||||
|
|
||||||
self.insert(difference, instruction.a(), position)?;
|
self.insert(difference, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Multiply => {
|
Operation::Multiply => {
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
log::debug!("{left} * {right}");
|
|
||||||
|
|
||||||
let product = left
|
let product = left
|
||||||
.multiply(right)
|
.multiply(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("{position} {left} * {right}");
|
||||||
|
|
||||||
self.insert(product, instruction.a(), position)?;
|
self.insert(product, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Divide => {
|
Operation::Divide => {
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
log::debug!("{left} / {right}");
|
|
||||||
|
|
||||||
let quotient = left
|
let quotient = left
|
||||||
.divide(right)
|
.divide(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("{left} / {right} = {quotient}");
|
||||||
|
|
||||||
self.insert(quotient, instruction.a(), position)?;
|
self.insert(quotient, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Modulo => {
|
Operation::Modulo => {
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
log::debug!("{left} % {right}");
|
|
||||||
|
|
||||||
let remainder = left
|
let remainder = left
|
||||||
.modulo(right)
|
.modulo(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("{left} % {right} = {remainder}");
|
||||||
|
|
||||||
self.insert(remainder, instruction.a(), position)?;
|
self.insert(remainder, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Test => {
|
Operation::Test => {
|
||||||
@ -238,6 +251,7 @@ impl Vm {
|
|||||||
debug_assert_eq!(jump.operation(), Operation::Jump);
|
debug_assert_eq!(jump.operation(), Operation::Jump);
|
||||||
|
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
let boolean = left
|
let boolean = left
|
||||||
.equal(right)
|
.equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?
|
.map_err(|error| VmError::Value { error, position })?
|
||||||
@ -248,6 +262,8 @@ impl Vm {
|
|||||||
})?;
|
})?;
|
||||||
let compare_to = instruction.a_as_boolean();
|
let compare_to = instruction.a_as_boolean();
|
||||||
|
|
||||||
|
log::debug!("{left} == {right} = {boolean} == {compare_to}");
|
||||||
|
|
||||||
if boolean == compare_to {
|
if boolean == compare_to {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -263,11 +279,12 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::Less => {
|
Operation::Less => {
|
||||||
let (jump, _) = *self.chunk.get_instruction(self.ip, position)?;
|
let jump = self.chunk.get_instruction(self.ip, position)?.0;
|
||||||
|
|
||||||
debug_assert_eq!(jump.operation(), Operation::Jump);
|
debug_assert_eq!(jump.operation(), Operation::Jump);
|
||||||
|
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
|
|
||||||
let boolean = left
|
let boolean = left
|
||||||
.less_than(right)
|
.less_than(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?
|
.map_err(|error| VmError::Value { error, position })?
|
||||||
@ -278,6 +295,8 @@ impl Vm {
|
|||||||
})?;
|
})?;
|
||||||
let compare_to = instruction.a_as_boolean();
|
let compare_to = instruction.a_as_boolean();
|
||||||
|
|
||||||
|
log::debug!("{left} < {right} = {boolean} == {compare_to}");
|
||||||
|
|
||||||
if boolean == compare_to {
|
if boolean == compare_to {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -293,7 +312,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::LessEqual => {
|
Operation::LessEqual => {
|
||||||
let (jump, _) = *self.chunk.get_instruction(self.ip, position)?;
|
let jump = self.chunk.get_instruction(self.ip, position)?.0;
|
||||||
|
|
||||||
debug_assert_eq!(jump.operation(), Operation::Jump);
|
debug_assert_eq!(jump.operation(), Operation::Jump);
|
||||||
|
|
||||||
@ -308,6 +327,8 @@ impl Vm {
|
|||||||
})?;
|
})?;
|
||||||
let compare_to = instruction.a_as_boolean();
|
let compare_to = instruction.a_as_boolean();
|
||||||
|
|
||||||
|
log::debug!("{left} <= {right} = {boolean} == {compare_to}");
|
||||||
|
|
||||||
if boolean == compare_to {
|
if boolean == compare_to {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -332,6 +353,8 @@ impl Vm {
|
|||||||
.negate()
|
.negate()
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("-({value}) = {negated}");
|
||||||
|
|
||||||
self.insert(negated, instruction.a(), position)?;
|
self.insert(negated, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Not => {
|
Operation::Not => {
|
||||||
@ -344,6 +367,8 @@ impl Vm {
|
|||||||
.not()
|
.not()
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
|
log::debug!("!{value} = {not}");
|
||||||
|
|
||||||
self.insert(not, instruction.a(), position)?;
|
self.insert(not, instruction.a(), position)?;
|
||||||
}
|
}
|
||||||
Operation::Jump => {
|
Operation::Jump => {
|
||||||
|
@ -24,21 +24,21 @@ fn main() {
|
|||||||
.parse_env("DUST_LOG")
|
.parse_env("DUST_LOG")
|
||||||
.format(|buf, record| {
|
.format(|buf, record| {
|
||||||
let level = match record.level() {
|
let level = match record.level() {
|
||||||
Level::Error => "ERROR".red(),
|
Level::Info => "INFO".white().bold(),
|
||||||
Level::Warn => "WARN".yellow(),
|
Level::Debug => "DEBUG".blue().bold(),
|
||||||
Level::Info => "INFO".white(),
|
Level::Warn => "WARN".yellow().bold(),
|
||||||
Level::Debug => "DEBUG".blue(),
|
Level::Error => "ERROR".red().bold(),
|
||||||
Level::Trace => "TRACE".purple(),
|
Level::Trace => "TRACE".purple().bold(),
|
||||||
}
|
}
|
||||||
.bold();
|
.bold();
|
||||||
let level_display = format!("[{level:^5}]").white().on_black();
|
let level_display = format!("{level:<5}");
|
||||||
let module = record
|
let module = record
|
||||||
.module_path()
|
.module_path()
|
||||||
.map(|path| path.split("::").last().unwrap_or("unknown"))
|
.map(|path| path.split("::").last().unwrap_or(path))
|
||||||
.unwrap_or("unknown")
|
.unwrap_or("unknown")
|
||||||
.dimmed();
|
.dimmed();
|
||||||
|
|
||||||
writeln!(buf, "{level_display} {module:^6} {}", record.args())
|
writeln!(buf, "{level_display:^10} {module:^6} {}", record.args())
|
||||||
})
|
})
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user