From d7880480b59605fa20e482a1bae8cad5148006f4 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 28 Nov 2024 01:10:49 -0500 Subject: [PATCH] Add destinations to instructions to support local destinations --- dust-lang/src/compiler.rs | 128 +++++++++----------- dust-lang/src/disassembler.rs | 8 +- dust-lang/src/instruction/add.rs | 19 ++- dust-lang/src/instruction/call.rs | 20 +++- dust-lang/src/instruction/call_native.rs | 20 +++- dust-lang/src/instruction/divide.rs | 19 ++- dust-lang/src/instruction/get_local.rs | 20 +++- dust-lang/src/instruction/load_boolean.rs | 20 +++- dust-lang/src/instruction/load_constant.rs | 20 +++- dust-lang/src/instruction/load_list.rs | 20 +++- dust-lang/src/instruction/load_self.rs | 23 +++- dust-lang/src/instruction/mod.rs | 131 +++++++++++++-------- dust-lang/src/instruction/modulo.rs | 19 ++- dust-lang/src/instruction/multiply.rs | 19 ++- dust-lang/src/instruction/negate.rs | 20 +++- dust-lang/src/instruction/not.rs | 20 +++- dust-lang/src/instruction/subtract.rs | 19 ++- dust-lang/src/instruction/test_set.rs | 20 +++- dust-lang/src/lib.rs | 2 +- dust-lang/src/optimizer.rs | 10 +- dust-lang/src/vm.rs | 2 +- dust-lang/tests/basic.rs | 14 ++- dust-lang/tests/comparison.rs | 24 ++-- dust-lang/tests/functions.rs | 28 +++-- dust-lang/tests/lists.rs | 44 ++++--- dust-lang/tests/logic.rs | 26 ++-- dust-lang/tests/loops.rs | 18 ++- dust-lang/tests/math.rs | 104 ++++++++++++---- dust-lang/tests/native_functions.rs | 10 +- dust-lang/tests/scopes.rs | 44 ++++--- dust-lang/tests/unary_operations.rs | 6 +- dust-lang/tests/variables.rs | 12 +- 32 files changed, 619 insertions(+), 290 deletions(-) diff --git a/dust-lang/src/compiler.rs b/dust-lang/src/compiler.rs index cb19bba..8b76650 100644 --- a/dust-lang/src/compiler.rs +++ b/dust-lang/src/compiler.rs @@ -14,14 +14,13 @@ use colored::Colorize; use crate::{ instruction::{ - Add, Call, CallNative, Close, DefineLocal, Divide, Equal, GetLocal, Jump, Less, LessEqual, - LoadBoolean, LoadConstant, LoadList, LoadSelf, Modulo, Move, Multiply, Negate, Not, Return, - SetLocal, Subtract, Test, + Call, CallNative, Close, DefineLocal, GetLocal, Jump, LoadBoolean, LoadConstant, LoadList, + LoadSelf, Move, Negate, Not, Return, SetLocal, Test, }, value::ConcreteValue, - AnnotatedError, Argument, Chunk, ChunkError, DustError, FunctionType, Instruction, LexError, - Lexer, Local, NativeFunction, Operation, Optimizer, Scope, Span, Token, TokenKind, TokenOwned, - Type, TypeConflict, + AnnotatedError, Argument, Chunk, ChunkError, Destination, DustError, FunctionType, Instruction, + LexError, Lexer, Local, NativeFunction, Operation, Optimizer, Scope, Span, Token, TokenKind, + TokenOwned, Type, TypeConflict, }; /// Compiles the input and returns a chunk. @@ -118,6 +117,8 @@ impl<'src> Compiler<'src> { .rev() .find_map(|(instruction, _, _)| { if instruction.yields_value() { + println!("{:?}", instruction); + Some(instruction.a() + 1) } else { None @@ -364,7 +365,7 @@ impl<'src> Compiler<'src> { ) -> Result<(), CompileError> { let r#type = constant.r#type(); let constant_index = self.chunk.push_or_get_constant(constant); - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let instruction = Instruction::from(LoadConstant { destination, constant_index, @@ -383,7 +384,7 @@ impl<'src> Compiler<'src> { self.advance()?; let boolean = text.parse::().unwrap(); - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let instruction = Instruction::from(LoadBoolean { destination, value: boolean, @@ -542,7 +543,7 @@ impl<'src> Compiler<'src> { }); }; - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let instruction = match operator.kind() { TokenKind::Bang => Instruction::from(Not { destination, @@ -576,10 +577,7 @@ impl<'src> Compiler<'src> { position: self.previous_position, } })?; - let push_back = !matches!( - instruction.operation(), - Operation::LoadConstant | Operation::GetLocal, - ); + let push_back = matches!(argument, Argument::Register(_)); Ok((argument, push_back)) } @@ -636,11 +634,7 @@ impl<'src> Compiler<'src> { .push((right_instruction, right_type, right_position)); } - let destination = if is_assignment { - left.index() - } else { - self.next_register() - }; + let destination = Destination::Register(self.next_register()); let instruction = match operator { Token::Plus | Token::PlusEqual => Instruction::add(destination, left, right), Token::Minus | Token::MinusEqual => Instruction::subtract(destination, left, right), @@ -688,16 +682,17 @@ impl<'src> Compiler<'src> { position: self.previous_position, } })?; - let left = left_instruction.destination_as_argument().ok_or_else(|| { - CompileError::ExpectedExpression { - found: self.previous_token.to_owned(), - position: left_position, - } - })?; + let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?; let operator = self.current_token; let operator_position = self.current_position; let rule = ParseRule::from(&operator); + if push_back_left { + self.chunk + .instructions_mut() + .push((left_instruction, left_type, left_position)); + } + self.advance()?; self.parse_sub_expression(&rule.precedence)?; @@ -708,43 +703,21 @@ impl<'src> Compiler<'src> { position: self.previous_position, } })?; - let right = right_instruction.destination_as_argument().ok_or_else(|| { - CompileError::ExpectedExpression { - found: self.previous_token.to_owned(), - position: right_position, - } - })?; + let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?; + + if push_back_right { + self.chunk + .instructions_mut() + .push((right_instruction, right_type, right_position)); + } + let comparison = match operator { - Token::DoubleEqual => Instruction::from(Equal { - value: true, - left, - right, - }), - Token::BangEqual => Instruction::from(Equal { - value: false, - left, - right, - }), - Token::Less => Instruction::from(Less { - value: true, - left, - right, - }), - Token::LessEqual => Instruction::from(LessEqual { - value: true, - left, - right, - }), - Token::Greater => Instruction::from(LessEqual { - value: false, - left, - right, - }), - Token::GreaterEqual => Instruction::from(Less { - value: false, - left, - right, - }), + Token::DoubleEqual => Instruction::equal(true, left, right), + Token::BangEqual => Instruction::equal(false, left, right), + Token::Less => Instruction::less(true, left, right), + Token::LessEqual => Instruction::less_equal(true, left, right), + Token::Greater => Instruction::less_equal(false, left, right), + Token::GreaterEqual => Instruction::less(false, left, right), _ => { return Err(CompileError::ExpectedTokenMultiple { expected: &[ @@ -760,19 +733,18 @@ impl<'src> Compiler<'src> { }) } }; - - let register = self.next_register(); + let destination = Destination::Register(self.next_register()); let jump = Instruction::from(Jump { offset: 1, is_positive: true, }); let load_true = Instruction::from(LoadBoolean { - destination: register, + destination, value: true, jump_next: true, }); let load_false = Instruction::from(LoadBoolean { - destination: register, + destination, value: false, jump_next: false, }); @@ -851,7 +823,7 @@ impl<'src> Compiler<'src> { } else if let Some(native_function) = NativeFunction::from_str(identifier) { return self.parse_native_call(native_function); } else if Some(identifier) == self.chunk.name().map(|string| string.as_str()) { - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let load_self = Instruction::from(LoadSelf { destination }); self.emit_instruction(load_self, Type::SelfChunk, start_position); @@ -901,7 +873,7 @@ impl<'src> Compiler<'src> { return Ok(()); } - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let get_local = Instruction::from(GetLocal { destination, local_index, @@ -980,7 +952,7 @@ impl<'src> Compiler<'src> { self.allow(Token::Comma)?; } - let destination = self.next_register(); + let destination = Destination::Register(self.next_register()); let end = self.current_position.1; let load_list = Instruction::from(LoadList { destination, @@ -1206,7 +1178,7 @@ impl<'src> Compiler<'src> { let argument_count = destination - start_register; let return_type = *function.r#type().return_type; let call_native = Instruction::from(CallNative { - destination, + destination: Destination::Register(destination), function, argument_count, }); @@ -1216,6 +1188,12 @@ impl<'src> Compiler<'src> { Ok(()) } + fn parse_semicolon(&mut self) -> Result<(), CompileError> { + self.advance()?; + + Ok(()) + } + fn parse_top_level(&mut self) -> Result<(), CompileError> { loop { self.parse(Precedence::None)?; @@ -1438,7 +1416,7 @@ impl<'src> Compiler<'src> { let function = ConcreteValue::Function(function_compiler.finish()); let constant_index = self.chunk.push_or_get_constant(function); let function_end = self.current_position.1; - let destination = self.next_register(); + let register = self.next_register(); self.lexer.skip_to(function_end); @@ -1450,13 +1428,13 @@ impl<'src> Compiler<'src> { self.current_scope, ); let load_constant = Instruction::from(LoadConstant { - destination, + destination: Destination::Register(register), constant_index, jump_next: false, }); let define_local = Instruction::from(DefineLocal { local_index, - register: destination, + register, is_mutable: false, }); @@ -1468,7 +1446,7 @@ impl<'src> Compiler<'src> { self.emit_instruction(define_local, Type::None, position); } else { let load_constant = Instruction::from(LoadConstant { - destination, + destination: Destination::Register(register), constant_index, jump_next: false, }); @@ -1542,10 +1520,10 @@ impl<'src> Compiler<'src> { } let end = self.current_position.1; - let destination = self.next_register(); + let register = self.next_register(); let argument_count = self.next_register() - function.index() - 1; let call = Instruction::from(Call { - destination, + destination: Destination::Register(register), function, argument_count, }); @@ -1875,7 +1853,7 @@ impl From<&Token<'_>> for ParseRule<'_> { precedence: Precedence::None, }, Token::Semicolon => ParseRule { - prefix: Some(Compiler::expect_expression), + prefix: Some(Compiler::parse_semicolon), infix: None, precedence: Precedence::None, }, diff --git a/dust-lang/src/disassembler.rs b/dust-lang/src/disassembler.rs index 6f831e7..e98d599 100644 --- a/dust-lang/src/disassembler.rs +++ b/dust-lang/src/disassembler.rs @@ -64,8 +64,8 @@ const CONSTANT_HEADER: [&str; 4] = [ const LOCAL_HEADER: [&str; 4] = [ "Locals", "------", - " i SCOPE MUTABLE TYPE IDENTIFIER ", - "--- ----- ------- ---------------- ----------------", + " i SCOPE MUTABLE TYPE IDENTIFIER ", + "--- ------- ------- ---------------- ----------------", ]; /// Builder that constructs a human-readable representation of a chunk. @@ -260,7 +260,7 @@ impl<'a> Disassembler<'a> { let position = position.to_string(); let operation = instruction.operation().to_string(); let r#type = r#type.to_string(); - let info = instruction.disassembly_info(self.chunk); + let info = instruction.disassembly_info(); let instruction_display = format!("{index:^3} {position:^10} {operation:13} {type:^16} {info:^34}"); @@ -291,7 +291,7 @@ impl<'a> Disassembler<'a> { .unwrap_or_else(|| "unknown".to_string()); let type_display = r#type.to_string(); let local_display = format!( - "{index:^3} {scope:5} {is_mutable:^7} {type_display:^16} {identifier_display:^16}" + "{index:^3} {scope:7} {is_mutable:^7} {type_display:^16} {identifier_display:^16}" ); self.push_details(&local_display); diff --git a/dust-lang/src/instruction/add.rs b/dust-lang/src/instruction/add.rs index 10a6ef5..f6da751 100644 --- a/dust-lang/src/instruction/add.rs +++ b/dust-lang/src/instruction/add.rs @@ -1,17 +1,22 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Add { - pub destination: u16, + pub destination: Destination, pub left: Argument, pub right: Argument, } impl From<&Instruction> for Add { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; let (left, right) = instruction.b_and_c_as_arguments(); Add { - destination: instruction.a(), + destination, left, right, } @@ -20,8 +25,14 @@ impl From<&Instruction> for Add { impl From for Instruction { fn from(add: Add) -> Self { + let (a, a_is_local) = match add.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Add) - .set_a(add.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(add.left.index()) .set_b_is_constant(add.left.is_constant()) .set_b_is_local(add.left.is_local()) diff --git a/dust-lang/src/instruction/call.rs b/dust-lang/src/instruction/call.rs index fd377f0..7fa1247 100644 --- a/dust-lang/src/instruction/call.rs +++ b/dust-lang/src/instruction/call.rs @@ -1,15 +1,21 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Call { - pub destination: u16, + pub destination: Destination, pub function: Argument, pub argument_count: u16, } impl From<&Instruction> for Call { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + Call { - destination: instruction.a(), + destination, function: instruction.b_as_argument(), argument_count: instruction.c(), } @@ -18,8 +24,14 @@ impl From<&Instruction> for Call { impl From for Instruction { fn from(call: Call) -> Self { + let (a, a_is_local) = match call.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Call) - .set_a(call.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(call.function.index()) .set_b_is_constant(call.function.is_constant()) .set_b_is_local(call.function.is_local()) diff --git a/dust-lang/src/instruction/call_native.rs b/dust-lang/src/instruction/call_native.rs index 2df039d..e35266b 100644 --- a/dust-lang/src/instruction/call_native.rs +++ b/dust-lang/src/instruction/call_native.rs @@ -1,15 +1,21 @@ -use crate::{Instruction, NativeFunction, Operation}; +use crate::{Destination, Instruction, NativeFunction, Operation}; pub struct CallNative { - pub destination: u16, + pub destination: Destination, pub function: NativeFunction, pub argument_count: u16, } impl From<&Instruction> for CallNative { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + CallNative { - destination: instruction.a(), + destination, function: NativeFunction::from(instruction.b()), argument_count: instruction.c(), } @@ -18,8 +24,14 @@ impl From<&Instruction> for CallNative { impl From for Instruction { fn from(call_native: CallNative) -> Self { + let (a, a_is_local) = match call_native.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::CallNative) - .set_a(call_native.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(call_native.function as u16) .set_c(call_native.argument_count) } diff --git a/dust-lang/src/instruction/divide.rs b/dust-lang/src/instruction/divide.rs index b86dbb3..85243a4 100644 --- a/dust-lang/src/instruction/divide.rs +++ b/dust-lang/src/instruction/divide.rs @@ -1,17 +1,22 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Divide { - pub destination: u16, + pub destination: Destination, pub left: Argument, pub right: Argument, } impl From<&Instruction> for Divide { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; let (left, right) = instruction.b_and_c_as_arguments(); Divide { - destination: instruction.a(), + destination, left, right, } @@ -20,8 +25,14 @@ impl From<&Instruction> for Divide { impl From for Instruction { fn from(divide: Divide) -> Self { + let (a, a_is_local) = match divide.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Divide) - .set_a(divide.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(divide.left.index()) .set_b_is_constant(divide.left.is_constant()) .set_b_is_local(divide.left.is_local()) diff --git a/dust-lang/src/instruction/get_local.rs b/dust-lang/src/instruction/get_local.rs index b2447cd..a2fc817 100644 --- a/dust-lang/src/instruction/get_local.rs +++ b/dust-lang/src/instruction/get_local.rs @@ -1,14 +1,20 @@ -use crate::{Instruction, Operation}; +use crate::{Destination, Instruction, Operation}; pub struct GetLocal { - pub destination: u16, + pub destination: Destination, pub local_index: u16, } impl From<&Instruction> for GetLocal { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + GetLocal { - destination: instruction.a(), + destination, local_index: instruction.b(), } } @@ -16,8 +22,14 @@ impl From<&Instruction> for GetLocal { impl From for Instruction { fn from(get_local: GetLocal) -> Self { + let (a, a_is_local) = match get_local.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::GetLocal) - .set_a(get_local.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(get_local.local_index) } } diff --git a/dust-lang/src/instruction/load_boolean.rs b/dust-lang/src/instruction/load_boolean.rs index 5025dc1..e3675de 100644 --- a/dust-lang/src/instruction/load_boolean.rs +++ b/dust-lang/src/instruction/load_boolean.rs @@ -1,15 +1,21 @@ -use crate::{Instruction, Operation}; +use crate::{Destination, Instruction, Operation}; pub struct LoadBoolean { - pub destination: u16, + pub destination: Destination, pub value: bool, pub jump_next: bool, } impl From<&Instruction> for LoadBoolean { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + LoadBoolean { - destination: instruction.a(), + destination, value: instruction.b_as_boolean(), jump_next: instruction.c_as_boolean(), } @@ -18,8 +24,14 @@ impl From<&Instruction> for LoadBoolean { impl From for Instruction { fn from(load_boolean: LoadBoolean) -> Self { + let (a, a_is_local) = match load_boolean.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::LoadBoolean) - .set_a(load_boolean.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b_to_boolean(load_boolean.value) .set_c_to_boolean(load_boolean.jump_next) } diff --git a/dust-lang/src/instruction/load_constant.rs b/dust-lang/src/instruction/load_constant.rs index a8aef2c..b6f0f2d 100644 --- a/dust-lang/src/instruction/load_constant.rs +++ b/dust-lang/src/instruction/load_constant.rs @@ -1,15 +1,21 @@ -use crate::{Instruction, Operation}; +use crate::{Destination, Instruction, Operation}; pub struct LoadConstant { - pub destination: u16, + pub destination: Destination, pub constant_index: u16, pub jump_next: bool, } impl From<&Instruction> for LoadConstant { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + LoadConstant { - destination: instruction.a(), + destination, constant_index: instruction.b(), jump_next: instruction.c_as_boolean(), } @@ -18,8 +24,14 @@ impl From<&Instruction> for LoadConstant { impl From for Instruction { fn from(load_constant: LoadConstant) -> Self { + let (a, a_is_local) = match load_constant.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::LoadConstant) - .set_a(load_constant.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(load_constant.constant_index) .set_c_to_boolean(load_constant.jump_next) } diff --git a/dust-lang/src/instruction/load_list.rs b/dust-lang/src/instruction/load_list.rs index 6dcfb39..3e6b987 100644 --- a/dust-lang/src/instruction/load_list.rs +++ b/dust-lang/src/instruction/load_list.rs @@ -1,14 +1,20 @@ -use crate::{Instruction, Operation}; +use crate::{Destination, Instruction, Operation}; pub struct LoadList { - pub destination: u16, + pub destination: Destination, pub start_register: u16, } impl From<&Instruction> for LoadList { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + LoadList { - destination: instruction.a(), + destination, start_register: instruction.b(), } } @@ -16,8 +22,14 @@ impl From<&Instruction> for LoadList { impl From for Instruction { fn from(load_list: LoadList) -> Self { + let (a, a_is_local) = match load_list.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::LoadList) - .set_a(load_list.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(load_list.start_register) } } diff --git a/dust-lang/src/instruction/load_self.rs b/dust-lang/src/instruction/load_self.rs index 04cabbd..66cf872 100644 --- a/dust-lang/src/instruction/load_self.rs +++ b/dust-lang/src/instruction/load_self.rs @@ -1,19 +1,30 @@ -use crate::{Instruction, Operation}; +use crate::{Destination, Instruction, Operation}; pub struct LoadSelf { - pub destination: u16, + pub destination: Destination, } impl From<&Instruction> for LoadSelf { fn from(instruction: &Instruction) -> Self { - LoadSelf { - destination: instruction.a(), - } + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + + LoadSelf { destination } } } impl From for Instruction { fn from(load_self: LoadSelf) -> Self { - *Instruction::new(Operation::LoadSelf).set_a(load_self.destination) + let (a, a_is_local) = match load_self.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + + *Instruction::new(Operation::LoadSelf) + .set_a(a) + .set_a_is_local(a_is_local) } } diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 1a99a84..d530985 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -40,7 +40,7 @@ mod subtract; mod test; mod test_set; -use std::fmt::{self, Display, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; pub use add::Add; pub use call::Call; @@ -70,8 +70,41 @@ pub use test_set::TestSet; use serde::{Deserialize, Serialize}; -use crate::{Chunk, NativeFunction, Operation}; +use crate::{NativeFunction, Operation}; +#[derive(Debug, Clone, Copy)] +pub enum Destination { + Local(u16), + Register(u16), +} + +impl Destination { + pub fn index(&self) -> u16 { + match self { + Destination::Local(index) => *index, + Destination::Register(index) => *index, + } + } + + pub fn is_local(&self) -> bool { + matches!(self, Destination::Local(_)) + } + + pub fn is_register(&self) -> bool { + matches!(self, Destination::Register(_)) + } +} + +impl Display for Destination { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Destination::Local(index) => write!(f, "L{index}"), + Destination::Register(index) => write!(f, "R{index}"), + } + } +} + +#[derive(Debug, Clone, Copy)] pub enum Argument { Constant(u16), Local(u16), @@ -113,7 +146,7 @@ impl Display for Argument { /// An operation and its arguments for the Dust virtual machine. /// /// See the [module-level documentation](index.html) for more information. -#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct Instruction(u64); impl Instruction { @@ -129,7 +162,7 @@ impl Instruction { Instruction::from(Close { from, to }) } - pub fn load_boolean(destination: u16, value: bool, jump_next: bool) -> Instruction { + pub fn load_boolean(destination: Destination, value: bool, jump_next: bool) -> Instruction { Instruction::from(LoadBoolean { destination, value, @@ -137,7 +170,11 @@ impl Instruction { }) } - pub fn load_constant(destination: u16, constant_index: u16, jump_next: bool) -> Instruction { + pub fn load_constant( + destination: Destination, + constant_index: u16, + jump_next: bool, + ) -> Instruction { Instruction::from(LoadConstant { destination, constant_index, @@ -145,14 +182,14 @@ impl Instruction { }) } - pub fn load_list(destination: u16, start_register: u16) -> Instruction { + pub fn load_list(destination: Destination, start_register: u16) -> Instruction { Instruction::from(LoadList { destination, start_register, }) } - pub fn load_self(destination: u16) -> Instruction { + pub fn load_self(destination: Destination) -> Instruction { Instruction::from(LoadSelf { destination }) } @@ -164,7 +201,7 @@ impl Instruction { }) } - pub fn get_local(destination: u16, local_index: u16) -> Instruction { + pub fn get_local(destination: Destination, local_index: u16) -> Instruction { Instruction::from(GetLocal { destination, local_index, @@ -178,7 +215,7 @@ impl Instruction { }) } - pub fn add(destination: u16, left: Argument, right: Argument) -> Instruction { + pub fn add(destination: Destination, left: Argument, right: Argument) -> Instruction { Instruction::from(Add { destination, left, @@ -186,7 +223,7 @@ impl Instruction { }) } - pub fn subtract(destination: u16, left: Argument, right: Argument) -> Instruction { + pub fn subtract(destination: Destination, left: Argument, right: Argument) -> Instruction { Instruction::from(Subtract { destination, left, @@ -194,7 +231,7 @@ impl Instruction { }) } - pub fn multiply(destination: u16, left: Argument, right: Argument) -> Instruction { + pub fn multiply(destination: Destination, left: Argument, right: Argument) -> Instruction { Instruction::from(Multiply { destination, left, @@ -202,7 +239,7 @@ impl Instruction { }) } - pub fn divide(destination: u16, left: Argument, right: Argument) -> Instruction { + pub fn divide(destination: Destination, left: Argument, right: Argument) -> Instruction { Instruction::from(Divide { destination, left, @@ -210,7 +247,7 @@ impl Instruction { }) } - pub fn modulo(destination: u16, left: Argument, right: Argument) -> Instruction { + pub fn modulo(destination: Destination, left: Argument, right: Argument) -> Instruction { Instruction::from(Modulo { destination, left, @@ -222,7 +259,7 @@ impl Instruction { Instruction::from(Test { argument, value }) } - pub fn test_set(destination: u16, argument: Argument, value: bool) -> Instruction { + pub fn test_set(destination: Destination, argument: Argument, value: bool) -> Instruction { Instruction::from(TestSet { destination, argument, @@ -242,14 +279,14 @@ impl Instruction { Instruction::from(LessEqual { value, left, right }) } - pub fn negate(destination: u16, argument: Argument) -> Instruction { + pub fn negate(destination: Destination, argument: Argument) -> Instruction { Instruction::from(Negate { destination, argument, }) } - pub fn not(destination: u16, argument: Argument) -> Instruction { + pub fn not(destination: Destination, argument: Argument) -> Instruction { Instruction::from(Not { destination, argument, @@ -263,7 +300,7 @@ impl Instruction { }) } - pub fn call(destination: u16, function: Argument, argument_count: u16) -> Instruction { + pub fn call(destination: Destination, function: Argument, argument_count: u16) -> Instruction { Instruction::from(Call { destination, function, @@ -272,7 +309,7 @@ impl Instruction { } pub fn call_native( - destination: u16, + destination: Destination, function: NativeFunction, argument_count: u16, ) -> Instruction { @@ -486,7 +523,7 @@ impl Instruction { } } - pub fn disassembly_info(&self, chunk: &Chunk) -> String { + pub fn disassembly_info(&self) -> String { match self.operation() { Operation::Move => { let Move { from, to } = Move::from(self); @@ -506,9 +543,9 @@ impl Instruction { } = LoadBoolean::from(self); if jump_next { - format!("R{destination} = {value} && JUMP +1") + format!("{destination} = {value} && JUMP +1") } else { - format!("R{destination} = {value}") + format!("{destination} = {value}") } } Operation::LoadConstant => { @@ -519,9 +556,9 @@ impl Instruction { } = LoadConstant::from(self); if jump_next { - format!("R{destination} = C{constant_index} JUMP +1") + format!("{destination} = C{constant_index} JUMP +1") } else { - format!("R{destination} = C{constant_index}") + format!("{destination} = C{constant_index}") } } Operation::LoadList => { @@ -529,18 +566,14 @@ impl Instruction { destination, start_register, } = LoadList::from(self); - let end_register = destination.saturating_sub(1); + let end_register = destination.index().saturating_sub(1); - format!("R{destination} = [R{start_register}..=R{end_register}]",) + format!("{destination} = [R{start_register}..=R{end_register}]",) } Operation::LoadSelf => { let LoadSelf { destination } = LoadSelf::from(self); - let name = chunk - .name() - .map(|idenifier| idenifier.as_str()) - .unwrap_or("self"); - format!("R{destination} = {name}") + format!("{destination} = self") } Operation::DefineLocal => { let DefineLocal { @@ -561,7 +594,7 @@ impl Instruction { local_index, } = GetLocal::from(self); - format!("R{destination} = L{local_index}") + format!("{destination} = L{local_index}") } Operation::SetLocal => { let SetLocal { @@ -578,7 +611,7 @@ impl Instruction { right, } = Add::from(self); - format!("R{destination} = {left} + {right}") + format!("{destination} = {left} + {right}") } Operation::Subtract => { let Subtract { @@ -587,7 +620,7 @@ impl Instruction { right, } = Subtract::from(self); - format!("R{destination} = {left} - {right}") + format!("{destination} = {left} - {right}") } Operation::Multiply => { let Multiply { @@ -596,7 +629,7 @@ impl Instruction { right, } = Multiply::from(self); - format!("R{destination} = {left} * {right}") + format!("{destination} = {left} * {right}") } Operation::Divide => { let Divide { @@ -605,7 +638,7 @@ impl Instruction { right, } = Divide::from(self); - format!("R{destination} = {left} / {right}") + format!("{destination} = {left} / {right}") } Operation::Modulo => { let Modulo { @@ -614,7 +647,7 @@ impl Instruction { right, } = Modulo::from(self); - format!("R{destination} = {left} % {right}") + format!("{destination} = {left} % {right}") } Operation::Test => { let Test { argument, value } = Test::from(self); @@ -630,7 +663,7 @@ impl Instruction { } = TestSet::from(self); let bang = if value { "" } else { "!" }; - format!("if {bang}{argument} {{ JUMP +1 }} else {{ R{destination} = {argument} }}") + format!("if {bang}{argument} {{ JUMP +1 }} else {{ {destination} = {argument} }}") } Operation::Equal => { let Equal { value, left, right } = Equal::from(self); @@ -639,7 +672,7 @@ impl Instruction { format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") } Operation::Less => { - let Equal { value, left, right } = Equal::from(self); + let Less { value, left, right } = Less::from(self); let comparison_symbol = if value { "<" } else { ">=" }; format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") @@ -656,7 +689,7 @@ impl Instruction { argument, } = Negate::from(self); - format!("R{destination} = -{argument}") + format!("{destination} = -{argument}") } Operation::Not => { let Not { @@ -664,7 +697,7 @@ impl Instruction { argument, } = Not::from(self); - format!("R{destination} = !{argument}") + format!("{destination} = !{argument}") } Operation::Jump => { let Jump { @@ -684,10 +717,10 @@ impl Instruction { function, argument_count, } = Call::from(self); - let first_argument = destination.saturating_sub(argument_count); - let last_argument = destination - 1; + let first_argument = destination.index().saturating_sub(argument_count); + let last_argument = destination.index() - 1; - format!("R{destination} = {function}(R{first_argument}..=R{last_argument})") + format!("{destination} = {function}(R{first_argument}..=R{last_argument})") } Operation::CallNative => { let CallNative { @@ -695,10 +728,10 @@ impl Instruction { function, argument_count, } = CallNative::from(self); - let first_argument = destination.saturating_sub(argument_count); - let last_argument = destination - 1; + let first_argument = destination.index().saturating_sub(argument_count); + let last_argument = destination.index() - 1; - format!("R{destination} = {function}(R{first_argument}..=R{last_argument})") + format!("{destination} = {function}(R{first_argument}..=R{last_argument})") } Operation::Return => { let Return { @@ -720,3 +753,9 @@ impl From<&Instruction> for u64 { instruction.0 } } + +impl Debug for Instruction { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{} {}", self.operation(), self.disassembly_info()) + } +} diff --git a/dust-lang/src/instruction/modulo.rs b/dust-lang/src/instruction/modulo.rs index 298017e..c50205d 100644 --- a/dust-lang/src/instruction/modulo.rs +++ b/dust-lang/src/instruction/modulo.rs @@ -1,17 +1,22 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Modulo { - pub destination: u16, + pub destination: Destination, pub left: Argument, pub right: Argument, } impl From<&Instruction> for Modulo { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; let (left, right) = instruction.b_and_c_as_arguments(); Modulo { - destination: instruction.a(), + destination, left, right, } @@ -20,8 +25,14 @@ impl From<&Instruction> for Modulo { impl From for Instruction { fn from(modulo: Modulo) -> Self { + let (a, a_is_local) = match modulo.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Modulo) - .set_a(modulo.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(modulo.left.index()) .set_b_is_constant(modulo.left.is_constant()) .set_b_is_local(modulo.left.is_local()) diff --git a/dust-lang/src/instruction/multiply.rs b/dust-lang/src/instruction/multiply.rs index 45ddea6..023a4d3 100644 --- a/dust-lang/src/instruction/multiply.rs +++ b/dust-lang/src/instruction/multiply.rs @@ -1,17 +1,22 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Multiply { - pub destination: u16, + pub destination: Destination, pub left: Argument, pub right: Argument, } impl From<&Instruction> for Multiply { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; let (left, right) = instruction.b_and_c_as_arguments(); Multiply { - destination: instruction.a(), + destination, left, right, } @@ -20,8 +25,14 @@ impl From<&Instruction> for Multiply { impl From for Instruction { fn from(multiply: Multiply) -> Self { + let (a, a_is_local) = match multiply.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Multiply) - .set_a(multiply.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(multiply.left.index()) .set_b_is_constant(multiply.left.is_constant()) .set_b_is_local(multiply.left.is_local()) diff --git a/dust-lang/src/instruction/negate.rs b/dust-lang/src/instruction/negate.rs index ccb1059..1340c9a 100644 --- a/dust-lang/src/instruction/negate.rs +++ b/dust-lang/src/instruction/negate.rs @@ -1,14 +1,20 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Negate { - pub destination: u16, + pub destination: Destination, pub argument: Argument, } impl From<&Instruction> for Negate { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + Negate { - destination: instruction.a(), + destination, argument: instruction.b_as_argument(), } } @@ -16,8 +22,14 @@ impl From<&Instruction> for Negate { impl From for Instruction { fn from(negate: Negate) -> Self { + let (a, a_is_local) = match negate.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Negate) - .set_a(negate.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(negate.argument.index()) .set_b_is_constant(negate.argument.is_constant()) .set_b_is_local(negate.argument.is_local()) diff --git a/dust-lang/src/instruction/not.rs b/dust-lang/src/instruction/not.rs index 0e16176..805e7d1 100644 --- a/dust-lang/src/instruction/not.rs +++ b/dust-lang/src/instruction/not.rs @@ -1,14 +1,20 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct Not { - pub destination: u16, + pub destination: Destination, pub argument: Argument, } impl From<&Instruction> for Not { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + Not { - destination: instruction.a(), + destination, argument: instruction.b_as_argument(), } } @@ -16,8 +22,14 @@ impl From<&Instruction> for Not { impl From for Instruction { fn from(not: Not) -> Self { + let (a, a_is_local) = match not.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::Not) - .set_a(not.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(not.argument.index()) .set_b_is_constant(not.argument.is_constant()) .set_b_is_local(not.argument.is_local()) diff --git a/dust-lang/src/instruction/subtract.rs b/dust-lang/src/instruction/subtract.rs index b8d8a67..482ce66 100644 --- a/dust-lang/src/instruction/subtract.rs +++ b/dust-lang/src/instruction/subtract.rs @@ -1,17 +1,22 @@ -use crate::{Argument, Instruction}; +use crate::{Argument, Destination, Instruction}; pub struct Subtract { - pub destination: u16, + pub destination: Destination, pub left: Argument, pub right: Argument, } impl From<&Instruction> for Subtract { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; let (left, right) = instruction.b_and_c_as_arguments(); Subtract { - destination: instruction.a(), + destination, left, right, } @@ -20,8 +25,14 @@ impl From<&Instruction> for Subtract { impl From for Instruction { fn from(subtract: Subtract) -> Self { + let (a, a_is_local) = match subtract.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(crate::Operation::Subtract) - .set_a(subtract.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(subtract.left.index()) .set_b_is_constant(subtract.left.is_constant()) .set_b_is_local(subtract.left.is_local()) diff --git a/dust-lang/src/instruction/test_set.rs b/dust-lang/src/instruction/test_set.rs index cac4096..281fdf7 100644 --- a/dust-lang/src/instruction/test_set.rs +++ b/dust-lang/src/instruction/test_set.rs @@ -1,15 +1,21 @@ -use crate::{Argument, Instruction, Operation}; +use crate::{Argument, Destination, Instruction, Operation}; pub struct TestSet { - pub destination: u16, + pub destination: Destination, pub argument: Argument, pub value: bool, } impl From<&Instruction> for TestSet { fn from(instruction: &Instruction) -> Self { + let destination = if instruction.a_is_local() { + Destination::Local(instruction.a()) + } else { + Destination::Register(instruction.a()) + }; + TestSet { - destination: instruction.a(), + destination, argument: instruction.b_as_argument(), value: instruction.c_as_boolean(), } @@ -18,8 +24,14 @@ impl From<&Instruction> for TestSet { impl From for Instruction { fn from(test_set: TestSet) -> Self { + let (a, a_is_local) = match test_set.destination { + Destination::Local(local) => (local, true), + Destination::Register(register) => (register, false), + }; + *Instruction::new(Operation::TestSet) - .set_a(test_set.destination) + .set_a(a) + .set_a_is_local(a_is_local) .set_b(test_set.argument.index()) .set_b_is_constant(test_set.argument.is_constant()) .set_b_is_local(test_set.argument.is_local()) diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 183fdc5..ced06c5 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -19,7 +19,7 @@ pub use crate::chunk::{Chunk, ChunkError, Local}; pub use crate::compiler::{compile, CompileError, Compiler}; pub use crate::disassembler::Disassembler; pub use crate::dust_error::{AnnotatedError, DustError}; -pub use crate::instruction::{Argument, Instruction}; +pub use crate::instruction::{Argument, Destination, Instruction}; pub use crate::lexer::{lex, LexError, Lexer}; pub use crate::native_function::{NativeFunction, NativeFunctionError}; pub use crate::operation::Operation; diff --git a/dust-lang/src/optimizer.rs b/dust-lang/src/optimizer.rs index 23051cc..1d86719 100644 --- a/dust-lang/src/optimizer.rs +++ b/dust-lang/src/optimizer.rs @@ -1,6 +1,6 @@ //! Tool used by the compiler to optimize a chunk's bytecode. -use crate::{Chunk, Instruction, Operation, Span, Type}; +use crate::{instruction::SetLocal, Chunk, Instruction, Operation, Span, Type}; /// An instruction optimizer that mutably borrows instructions from a chunk. #[derive(Debug)] @@ -83,10 +83,12 @@ impl<'a> Optimizer<'a> { log::debug!("Condensing math and SetLocal to math instruction"); let instructions = self.instructions_mut(); - let set_local = instructions.pop().unwrap().0; - let set_local_register = set_local.a(); + let set_local = SetLocal::from(&instructions.pop().unwrap().0); let math_instruction = instructions.last_mut().unwrap().0; - let math_instruction_new = *math_instruction.clone().set_a(set_local_register); + let math_instruction_new = *math_instruction + .clone() + .set_a(set_local.local_index) + .set_a_is_local(true); instructions.last_mut().unwrap().0 = math_instruction_new; diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 3e023c3..9c726d0 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -63,7 +63,7 @@ impl<'a> Vm<'a> { self.ip - 1, self.current_position, instruction.operation(), - instruction.disassembly_info(self.chunk) + instruction.disassembly_info() ); match instruction.operation() { diff --git a/dust-lang/tests/basic.rs b/dust-lang/tests/basic.rs index 62421d6..f6be57e 100644 --- a/dust-lang/tests/basic.rs +++ b/dust-lang/tests/basic.rs @@ -15,7 +15,7 @@ fn constant() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(0, 2) ), @@ -65,12 +65,20 @@ fn parentheses_precedence() { }, vec![ ( - Instruction::add(0, Argument::Constant(0), Argument::Constant(1)), + Instruction::add( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(1) + ), Type::Integer, Span(3, 4) ), ( - Instruction::multiply(1, Argument::Register(0), Argument::Constant(2)), + Instruction::multiply( + Destination::Register(1), + Argument::Register(0), + Argument::Constant(2) + ), Type::Integer, Span(8, 9) ), diff --git a/dust-lang/tests/comparison.rs b/dust-lang/tests/comparison.rs index e67fd69..1b19be9 100644 --- a/dust-lang/tests/comparison.rs +++ b/dust-lang/tests/comparison.rs @@ -21,12 +21,12 @@ fn equal() { ), (Instruction::jump(1, true), Type::None, Span(2, 4)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 4) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 4) ), @@ -61,12 +61,12 @@ fn greater() { ), (Instruction::jump(1, true), Type::None, Span(2, 3)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 3) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 3) ), @@ -101,12 +101,12 @@ fn greater_than_or_equal() { ), (Instruction::jump(1, true), Type::None, Span(2, 4)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 4) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 4) ), @@ -141,12 +141,12 @@ fn less_than() { ), (Instruction::jump(1, true), Type::None, Span(2, 3)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 3) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 3) ), @@ -181,12 +181,12 @@ fn less_than_or_equal() { ), (Instruction::jump(1, true), Type::None, Span(2, 4)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 4) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 4) ), @@ -221,12 +221,12 @@ fn not_equal() { ), (Instruction::jump(1, true), Type::None, Span(2, 4)), ( - Instruction::load_boolean(0, true, true), + Instruction::load_boolean(Destination::Register(0), true, true), Type::Boolean, Span(2, 4) ), ( - Instruction::load_boolean(0, false, false), + Instruction::load_boolean(Destination::Register(0), false, false), Type::Boolean, Span(2, 4) ), diff --git a/dust-lang/tests/functions.rs b/dust-lang/tests/functions.rs index cc65bd1..6eab230 100644 --- a/dust-lang/tests/functions.rs +++ b/dust-lang/tests/functions.rs @@ -19,7 +19,11 @@ fn function() { }, vec![ ( - Instruction::add(2, Argument::Local(0), Argument::Local(1)), + Instruction::add( + Destination::Register(2), + Argument::Local(0), + Argument::Local(1) + ), Type::Integer, Span(30, 31) ), @@ -49,7 +53,7 @@ fn function_call() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Function(FunctionType { type_parameters: None, value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]), @@ -58,17 +62,17 @@ fn function_call() { Span(0, 36) ), ( - Instruction::load_constant(1, 1, false), + Instruction::load_constant(Destination::Register(1), 1, false), Type::Integer, Span(36, 37) ), ( - Instruction::load_constant(2, 2, false), + Instruction::load_constant(Destination::Register(2), 2, false), Type::Integer, Span(39, 40) ), ( - Instruction::call(3, Argument::Constant(0), 2), + Instruction::call(Destination::Register(3), Argument::Constant(0), 2), Type::Integer, Span(35, 41) ), @@ -84,7 +88,11 @@ fn function_call() { }, vec![ ( - Instruction::add(2, Argument::Local(0), Argument::Local(1)), + Instruction::add( + Destination::Register(2), + Argument::Local(0), + Argument::Local(1) + ), Type::Integer, Span(30, 31) ), @@ -121,7 +129,7 @@ fn function_declaration() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Function(FunctionType { type_parameters: None, value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]), @@ -146,7 +154,11 @@ fn function_declaration() { }, vec![ ( - Instruction::add(2, Argument::Local(0), Argument::Local(1)), + Instruction::add( + Destination::Register(2), + Argument::Local(0), + Argument::Local(1) + ), Type::Integer, Span(35, 36) ), diff --git a/dust-lang/tests/lists.rs b/dust-lang/tests/lists.rs index 173485c..c8fcd5e 100644 --- a/dust-lang/tests/lists.rs +++ b/dust-lang/tests/lists.rs @@ -15,7 +15,7 @@ fn empty_list() { }, vec![ ( - Instruction::load_list(0, 0), + Instruction::load_list(Destination::Register(0), 0), Type::List(Box::new(Type::Any)), Span(0, 2) ), @@ -44,22 +44,22 @@ fn list() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(1, 2) ), ( - Instruction::load_constant(1, 1, false), + Instruction::load_constant(Destination::Register(1), 1, false), Type::Integer, Span(4, 5) ), ( - Instruction::load_constant(2, 2, false), + Instruction::load_constant(Destination::Register(2), 2, false), Type::Integer, Span(7, 8) ), ( - Instruction::load_list(3, 0), + Instruction::load_list(Destination::Register(3), 0), Type::List(Box::new(Type::Integer)), Span(0, 9) ), @@ -99,28 +99,40 @@ fn list_with_complex_expression() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(1, 2) ), ( - Instruction::add(1, Argument::Constant(1), Argument::Constant(2)), + Instruction::add( + Destination::Register(1), + Argument::Constant(1), + Argument::Constant(2) + ), Type::Integer, Span(6, 7) ), ( - Instruction::multiply(2, Argument::Constant(3), Argument::Constant(4)), + Instruction::multiply( + Destination::Register(2), + Argument::Constant(3), + Argument::Constant(4) + ), Type::Integer, Span(14, 15) ), ( - Instruction::subtract(3, Argument::Register(1), Argument::Register(2)), + Instruction::subtract( + Destination::Register(3), + Argument::Register(1), + Argument::Register(2) + ), Type::Integer, Span(10, 11) ), (Instruction::close(1, 3), Type::None, Span(17, 18)), ( - Instruction::load_list(4, 0), + Instruction::load_list(Destination::Register(4), 0), Type::List(Box::new(Type::Integer)), Span(0, 18) ), @@ -161,22 +173,26 @@ fn list_with_simple_expression() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(1, 2) ), ( - Instruction::add(1, Argument::Constant(1), Argument::Constant(2)), + Instruction::add( + Destination::Register(1), + Argument::Constant(1), + Argument::Constant(2) + ), Type::Integer, Span(6, 7) ), ( - Instruction::load_constant(2, 3, false), + Instruction::load_constant(Destination::Register(2), 3, false), Type::Integer, Span(11, 12) ), ( - Instruction::load_list(3, 0), + Instruction::load_list(Destination::Register(3), 0), Type::List(Box::new(Type::Integer)), Span(0, 13) ), diff --git a/dust-lang/tests/logic.rs b/dust-lang/tests/logic.rs index ccaf34f..0a5a533 100644 --- a/dust-lang/tests/logic.rs +++ b/dust-lang/tests/logic.rs @@ -15,7 +15,7 @@ fn and() { }, vec![ ( - Instruction::load_boolean(0, true, false), + Instruction::load_boolean(Destination::Register(0), true, false), Type::Boolean, Span(0, 4) ), @@ -26,7 +26,7 @@ fn and() { ), (Instruction::jump(1, true), Type::None, Span(5, 7)), ( - Instruction::load_boolean(1, false, false), + Instruction::load_boolean(Destination::Register(1), false, false), Type::Boolean, Span(8, 13) ), @@ -55,7 +55,7 @@ fn or() { }, vec![ ( - Instruction::load_boolean(0, true, false), + Instruction::load_boolean(Destination::Register(0), true, false), Type::Boolean, Span(0, 4) ), @@ -66,7 +66,7 @@ fn or() { ), (Instruction::jump(1, true), Type::None, Span(5, 7)), ( - Instruction::load_boolean(1, false, false), + Instruction::load_boolean(Destination::Register(1), false, false), Type::Boolean, Span(8, 13) ), @@ -95,7 +95,7 @@ fn variable_and() { }, vec![ ( - Instruction::load_boolean(0, true, false), + Instruction::load_boolean(Destination::Register(0), true, false), Type::Boolean, Span(8, 12) ), @@ -105,7 +105,7 @@ fn variable_and() { Span(4, 5) ), ( - Instruction::load_boolean(1, false, false), + Instruction::load_boolean(Destination::Register(1), false, false), Type::Boolean, Span(22, 27) ), @@ -114,14 +114,22 @@ fn variable_and() { Type::None, Span(18, 19) ), - (Instruction::get_local(2, 0), Type::Boolean, Span(29, 30)), ( - Instruction::test(Argument::Register(2), true), + Instruction::get_local(Destination::Register(2), 0), + Type::Boolean, + Span(29, 30) + ), + ( + Instruction::test(Argument::Local(0), true), Type::None, Span(31, 33) ), (Instruction::jump(1, true), Type::None, Span(31, 33)), - (Instruction::get_local(3, 1), Type::Boolean, Span(34, 35)), + ( + Instruction::get_local(Destination::Register(3), 1), + Type::Boolean, + Span(34, 35) + ), (Instruction::r#return(true), Type::None, Span(35, 35)), ], vec![ConcreteValue::string("a"), ConcreteValue::string("b"),], diff --git a/dust-lang/tests/loops.rs b/dust-lang/tests/loops.rs index 5a1be45..2ca09aa 100644 --- a/dust-lang/tests/loops.rs +++ b/dust-lang/tests/loops.rs @@ -15,7 +15,7 @@ fn r#while() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 13) ), @@ -25,18 +25,26 @@ fn r#while() { Span(8, 9) ), ( - Instruction::less(true, Argument::Register(0), Argument::Constant(2)), - Type::Integer, + Instruction::less(true, Argument::Local(0), Argument::Constant(2)), + Type::None, Span(23, 24) ), (Instruction::jump(2, true), Type::None, Span(41, 42)), ( - Instruction::add(0, Argument::Register(0), Argument::Constant(3)), + Instruction::add( + Destination::Local(0), + Argument::Local(0), + Argument::Constant(3) + ), Type::Integer, Span(35, 36) ), (Instruction::jump(3, false), Type::None, Span(41, 42)), - (Instruction::get_local(1, 0), Type::Integer, Span(41, 42)), + ( + Instruction::get_local(Destination::Register(1), 0), + Type::Integer, + Span(41, 42) + ), (Instruction::r#return(true), Type::None, Span(42, 42)), ], vec![ diff --git a/dust-lang/tests/math.rs b/dust-lang/tests/math.rs index 03a5ff3..150214f 100644 --- a/dust-lang/tests/math.rs +++ b/dust-lang/tests/math.rs @@ -15,7 +15,11 @@ fn add() { }, vec![ ( - Instruction::add(0, Argument::Constant(0), Argument::Constant(1)), + Instruction::add( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(1) + ), Type::Integer, Span(2, 3) ), @@ -44,7 +48,7 @@ fn add_assign() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 13) ), @@ -54,11 +58,19 @@ fn add_assign() { Span(8, 9) ), ( - Instruction::add(0, Argument::Register(0), Argument::Constant(2)), + Instruction::add( + Destination::Register(0), + Argument::Register(0), + Argument::Constant(2) + ), Type::Integer, Span(17, 19) ), - (Instruction::get_local(1, 0), Type::Integer, Span(23, 24)), + ( + Instruction::get_local(Destination::Register(1), 0), + Type::Integer, + Span(23, 24) + ), (Instruction::r#return(true), Type::None, Span(24, 24)) ], vec![ @@ -120,7 +132,11 @@ fn divide() { }, vec![ ( - Instruction::divide(0, Argument::Constant(0), Argument::Constant(0)), + Instruction::divide( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(0) + ), Type::Integer, Span(2, 3) ), @@ -149,7 +165,7 @@ fn divide_assign() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 13) ), @@ -159,11 +175,19 @@ fn divide_assign() { Span(8, 9) ), ( - Instruction::divide(0, Argument::Register(0), Argument::Constant(0)), + Instruction::divide( + Destination::Register(0), + Argument::Register(0), + Argument::Constant(0) + ), Type::Integer, Span(17, 19) ), - (Instruction::get_local(1, 0), Type::Integer, Span(23, 24)), + ( + Instruction::get_local(Destination::Register(1), 0), + Type::Integer, + Span(23, 24) + ), (Instruction::r#return(true), Type::None, Span(24, 24)) ], vec![ConcreteValue::Integer(2), ConcreteValue::string("a")], @@ -205,22 +229,38 @@ fn math_operator_precedence() { }, vec![ ( - Instruction::add(0, Argument::Constant(0), Argument::Constant(1)), + Instruction::add( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(1) + ), Type::Integer, Span(2, 3) ), ( - Instruction::multiply(1, Argument::Constant(2), Argument::Constant(3)), + Instruction::multiply( + Destination::Register(1), + Argument::Constant(2), + Argument::Constant(3) + ), Type::Integer, Span(10, 11) ), ( - Instruction::divide(2, Argument::Register(1), Argument::Constant(4)), + Instruction::divide( + Destination::Register(2), + Argument::Register(1), + Argument::Constant(4) + ), Type::Integer, Span(14, 15) ), ( - Instruction::subtract(3, Argument::Register(0), Argument::Register(2)), + Instruction::subtract( + Destination::Register(3), + Argument::Register(0), + Argument::Register(2) + ), Type::Integer, Span(6, 7) ), @@ -255,7 +295,11 @@ fn multiply() { }, vec![ ( - Instruction::multiply(0, Argument::Constant(0), Argument::Constant(1)), + Instruction::multiply( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(1) + ), Type::Integer, Span(2, 3) ), @@ -284,7 +328,7 @@ fn multiply_assign() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 13) ), @@ -294,11 +338,19 @@ fn multiply_assign() { Span(8, 9) ), ( - Instruction::multiply(0, Argument::Register(0), Argument::Constant(2)), + Instruction::multiply( + Destination::Register(0), + Argument::Register(0), + Argument::Constant(2) + ), Type::Integer, Span(17, 19) ), - (Instruction::get_local(1, 0), Type::Integer, Span(22, 23)), + ( + Instruction::get_local(Destination::Register(1), 0), + Type::Integer, + Span(22, 23) + ), (Instruction::r#return(true), Type::None, Span(23, 23)) ], vec![ @@ -344,7 +396,11 @@ fn subtract() { }, vec![ ( - Instruction::subtract(0, Argument::Constant(0), Argument::Constant(1)), + Instruction::subtract( + Destination::Register(0), + Argument::Constant(0), + Argument::Constant(1) + ), Type::Integer, Span(2, 3) ), @@ -373,7 +429,7 @@ fn subtract_assign() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 14) ), @@ -383,11 +439,19 @@ fn subtract_assign() { Span(8, 9) ), ( - Instruction::subtract(0, Argument::Register(0), Argument::Constant(2)), + Instruction::subtract( + Destination::Register(0), + Argument::Register(0), + Argument::Constant(2) + ), Type::Integer, Span(18, 20) ), - (Instruction::get_local(1, 0), Type::Integer, Span(24, 25)), + ( + Instruction::get_local(Destination::Register(1), 0), + Type::Integer, + Span(24, 25) + ), (Instruction::r#return(true), Type::None, Span(25, 25)), ], vec![ diff --git a/dust-lang/tests/native_functions.rs b/dust-lang/tests/native_functions.rs index c398264..4b83b21 100644 --- a/dust-lang/tests/native_functions.rs +++ b/dust-lang/tests/native_functions.rs @@ -15,17 +15,17 @@ fn panic() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::String, Span(6, 22) ), ( - Instruction::load_constant(1, 1, false), + Instruction::load_constant(Destination::Register(1), 1, false), Type::Integer, Span(24, 26) ), ( - Instruction::call_native(2, NativeFunction::Panic, 2), + Instruction::call_native(Destination::Register(2), NativeFunction::Panic, 2), Type::None, Span(0, 27) ), @@ -66,12 +66,12 @@ fn to_string() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(10, 12) ), ( - Instruction::call_native(1, NativeFunction::ToString, 1), + Instruction::call_native(Destination::Register(1), NativeFunction::ToString, 1), Type::String, Span(0, 13) ), diff --git a/dust-lang/tests/scopes.rs b/dust-lang/tests/scopes.rs index 01342d1..c34d33b 100644 --- a/dust-lang/tests/scopes.rs +++ b/dust-lang/tests/scopes.rs @@ -37,7 +37,7 @@ fn block_scope() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(17, 18) ), @@ -47,7 +47,7 @@ fn block_scope() { Span(13, 14) ), ( - Instruction::load_constant(1, 2, false), + Instruction::load_constant(Destination::Register(1), 2, false), Type::Integer, Span(50, 52) ), @@ -57,7 +57,7 @@ fn block_scope() { Span(46, 47) ), ( - Instruction::load_constant(2, 4, false), + Instruction::load_constant(Destination::Register(2), 4, false), Type::Integer, Span(92, 93) ), @@ -67,7 +67,7 @@ fn block_scope() { Span(88, 89) ), ( - Instruction::load_constant(3, 6, false), + Instruction::load_constant(Destination::Register(3), 6, false), Type::Integer, Span(129, 130) ), @@ -77,7 +77,7 @@ fn block_scope() { Span(125, 126) ), ( - Instruction::load_constant(4, 4, false), + Instruction::load_constant(Destination::Register(4), 4, false), Type::Integer, Span(158, 159) ), @@ -145,7 +145,7 @@ fn multiple_block_scopes() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(17, 18) ), @@ -155,7 +155,7 @@ fn multiple_block_scopes() { Span(13, 14) ), ( - Instruction::load_constant(1, 2, false), + Instruction::load_constant(Destination::Register(1), 2, false), Type::Integer, Span(50, 52) ), @@ -165,7 +165,7 @@ fn multiple_block_scopes() { Span(46, 47) ), ( - Instruction::load_constant(2, 4, false), + Instruction::load_constant(Destination::Register(2), 4, false), Type::Integer, Span(92, 93) ), @@ -174,20 +174,28 @@ fn multiple_block_scopes() { Type::None, Span(88, 89) ), - (Instruction::get_local(3, 1), Type::Integer, Span(129, 130)), + ( + Instruction::get_local(Destination::Register(3), 1), + Type::Integer, + Span(129, 130) + ), ( Instruction::define_local(3, 3, false), Type::None, Span(125, 126) ), - (Instruction::get_local(4, 0), Type::Integer, Span(158, 159)), + ( + Instruction::get_local(Destination::Register(4), 0), + Type::Integer, + Span(158, 159) + ), ( Instruction::define_local(4, 4, false), Type::None, Span(154, 155) ), ( - Instruction::load_constant(5, 2, false), + Instruction::load_constant(Destination::Register(5), 2, false), Type::Integer, Span(191, 193) ), @@ -197,7 +205,7 @@ fn multiple_block_scopes() { Span(187, 188) ), ( - Instruction::load_constant(6, 4, false), + Instruction::load_constant(Destination::Register(6), 4, false), Type::Integer, Span(233, 234) ), @@ -206,13 +214,21 @@ fn multiple_block_scopes() { Type::None, Span(229, 230) ), - (Instruction::get_local(7, 5), Type::Integer, Span(270, 271)), + ( + Instruction::get_local(Destination::Register(7), 5), + Type::Integer, + Span(270, 271) + ), ( Instruction::define_local(7, 7, false), Type::None, Span(266, 267) ), - (Instruction::get_local(8, 0), Type::Integer, Span(299, 300)), + ( + Instruction::get_local(Destination::Register(8), 0), + Type::Integer, + Span(299, 300) + ), ( Instruction::define_local(8, 8, false), Type::None, diff --git a/dust-lang/tests/unary_operations.rs b/dust-lang/tests/unary_operations.rs index 8392a4f..8e289c5 100644 --- a/dust-lang/tests/unary_operations.rs +++ b/dust-lang/tests/unary_operations.rs @@ -15,7 +15,7 @@ fn negate() { }, vec![ ( - Instruction::negate(0, Argument::Constant(0)), + Instruction::negate(Destination::Register(0), Argument::Constant(0)), Type::Integer, Span(0, 1) ), @@ -44,12 +44,12 @@ fn not() { }, vec![ ( - Instruction::load_boolean(0, true, false), + Instruction::load_boolean(Destination::Register(0), true, false), Type::Boolean, Span(1, 5) ), ( - Instruction::not(1, Argument::Register(0)), + Instruction::not(Destination::Register(1), Argument::Register(0)), Type::Boolean, Span(0, 1) ), diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index e5e0fcb..bdd7254 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -15,7 +15,7 @@ fn define_local() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(8, 10) ), @@ -66,7 +66,7 @@ fn set_local() { }, vec![ ( - Instruction::load_constant(0, 0, false), + Instruction::load_constant(Destination::Register(0), 0, false), Type::Integer, Span(12, 14) ), @@ -76,12 +76,16 @@ fn set_local() { Span(8, 9) ), ( - Instruction::load_constant(1, 2, false), + Instruction::load_constant(Destination::Register(1), 2, false), Type::Integer, Span(20, 22) ), (Instruction::set_local(1, 0), Type::None, Span(16, 17)), - (Instruction::get_local(2, 0), Type::Integer, Span(24, 25)), + ( + Instruction::get_local(Destination::Register(2), 0), + Type::Integer, + Span(24, 25) + ), (Instruction::r#return(true), Type::None, Span(25, 25)), ], vec![