Add destinations to instructions to support local destinations
This commit is contained in:
parent
ef22fa18b6
commit
d7880480b5
@ -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::<bool>().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,
|
||||
},
|
||||
|
@ -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);
|
||||
|
@ -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<Add> 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())
|
||||
|
@ -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<Call> 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())
|
||||
|
@ -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<CallNative> 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)
|
||||
}
|
||||
|
@ -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<Divide> 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())
|
||||
|
@ -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<GetLocal> 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)
|
||||
}
|
||||
}
|
||||
|
@ -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<LoadBoolean> 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)
|
||||
}
|
||||
|
@ -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<LoadConstant> 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)
|
||||
}
|
||||
|
@ -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<LoadList> 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)
|
||||
}
|
||||
}
|
||||
|
@ -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<LoadSelf> 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)
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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<Modulo> 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())
|
||||
|
@ -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<Multiply> 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())
|
||||
|
@ -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<Negate> 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())
|
||||
|
@ -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<Not> 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())
|
||||
|
@ -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<Subtract> 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())
|
||||
|
@ -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<TestSet> 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())
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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"),],
|
||||
|
@ -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![
|
||||
|
@ -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![
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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![
|
||||
|
Loading…
Reference in New Issue
Block a user