diff --git a/dust-lang/Cargo.toml b/dust-lang/Cargo.toml index a651f42..732932b 100644 --- a/dust-lang/Cargo.toml +++ b/dust-lang/Cargo.toml @@ -25,6 +25,7 @@ smartstring = { version = "1.0.1", features = [ [dev-dependencies] criterion = { version = "0.3.4", features = ["html_reports"] } +smallvec = { version = "1.13.2", features = ["const_generics"] } [[bench]] name = "addictive_addition" diff --git a/dust-lang/src/chunk/mod.rs b/dust-lang/src/chunk/mod.rs index d8c1db6..786f8e5 100644 --- a/dust-lang/src/chunk/mod.rs +++ b/dust-lang/src/chunk/mod.rs @@ -74,7 +74,7 @@ impl Chunk { } } - #[cfg(test)] + #[cfg(any(test, debug_assertions))] pub fn with_data( name: Option, r#type: FunctionType, diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 922cde5..ba8c8bb 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -20,13 +20,12 @@ //! runtime error, it is the compiler's fault and the error should be fixed here. mod error; mod optimize; +mod parse_rule; pub use error::CompileError; +use parse_rule::{ParseRule, Precedence}; -use std::{ - fmt::{self, Display, Formatter}, - mem::replace, -}; +use std::mem::{replace, swap}; use colored::Colorize; use optimize::control_flow_register_consolidation; @@ -119,14 +118,14 @@ pub struct Compiler<'src> { /// The current scope of the compiler. This is used to test if a variable is in scope. current_scope: Scope, - /// Index of the record (i.e. runtime data) that the VM will use when calling the function. This - /// is a depth-first index. + /// Index of the [`Record`] that the VM will use when calling the function. This is a + /// depth-first index. record_index: u8, /// Record index for the next nested chunk that is compiled. When a function is compiled, its /// `record_index` is assigned from this value. Then `next_record_index` is incremented to - /// maintain the depth-first index. After the function is compiled, the its `next_record_index` - /// is assigned to this chunk. + /// maintain the depth-first index. After the function is compiled, its `next_record_index` + /// is assigned back to this chunk. next_record_index: u8, } @@ -360,6 +359,12 @@ impl<'src> Compiler<'src> { } } + fn get_last_operation(&self) -> Option { + self.instructions + .last() + .map(|(instruction, _, _)| instruction.operation()) + } + fn get_last_operations(&self) -> Option<[Operation; COUNT]> { let mut n_operations = [Operation::RETURN; COUNT]; @@ -946,19 +951,30 @@ impl<'src> Compiler<'src> { } fn parse_logical_binary(&mut self) -> Result<(), CompileError> { - let is_logic_chain = matches!( - self.get_last_operations(), - Some([_, Operation::TEST, Operation::JUMP, _]) - ); - let jump_over_index = self.instructions.len() - 2; - let jump_over = if is_logic_chain { - let (instruction, _, _) = self.instructions.remove(jump_over_index); + let (last_instruction, last_type, last_position) = + self.instructions + .pop() + .ok_or_else(|| CompileError::ExpectedExpression { + found: self.previous_token.to_owned(), + position: self.previous_position, + })?; + let operand_register = if last_instruction.operation() == Operation::GET_LOCAL { + let (local, _) = self.get_local(last_instruction.b_field())?; - Some(instruction) + local.register_index + } else if last_instruction.yields_value() { + let register = last_instruction.a_field(); + + self.instructions + .push((last_instruction, last_type, last_position)); + + register } else { - None + self.instructions + .push((last_instruction, last_type, last_position)); + + self.next_register() - 1 }; - let operand_register = self.next_register() - 1; let operator = self.current_token; let operator_position = self.current_position; let rule = ParseRule::from(&operator); @@ -974,44 +990,29 @@ impl<'src> Compiler<'src> { } }; let test = Instruction::test(operand_register, test_boolean); + let jump = Instruction::jump(1, true); - self.advance()?; self.emit_instruction(test, Type::None, operator_position); - - let jump_index = self.instructions.len(); - + self.emit_instruction(jump, Type::None, operator_position); + self.advance()?; self.parse_sub_expression(&rule.precedence)?; - let jump_distance = (self.instructions.len() - jump_index) as u8; - let jump = Instruction::jump(jump_distance, true); + let instructions_length = self.instructions.len() - 1; - self.instructions - .insert(jump_index, (jump, Type::None, operator_position)); + for (group_index, instructions) in self.instructions.rchunks_mut(3).enumerate().rev() { + if instructions[0].0.operation() != Operation::TEST + || instructions[1].0.operation() != Operation::JUMP + { + continue; + } - if let Some(jump_over) = jump_over { - let is_end_of_context = matches!(self.current_token, Token::RightBrace | Token::Eof); - let jump_over_distance = - jump_over.b_field() + (self.instructions.len() - jump_over_index) as u8 - { - if is_end_of_context { - 1 - } else { - 0 - } - }; - let jump_over = Instruction::jump(jump_over_distance, true); + let jump = &mut instructions[1].0; + let jump_index = instructions_length - group_index * 3 - 1; + let short_circuit_distance = (instructions_length - jump_index) as u8; - self.instructions - .insert(jump_over_index, (jump_over, Type::None, operator_position)); + *jump = Instruction::jump(short_circuit_distance, true); } - // short_circuit_jump_distance += (self.instructions.len() - short_circuit_jump_index) as u8; - // let jump = Instruction::jump(short_circuit_jump_distance, true); - - // self.instructions.insert( - // short_circuit_jump_index, - // (jump, Type::None, operator_position), - // ); - Ok(()) } @@ -1241,8 +1242,8 @@ impl<'src> Compiler<'src> { match else_block_distance { 0 => {} 1 => { - if let Some([Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT]) = - self.get_last_operations() + if let Some(Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT) = + self.get_last_operation() { let (mut loader, _, _) = self.instructions.last_mut().unwrap(); @@ -1921,318 +1922,3 @@ impl<'src> Compiler<'src> { } } } - -/// Operator precedence levels. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Precedence { - Primary = 9, - Call = 8, - Unary = 7, - Factor = 6, - Term = 5, - Comparison = 4, - LogicalAnd = 3, - LogicalOr = 2, - Assignment = 1, - None = 0, -} - -impl Precedence { - fn increment(&self) -> Self { - match self { - Precedence::None => Precedence::Assignment, - Precedence::Assignment => Precedence::LogicalOr, - Precedence::LogicalOr => Precedence::LogicalAnd, - Precedence::LogicalAnd => Precedence::Comparison, - Precedence::Comparison => Precedence::Term, - Precedence::Term => Precedence::Factor, - Precedence::Factor => Precedence::Unary, - Precedence::Unary => Precedence::Call, - Precedence::Call => Precedence::Primary, - Precedence::Primary => Precedence::Primary, - } - } -} - -impl Display for Precedence { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -type Parser<'a> = fn(&mut Compiler<'a>) -> Result<(), CompileError>; - -/// Rule that defines how to parse a token. -#[derive(Debug, Clone, Copy)] -struct ParseRule<'a> { - pub prefix: Option>, - pub infix: Option>, - pub precedence: Precedence, -} - -impl From<&Token<'_>> for ParseRule<'_> { - fn from(token: &Token) -> Self { - match token { - Token::ArrowThin => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Async => todo!(), - Token::Bang => ParseRule { - prefix: Some(Compiler::parse_unary), - infix: None, - precedence: Precedence::Unary, - }, - Token::BangEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::Bool => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Boolean(_) => ParseRule { - prefix: Some(Compiler::parse_boolean), - infix: None, - precedence: Precedence::None, - }, - Token::Break => todo!(), - Token::Byte(_) => ParseRule { - prefix: Some(Compiler::parse_byte), - infix: None, - precedence: Precedence::None, - }, - Token::Character(_) => ParseRule { - prefix: Some(Compiler::parse_character), - infix: None, - precedence: Precedence::None, - }, - Token::Colon => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Comma => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::Dot => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::DoubleAmpersand => ParseRule { - prefix: None, - infix: Some(Compiler::parse_logical_binary), - precedence: Precedence::LogicalAnd, - }, - Token::DoubleEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::DoublePipe => ParseRule { - prefix: None, - infix: Some(Compiler::parse_logical_binary), - precedence: Precedence::LogicalOr, - }, - Token::DoubleDot => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Eof => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::Equal => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::Assignment, - }, - Token::Else => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::Float(_) => ParseRule { - prefix: Some(Compiler::parse_float), - infix: None, - precedence: Precedence::None, - }, - Token::FloatKeyword => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Fn => ParseRule { - prefix: Some(Compiler::parse_function), - infix: None, - precedence: Precedence::None, - }, - Token::Greater => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::GreaterEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::Identifier(_) => ParseRule { - prefix: Some(Compiler::parse_variable), - infix: None, - precedence: Precedence::None, - }, - Token::If => ParseRule { - prefix: Some(Compiler::parse_if), - infix: None, - precedence: Precedence::None, - }, - Token::Int => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::Integer(_) => ParseRule { - prefix: Some(Compiler::parse_integer), - infix: None, - precedence: Precedence::None, - }, - Token::LeftBrace => ParseRule { - prefix: Some(Compiler::parse_block), - infix: None, - precedence: Precedence::None, - }, - Token::LeftParenthesis => ParseRule { - prefix: Some(Compiler::parse_grouped), - infix: Some(Compiler::parse_call), - precedence: Precedence::Call, - }, - Token::LeftBracket => ParseRule { - prefix: Some(Compiler::parse_list), - infix: None, - precedence: Precedence::None, - }, - Token::Less => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::LessEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_comparison_binary), - precedence: Precedence::Comparison, - }, - Token::Let => ParseRule { - prefix: Some(Compiler::parse_let_statement), - infix: None, - precedence: Precedence::Assignment, - }, - Token::Loop => todo!(), - Token::Map => todo!(), - Token::Minus => ParseRule { - prefix: Some(Compiler::parse_unary), - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Term, - }, - Token::MinusEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Assignment, - }, - Token::Mut => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::Percent => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Factor, - }, - Token::PercentEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Assignment, - }, - Token::Plus => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Term, - }, - Token::PlusEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Assignment, - }, - Token::Return => ParseRule { - prefix: Some(Compiler::parse_return_statement), - infix: None, - precedence: Precedence::None, - }, - Token::RightBrace => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::RightParenthesis => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::RightBracket => ParseRule { - prefix: None, - infix: None, - precedence: Precedence::None, - }, - Token::Semicolon => ParseRule { - prefix: Some(Compiler::parse_semicolon), - infix: None, - precedence: Precedence::None, - }, - Token::Slash => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Factor, - }, - Token::SlashEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Assignment, - }, - Token::Star => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Factor, - }, - Token::StarEqual => ParseRule { - prefix: None, - infix: Some(Compiler::parse_math_binary), - precedence: Precedence::Assignment, - }, - Token::Str => ParseRule { - prefix: Some(Compiler::expect_expression), - infix: None, - precedence: Precedence::None, - }, - Token::String(_) => ParseRule { - prefix: Some(Compiler::parse_string), - infix: None, - precedence: Precedence::None, - }, - Token::Struct => todo!(), - Token::While => ParseRule { - prefix: Some(Compiler::parse_while), - infix: None, - precedence: Precedence::None, - }, - } - } -} diff --git a/dust-lang/src/compiler/parse_rule.rs b/dust-lang/src/compiler/parse_rule.rs new file mode 100644 index 0000000..90261c5 --- /dev/null +++ b/dust-lang/src/compiler/parse_rule.rs @@ -0,0 +1,320 @@ +use std::fmt::{self, Display, Formatter}; + +use crate::Token; + +use super::{CompileError, Compiler}; + +pub type Parser<'a> = fn(&mut Compiler<'a>) -> Result<(), CompileError>; + +/// Rule that defines how to parse a token. +#[derive(Debug, Clone, Copy)] +pub struct ParseRule<'a> { + pub prefix: Option>, + pub infix: Option>, + pub precedence: Precedence, +} + +impl From<&Token<'_>> for ParseRule<'_> { + fn from(token: &Token) -> Self { + match token { + Token::ArrowThin => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Async => todo!(), + Token::Bang => ParseRule { + prefix: Some(Compiler::parse_unary), + infix: None, + precedence: Precedence::Unary, + }, + Token::BangEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::Bool => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Boolean(_) => ParseRule { + prefix: Some(Compiler::parse_boolean), + infix: None, + precedence: Precedence::None, + }, + Token::Break => todo!(), + Token::Byte(_) => ParseRule { + prefix: Some(Compiler::parse_byte), + infix: None, + precedence: Precedence::None, + }, + Token::Character(_) => ParseRule { + prefix: Some(Compiler::parse_character), + infix: None, + precedence: Precedence::None, + }, + Token::Colon => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Comma => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::Dot => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::DoubleAmpersand => ParseRule { + prefix: None, + infix: Some(Compiler::parse_logical_binary), + precedence: Precedence::LogicalAnd, + }, + Token::DoubleEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::DoublePipe => ParseRule { + prefix: None, + infix: Some(Compiler::parse_logical_binary), + precedence: Precedence::LogicalOr, + }, + Token::DoubleDot => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Eof => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::Equal => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::Assignment, + }, + Token::Else => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::Float(_) => ParseRule { + prefix: Some(Compiler::parse_float), + infix: None, + precedence: Precedence::None, + }, + Token::FloatKeyword => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Fn => ParseRule { + prefix: Some(Compiler::parse_function), + infix: None, + precedence: Precedence::None, + }, + Token::Greater => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::GreaterEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::Identifier(_) => ParseRule { + prefix: Some(Compiler::parse_variable), + infix: None, + precedence: Precedence::None, + }, + Token::If => ParseRule { + prefix: Some(Compiler::parse_if), + infix: None, + precedence: Precedence::None, + }, + Token::Int => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::Integer(_) => ParseRule { + prefix: Some(Compiler::parse_integer), + infix: None, + precedence: Precedence::None, + }, + Token::LeftBrace => ParseRule { + prefix: Some(Compiler::parse_block), + infix: None, + precedence: Precedence::None, + }, + Token::LeftParenthesis => ParseRule { + prefix: Some(Compiler::parse_grouped), + infix: Some(Compiler::parse_call), + precedence: Precedence::Call, + }, + Token::LeftBracket => ParseRule { + prefix: Some(Compiler::parse_list), + infix: None, + precedence: Precedence::None, + }, + Token::Less => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::LessEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_comparison_binary), + precedence: Precedence::Comparison, + }, + Token::Let => ParseRule { + prefix: Some(Compiler::parse_let_statement), + infix: None, + precedence: Precedence::Assignment, + }, + Token::Loop => todo!(), + Token::Map => todo!(), + Token::Minus => ParseRule { + prefix: Some(Compiler::parse_unary), + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Term, + }, + Token::MinusEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Assignment, + }, + Token::Mut => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::Percent => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Factor, + }, + Token::PercentEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Assignment, + }, + Token::Plus => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Term, + }, + Token::PlusEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Assignment, + }, + Token::Return => ParseRule { + prefix: Some(Compiler::parse_return_statement), + infix: None, + precedence: Precedence::None, + }, + Token::RightBrace => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::RightParenthesis => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::RightBracket => ParseRule { + prefix: None, + infix: None, + precedence: Precedence::None, + }, + Token::Semicolon => ParseRule { + prefix: Some(Compiler::parse_semicolon), + infix: None, + precedence: Precedence::None, + }, + Token::Slash => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Factor, + }, + Token::SlashEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Assignment, + }, + Token::Star => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Factor, + }, + Token::StarEqual => ParseRule { + prefix: None, + infix: Some(Compiler::parse_math_binary), + precedence: Precedence::Assignment, + }, + Token::Str => ParseRule { + prefix: Some(Compiler::expect_expression), + infix: None, + precedence: Precedence::None, + }, + Token::String(_) => ParseRule { + prefix: Some(Compiler::parse_string), + infix: None, + precedence: Precedence::None, + }, + Token::Struct => todo!(), + Token::While => ParseRule { + prefix: Some(Compiler::parse_while), + infix: None, + precedence: Precedence::None, + }, + } + } +} + +/// Operator precedence levels. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum Precedence { + Primary = 9, + Call = 8, + Unary = 7, + Factor = 6, + Term = 5, + Comparison = 4, + LogicalAnd = 3, + LogicalOr = 2, + Assignment = 1, + None = 0, +} + +impl Precedence { + pub fn increment(&self) -> Self { + match self { + Precedence::None => Precedence::Assignment, + Precedence::Assignment => Precedence::LogicalOr, + Precedence::LogicalOr => Precedence::LogicalAnd, + Precedence::LogicalAnd => Precedence::Comparison, + Precedence::Comparison => Precedence::Term, + Precedence::Term => Precedence::Factor, + Precedence::Factor => Precedence::Unary, + Precedence::Unary => Precedence::Call, + Precedence::Call => Precedence::Primary, + Precedence::Primary => Precedence::Primary, + } + } +} + +impl Display for Precedence { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} diff --git a/dust-lang/src/value/mod.rs b/dust-lang/src/value/mod.rs index 6ce0bb1..317a0fc 100644 --- a/dust-lang/src/value/mod.rs +++ b/dust-lang/src/value/mod.rs @@ -26,6 +26,30 @@ pub enum Value { } impl Value { + pub fn boolean(boolean: bool) -> Self { + Value::Concrete(ConcreteValue::Boolean(boolean)) + } + + pub fn byte(byte: u8) -> Self { + Value::Concrete(ConcreteValue::Byte(byte)) + } + + pub fn character(character: char) -> Self { + Value::Concrete(ConcreteValue::Character(character)) + } + + pub fn float(float: f64) -> Self { + Value::Concrete(ConcreteValue::Float(float)) + } + + pub fn integer(integer: i64) -> Self { + Value::Concrete(ConcreteValue::Integer(integer)) + } + + pub fn string(string: DustString) -> Self { + Value::Concrete(ConcreteValue::String(string)) + } + pub fn as_boolean(&self) -> Option<&bool> { if let Value::Concrete(ConcreteValue::Boolean(value)) = self { Some(value) diff --git a/dust-lang/tests/logic/and.rs b/dust-lang/tests/logic/and.rs index ec5920e..68f9d6a 100644 --- a/dust-lang/tests/logic/and.rs +++ b/dust-lang/tests/logic/and.rs @@ -1,4 +1,5 @@ use dust_lang::*; +use smallvec::smallvec; #[test] fn true_and_true() { @@ -13,19 +14,27 @@ fn true_and_true() { value_parameters: None, return_type: Type::Boolean, }, - vec![ - (Instruction::load_boolean(0, true, false), Span(0, 4)), - (Instruction::test(Argument::Register(0), true), Span(5, 7)), - (Instruction::jump(1, true), Span(5, 7)), - (Instruction::load_boolean(1, true, false), Span(8, 12)), - (Instruction::r#return(true), Span(12, 12)), + smallvec![ + Instruction::load_boolean(0, true, false), + Instruction::test(0, true), + Instruction::jump(1, true), + Instruction::load_boolean(1, true, false), + Instruction::r#return(true), ], - vec![], + smallvec![ + Span(0, 4), + Span(5, 7), + Span(5, 7), + Span(8, 12), + Span(12, 12), + ], + smallvec![], + smallvec![], vec![] )) ); - assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true)))); + assert_eq!(run(source), Ok(Some(Value::boolean(true)))); } #[test] @@ -41,19 +50,27 @@ fn false_and_false() { value_parameters: None, return_type: Type::Boolean, }, - vec![ - (Instruction::load_boolean(0, false, false), Span(0, 5)), - (Instruction::test(Argument::Register(0), true), Span(6, 8)), - (Instruction::jump(1, true), Span(6, 8)), - (Instruction::load_boolean(1, false, false), Span(9, 14)), - (Instruction::r#return(true), Span(14, 14)), + smallvec![ + Instruction::load_boolean(0, false, false), + Instruction::test(0, true), + Instruction::jump(1, true), + Instruction::load_boolean(1, false, false), + Instruction::r#return(true), ], - vec![], + smallvec![ + Span(0, 5), + Span(6, 8), + Span(6, 8), + Span(9, 14), + Span(14, 14), + ], + smallvec![], + smallvec![], vec![] )) ); - assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false)))); + assert_eq!(run(source), Ok(Some(Value::boolean(false)))); } #[test] @@ -69,19 +86,27 @@ fn false_and_true() { value_parameters: None, return_type: Type::Boolean, }, - vec![ - (Instruction::load_boolean(0, false, false), Span(0, 5)), - (Instruction::test(Argument::Register(0), true), Span(6, 8)), - (Instruction::jump(1, true), Span(6, 8)), - (Instruction::load_boolean(1, true, false), Span(9, 13)), - (Instruction::r#return(true), Span(13, 13)), + smallvec![ + Instruction::load_boolean(0, false, false), + Instruction::test(0, true), + Instruction::jump(1, true), + Instruction::load_boolean(1, true, false), + Instruction::r#return(true), ], - vec![], + smallvec![ + Span(0, 5), + Span(6, 8), + Span(6, 8), + Span(9, 13), + Span(13, 13) + ], + smallvec![], + smallvec![], vec![] )) ); - assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false)))); + assert_eq!(run(source), Ok(Some(Value::boolean(false)))); } #[test] @@ -97,17 +122,25 @@ fn true_and_false() { value_parameters: None, return_type: Type::Boolean, }, - vec![ - (Instruction::load_boolean(0, true, false), Span(0, 4)), - (Instruction::test(Argument::Register(0), true), Span(5, 7)), - (Instruction::jump(1, true), Span(5, 7)), - (Instruction::load_boolean(1, false, false), Span(8, 13)), - (Instruction::r#return(true), Span(13, 13)), + smallvec![ + Instruction::load_boolean(0, true, false), + Instruction::test(0, true), + Instruction::jump(1, true), + Instruction::load_boolean(1, false, false), + Instruction::r#return(true), ], - vec![], + smallvec![ + Span(0, 4), + Span(5, 7), + Span(5, 7), + Span(8, 13), + Span(13, 13) + ], + smallvec![], + smallvec![], vec![] )) ); - assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false)))); + assert_eq!(run(source), Ok(Some(Value::boolean(false)))); }