Begin implementing typed 64-bit instructions
This commit is contained in:
parent
22d46e7b6d
commit
0510e18060
62
dust-lang/src/chunk/constant_table.rs
Normal file
62
dust-lang/src/chunk/constant_table.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::DustString;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||||
|
pub struct ConstantTable {
|
||||||
|
pub r#true: bool,
|
||||||
|
pub r#false: bool,
|
||||||
|
pub bytes: Vec<u8>,
|
||||||
|
pub characters: Vec<char>,
|
||||||
|
pub floats: Vec<f64>,
|
||||||
|
pub integers: Vec<i64>,
|
||||||
|
pub strings: Vec<DustString>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstantTable {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
r#true: false,
|
||||||
|
r#false: false,
|
||||||
|
bytes: Vec::new(),
|
||||||
|
characters: Vec::new(),
|
||||||
|
floats: Vec::new(),
|
||||||
|
integers: Vec::new(),
|
||||||
|
strings: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
pub fn with_data(
|
||||||
|
booleans: (bool, bool),
|
||||||
|
bytes: impl Into<Vec<u8>>,
|
||||||
|
characters: impl Into<Vec<char>>,
|
||||||
|
floats: impl Into<Vec<f64>>,
|
||||||
|
integers: impl Into<Vec<i64>>,
|
||||||
|
strings: impl Into<Vec<DustString>>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
r#true: booleans.0,
|
||||||
|
r#false: booleans.1,
|
||||||
|
bytes: bytes.into(),
|
||||||
|
characters: characters.into(),
|
||||||
|
floats: floats.into(),
|
||||||
|
integers: integers.into(),
|
||||||
|
strings: strings.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
(if self.r#true { 1 } else { 0 })
|
||||||
|
+ (if self.r#false { 1 } else { 0 })
|
||||||
|
+ self.bytes.len()
|
||||||
|
+ self.characters.len()
|
||||||
|
+ self.floats.len()
|
||||||
|
+ self.integers.len()
|
||||||
|
+ self.strings.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,7 @@ use std::io::{self, Write};
|
|||||||
|
|
||||||
use colored::{ColoredString, Colorize};
|
use colored::{ColoredString, Colorize};
|
||||||
|
|
||||||
use crate::{Chunk, Local};
|
use crate::{Chunk, Local, Type};
|
||||||
|
|
||||||
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
|
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
|
||||||
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 24)];
|
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 24)];
|
||||||
@ -322,6 +322,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
let identifier_display = self
|
let identifier_display = self
|
||||||
.chunk
|
.chunk
|
||||||
.constants
|
.constants
|
||||||
|
.strings
|
||||||
.get(*identifier_index as usize)
|
.get(*identifier_index as usize)
|
||||||
.map(|value| value.to_string())
|
.map(|value| value.to_string())
|
||||||
.unwrap_or_else(|| "unknown".to_string());
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
@ -352,8 +353,88 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
self.write_center_border(&column_name_line)?;
|
self.write_center_border(&column_name_line)?;
|
||||||
self.write_center_border(CONSTANT_BORDERS[1])?;
|
self.write_center_border(CONSTANT_BORDERS[1])?;
|
||||||
|
|
||||||
for (index, value) in self.chunk.constants.iter().enumerate() {
|
if self.chunk.constants.r#true {
|
||||||
let type_display = value.r#type().to_string();
|
let type_display = Type::Boolean.to_string();
|
||||||
|
let value_display = "true";
|
||||||
|
let constant_display = format!("│{:^5}│{:^26}│{:^26}│", 0, type_display, value_display);
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.chunk.constants.r#false {
|
||||||
|
let type_display = Type::Boolean.to_string();
|
||||||
|
let value_display = "false";
|
||||||
|
let constant_display = format!("│{:^5}│{:^26}│{:^26}│", 1, type_display, value_display);
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.constants.bytes.iter().enumerate() {
|
||||||
|
let type_display = Type::Byte.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.constants.characters.iter().enumerate() {
|
||||||
|
let type_display = Type::Character.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.constants.floats.iter().enumerate() {
|
||||||
|
let type_display = Type::Float.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.constants.integers.iter().enumerate() {
|
||||||
|
let type_display = Type::Integer.to_string();
|
||||||
|
let value_display = {
|
||||||
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
|
if value_string.len() > 26 {
|
||||||
|
value_string = format!("{value_string:.23}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_string
|
||||||
|
};
|
||||||
|
let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│");
|
||||||
|
|
||||||
|
self.write_center_border(&constant_display)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, value) in self.chunk.constants.strings.iter().enumerate() {
|
||||||
|
let type_display = Type::String.to_string();
|
||||||
let value_display = {
|
let value_display = {
|
||||||
let mut value_string = value.to_string();
|
let mut value_string = value.to_string();
|
||||||
|
|
||||||
@ -374,7 +455,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_prototype_section(&mut self) -> Result<(), io::Error> {
|
pub fn write_prototype_section(&mut self) -> Result<(), io::Error> {
|
||||||
self.write_center_border_bold("Functions")?;
|
self.write_center_border_bold("Prototypes")?;
|
||||||
|
|
||||||
for chunk in &self.chunk.prototypes {
|
for chunk in &self.chunk.prototypes {
|
||||||
chunk
|
chunk
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
//! Scoped variable.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Scope;
|
use crate::Scope;
|
||||||
|
|
||||||
/// A scoped variable.
|
/// Scoped variable.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
/// The index of the identifier in the constants table.
|
/// Index of the identifier in the constants list.
|
||||||
pub identifier_index: u8,
|
pub identifier_index: u16,
|
||||||
|
|
||||||
/// Stack index where the local's value is stored.
|
/// Index of the register where the variable's value is stored.
|
||||||
pub register_index: u8,
|
pub register_index: u16,
|
||||||
|
|
||||||
/// Whether the local is mutable.
|
/// Whether the local is mutable.
|
||||||
pub is_mutable: bool,
|
pub is_mutable: bool,
|
||||||
@ -20,7 +22,7 @@ pub struct Local {
|
|||||||
|
|
||||||
impl Local {
|
impl Local {
|
||||||
/// Creates a new Local instance.
|
/// Creates a new Local instance.
|
||||||
pub fn new(identifier_index: u8, register_index: u8, is_mutable: bool, scope: Scope) -> Self {
|
pub fn new(identifier_index: u16, register_index: u16, is_mutable: bool, scope: Scope) -> Self {
|
||||||
Self {
|
Self {
|
||||||
identifier_index,
|
identifier_index,
|
||||||
register_index,
|
register_index,
|
||||||
|
@ -13,10 +13,12 @@
|
|||||||
//! [`Chunk::with_data`] can be used to create a chunk for comparison to the compiler output. Do not
|
//! [`Chunk::with_data`] can be used to create a chunk for comparison to the compiler output. Do not
|
||||||
//! try to run these chunks in a virtual machine. Due to their missing stack size and record index,
|
//! try to run these chunks in a virtual machine. Due to their missing stack size and record index,
|
||||||
//! they will cause a panic or undefined behavior.
|
//! they will cause a panic or undefined behavior.
|
||||||
|
mod constant_table;
|
||||||
mod disassembler;
|
mod disassembler;
|
||||||
mod local;
|
mod local;
|
||||||
mod scope;
|
mod scope;
|
||||||
|
|
||||||
|
pub use constant_table::ConstantTable;
|
||||||
pub use disassembler::Disassembler;
|
pub use disassembler::Disassembler;
|
||||||
pub use local::Local;
|
pub use local::Local;
|
||||||
pub use scope::Scope;
|
pub use scope::Scope;
|
||||||
@ -27,7 +29,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{DustString, Function, FunctionType, Instruction, Span, Value};
|
use crate::{DustString, Function, FunctionType, Instruction, Span};
|
||||||
|
|
||||||
/// Representation of a Dust program or function.
|
/// Representation of a Dust program or function.
|
||||||
///
|
///
|
||||||
@ -39,12 +41,12 @@ pub struct Chunk {
|
|||||||
|
|
||||||
pub(crate) instructions: Vec<Instruction>,
|
pub(crate) instructions: Vec<Instruction>,
|
||||||
pub(crate) positions: Vec<Span>,
|
pub(crate) positions: Vec<Span>,
|
||||||
pub(crate) constants: Vec<Value>,
|
pub(crate) constants: ConstantTable,
|
||||||
pub(crate) locals: Vec<Local>,
|
pub(crate) locals: Vec<Local>,
|
||||||
pub(crate) prototypes: Vec<Arc<Chunk>>,
|
pub(crate) prototypes: Vec<Arc<Chunk>>,
|
||||||
|
|
||||||
pub(crate) register_count: usize,
|
pub(crate) register_count: usize,
|
||||||
pub(crate) prototype_index: u8,
|
pub(crate) prototype_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
@ -54,7 +56,7 @@ impl Chunk {
|
|||||||
r#type: FunctionType,
|
r#type: FunctionType,
|
||||||
instructions: impl Into<Vec<Instruction>>,
|
instructions: impl Into<Vec<Instruction>>,
|
||||||
positions: impl Into<Vec<Span>>,
|
positions: impl Into<Vec<Span>>,
|
||||||
constants: impl Into<Vec<Value>>,
|
constants: ConstantTable,
|
||||||
locals: impl Into<Vec<Local>>,
|
locals: impl Into<Vec<Local>>,
|
||||||
prototypes: impl IntoIterator<Item = Chunk>,
|
prototypes: impl IntoIterator<Item = Chunk>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -63,7 +65,7 @@ impl Chunk {
|
|||||||
r#type,
|
r#type,
|
||||||
instructions: instructions.into(),
|
instructions: instructions.into(),
|
||||||
positions: positions.into(),
|
positions: positions.into(),
|
||||||
constants: constants.into(),
|
constants,
|
||||||
locals: locals.into(),
|
locals: locals.into(),
|
||||||
prototypes: prototypes.into_iter().map(Arc::new).collect(),
|
prototypes: prototypes.into_iter().map(Arc::new).collect(),
|
||||||
register_count: 0,
|
register_count: 0,
|
||||||
|
@ -33,9 +33,10 @@ use std::{mem::replace, sync::Arc};
|
|||||||
use optimize::control_flow_register_consolidation;
|
use optimize::control_flow_register_consolidation;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Argument, Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
|
Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
|
||||||
NativeFunction, Operation, Scope, Span, Token, TokenKind, Type, Value,
|
NativeFunction, Operand, Operation, Scope, Span, Token, TokenKind, Type, Value,
|
||||||
instruction::{CallNative, Close, GetLocal, Jump, LoadList, Negate, Not, Return, SetLocal},
|
chunk::ConstantTable,
|
||||||
|
instruction::{GetLocal, Jump, LoadList},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compiles the input and returns a chunk.
|
/// Compiles the input and returns a chunk.
|
||||||
@ -88,7 +89,7 @@ pub struct Compiler<'src> {
|
|||||||
|
|
||||||
/// Constants that have been compiled. These are assigned to the chunk when [`Compiler::finish`]
|
/// Constants that have been compiled. These are assigned to the chunk when [`Compiler::finish`]
|
||||||
/// is called.
|
/// is called.
|
||||||
constants: Vec<Value>,
|
constants: ConstantTable,
|
||||||
|
|
||||||
/// Block-local variables and their types. The locals are assigned to the chunk when
|
/// Block-local variables and their types. The locals are assigned to the chunk when
|
||||||
/// [`Compiler::finish`] is called. The types are discarded after compilation.
|
/// [`Compiler::finish`] is called. The types are discarded after compilation.
|
||||||
@ -104,7 +105,7 @@ pub struct Compiler<'src> {
|
|||||||
|
|
||||||
/// The first register index that the compiler should use. This is used to avoid reusing the
|
/// The first register index that the compiler should use. This is used to avoid reusing the
|
||||||
/// registers that are used for the function's arguments.
|
/// registers that are used for the function's arguments.
|
||||||
minimum_register: u8,
|
minimum_register: u16,
|
||||||
|
|
||||||
/// Index of the current block. This is used to determine the scope of locals and is incremented
|
/// Index of the current block. This is used to determine the scope of locals and is incremented
|
||||||
/// when a new block is entered.
|
/// when a new block is entered.
|
||||||
@ -115,7 +116,7 @@ pub struct Compiler<'src> {
|
|||||||
|
|
||||||
/// Index of the Chunk in its parent's prototype list. This is set to 0 for the main chunk but
|
/// Index of the Chunk in its parent's prototype list. This is set to 0 for the main chunk but
|
||||||
/// that value is never read because the main chunk is not a callable function.
|
/// that value is never read because the main chunk is not a callable function.
|
||||||
prototype_index: u8,
|
prototype_index: u16,
|
||||||
|
|
||||||
/// Whether the chunk is the program's main chunk. This is used to prevent recursive calls to
|
/// Whether the chunk is the program's main chunk. This is used to prevent recursive calls to
|
||||||
/// the main chunk.
|
/// the main chunk.
|
||||||
@ -144,7 +145,7 @@ impl<'src> Compiler<'src> {
|
|||||||
return_type: Type::None,
|
return_type: Type::None,
|
||||||
},
|
},
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
constants: Vec::new(),
|
constants: ConstantTable::new(),
|
||||||
locals: Vec::new(),
|
locals: Vec::new(),
|
||||||
prototypes: Vec::new(),
|
prototypes: Vec::new(),
|
||||||
stack_size: 0,
|
stack_size: 0,
|
||||||
@ -215,7 +216,7 @@ impl<'src> Compiler<'src> {
|
|||||||
r#type: self.r#type,
|
r#type: self.r#type,
|
||||||
instructions,
|
instructions,
|
||||||
positions,
|
positions,
|
||||||
constants: self.constants.to_vec(),
|
constants: self.constants,
|
||||||
locals,
|
locals,
|
||||||
prototypes: self.prototypes,
|
prototypes: self.prototypes,
|
||||||
register_count: self.stack_size,
|
register_count: self.stack_size,
|
||||||
@ -227,7 +228,7 @@ impl<'src> Compiler<'src> {
|
|||||||
matches!(self.current_token, Token::Eof)
|
matches!(self.current_token, Token::Eof)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_register(&self) -> u8 {
|
fn next_register(&self) -> u16 {
|
||||||
self.instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
@ -260,7 +261,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_local(&self, index: u8) -> Result<&(Local, Type), CompileError> {
|
fn get_local(&self, index: u16) -> Result<&(Local, Type), CompileError> {
|
||||||
self.locals
|
self.locals
|
||||||
.get(index as usize)
|
.get(index as usize)
|
||||||
.ok_or(CompileError::UndeclaredVariable {
|
.ok_or(CompileError::UndeclaredVariable {
|
||||||
@ -269,22 +270,19 @@ impl<'src> Compiler<'src> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_local_index(&self, identifier_text: &str) -> Result<u8, CompileError> {
|
fn get_local_index(&self, identifier_text: &str) -> Result<u16, CompileError> {
|
||||||
self.locals
|
self.locals
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(index, (local, _))| {
|
.find_map(|(index, (local, _))| {
|
||||||
let constant = self.constants.get(local.identifier_index as usize)?;
|
let identifier = self
|
||||||
let identifier =
|
.constants
|
||||||
if let Value::Concrete(ConcreteValue::String(identifier)) = constant {
|
.strings
|
||||||
identifier
|
.get(local.identifier_index as usize)?;
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
if identifier == identifier_text {
|
if identifier == identifier_text {
|
||||||
Some(index as u8)
|
Some(index as u16)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -298,16 +296,16 @@ impl<'src> Compiler<'src> {
|
|||||||
fn declare_local(
|
fn declare_local(
|
||||||
&mut self,
|
&mut self,
|
||||||
identifier: &str,
|
identifier: &str,
|
||||||
register_index: u8,
|
register_index: u16,
|
||||||
r#type: Type,
|
r#type: Type,
|
||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
) -> (u8, u8) {
|
) -> (u16, u16) {
|
||||||
info!("Declaring local {identifier}");
|
info!("Declaring local {identifier}");
|
||||||
|
|
||||||
let identifier = Value::Concrete(ConcreteValue::string(identifier));
|
let identifier = DustString::from(identifier);
|
||||||
let identifier_index = self.push_or_get_constant(identifier);
|
let identifier_index = self.push_or_get_constant_string(identifier);
|
||||||
let local_index = self.locals.len() as u8;
|
let local_index = self.locals.len() as u16;
|
||||||
|
|
||||||
self.locals.push((
|
self.locals.push((
|
||||||
Local::new(identifier_index, register_index, is_mutable, scope),
|
Local::new(identifier_index, register_index, is_mutable, scope),
|
||||||
@ -317,29 +315,107 @@ impl<'src> Compiler<'src> {
|
|||||||
(local_index, identifier_index)
|
(local_index, identifier_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_identifier(&self, local_index: u8) -> Option<String> {
|
fn get_identifier(&self, local_index: u16) -> Option<String> {
|
||||||
self.locals
|
self.locals
|
||||||
.get(local_index as usize)
|
.get(local_index as usize)
|
||||||
.and_then(|(local, _)| {
|
.and_then(|(local, _)| {
|
||||||
self.constants
|
self.constants
|
||||||
|
.strings
|
||||||
.get(local.identifier_index as usize)
|
.get(local.identifier_index as usize)
|
||||||
.map(|value| value.to_string())
|
.map(|value| value.to_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_or_get_constant(&mut self, value: Value) -> u8 {
|
fn push_or_get_constant_bool(&mut self, boolean: bool) -> u16 {
|
||||||
|
if boolean {
|
||||||
|
if self.constants.r#true {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
self.constants.r#true = true;
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
} else if self.constants.r#false {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
self.constants.r#false = true;
|
||||||
|
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_or_get_constant_byte(&mut self, new_byte: u8) -> u16 {
|
||||||
if let Some(index) = self
|
if let Some(index) = self
|
||||||
.constants
|
.constants
|
||||||
|
.bytes
|
||||||
.iter()
|
.iter()
|
||||||
.position(|constant| constant == &value)
|
.position(|&byte| byte == new_byte)
|
||||||
{
|
{
|
||||||
index as u8
|
index as u16
|
||||||
} else {
|
} else {
|
||||||
let index = self.constants.len() as u8;
|
self.constants.bytes.push(new_byte);
|
||||||
|
|
||||||
self.constants.push(value);
|
(self.constants.bytes.len() - 1) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
index
|
fn push_or_get_constant_character(&mut self, new_character: char) -> u16 {
|
||||||
|
if let Some(index) = self
|
||||||
|
.constants
|
||||||
|
.characters
|
||||||
|
.iter()
|
||||||
|
.position(|&character| character == new_character)
|
||||||
|
{
|
||||||
|
index as u16
|
||||||
|
} else {
|
||||||
|
self.constants.characters.push(new_character);
|
||||||
|
|
||||||
|
(self.constants.characters.len() - 1) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_or_get_constant_float(&mut self, new_float: f64) -> u16 {
|
||||||
|
if let Some(index) = self
|
||||||
|
.constants
|
||||||
|
.floats
|
||||||
|
.iter()
|
||||||
|
.position(|&float| float == new_float)
|
||||||
|
{
|
||||||
|
index as u16
|
||||||
|
} else {
|
||||||
|
self.constants.floats.push(new_float);
|
||||||
|
|
||||||
|
(self.constants.floats.len() - 1) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_or_get_constant_integer(&mut self, new_integer: i64) -> u16 {
|
||||||
|
if let Some(index) = self
|
||||||
|
.constants
|
||||||
|
.integers
|
||||||
|
.iter()
|
||||||
|
.position(|&integer| integer == new_integer)
|
||||||
|
{
|
||||||
|
index as u16
|
||||||
|
} else {
|
||||||
|
self.constants.integers.push(new_integer);
|
||||||
|
|
||||||
|
(self.constants.integers.len() - 1) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_or_get_constant_string(&mut self, new_string: DustString) -> u16 {
|
||||||
|
if let Some(index) = self
|
||||||
|
.constants
|
||||||
|
.strings
|
||||||
|
.iter()
|
||||||
|
.position(|string| *string == new_string)
|
||||||
|
{
|
||||||
|
index as u16
|
||||||
|
} else {
|
||||||
|
self.constants.strings.push(new_string);
|
||||||
|
|
||||||
|
(self.constants.strings.len() - 1) as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +469,7 @@ impl<'src> Compiler<'src> {
|
|||||||
.unwrap_or(Type::None)
|
.unwrap_or(Type::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_register_type(&self, register_index: u8) -> Result<Type, CompileError> {
|
fn get_register_type(&self, register_index: u16) -> Result<Type, CompileError> {
|
||||||
if let Some((_, r#type)) = self
|
if let Some((_, r#type)) = self
|
||||||
.locals
|
.locals
|
||||||
.iter()
|
.iter()
|
||||||
@ -481,6 +557,14 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_boolean_constant(&mut self, boolean: bool, position: Span) {
|
||||||
|
let constant_index = self.push_or_get_constant_bool(boolean);
|
||||||
|
let destination = self.next_register();
|
||||||
|
let load_boolean = Instruction::load_constant(destination, constant_index, jump_next);
|
||||||
|
|
||||||
|
self.emit_instruction(load_boolean, Type::Boolean, position);
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_boolean(&mut self) -> Result<(), CompileError> {
|
fn parse_boolean(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
@ -651,15 +735,10 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let instruction = match operator.kind() {
|
let instruction = match (operator, &previous_type) {
|
||||||
TokenKind::Bang => Instruction::from(Not {
|
(Token::Bang, Type::Boolean) => Instruction::not(destination, argument),
|
||||||
destination,
|
(Token::Minus, Type::Float) => Instruction::negate_float(destination, argument),
|
||||||
argument,
|
(Token::Minus, Type::Integer) => Instruction::negate_int(destination, argument),
|
||||||
}),
|
|
||||||
TokenKind::Minus => Instruction::from(Negate {
|
|
||||||
destination,
|
|
||||||
argument,
|
|
||||||
}),
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompileError::ExpectedTokenMultiple {
|
return Err(CompileError::ExpectedTokenMultiple {
|
||||||
expected: &[TokenKind::Bang, TokenKind::Minus],
|
expected: &[TokenKind::Bang, TokenKind::Minus],
|
||||||
@ -677,34 +756,62 @@ impl<'src> Compiler<'src> {
|
|||||||
fn handle_binary_argument(
|
fn handle_binary_argument(
|
||||||
&mut self,
|
&mut self,
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
) -> Result<(Argument, bool), CompileError> {
|
) -> Result<(Operand, bool), CompileError> {
|
||||||
let (argument, push_back) = match instruction.operation() {
|
let (argument, push_back) = match instruction.operation() {
|
||||||
Operation::LOAD_CONSTANT => (Argument::Constant(instruction.b_field()), false),
|
Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false),
|
||||||
Operation::GET_LOCAL => {
|
Operation::GET_LOCAL => {
|
||||||
let local_index = instruction.b_field();
|
let local_index = instruction.b_field();
|
||||||
let (local, _) = self.get_local(local_index)?;
|
let (local, _) = self.get_local(local_index)?;
|
||||||
|
|
||||||
(Argument::Register(local.register_index), false)
|
(Operand::Register(local.register_index), false)
|
||||||
}
|
}
|
||||||
Operation::LOAD_BOOLEAN
|
Operation::LOAD_BOOLEAN
|
||||||
| Operation::LOAD_LIST
|
| Operation::LOAD_LIST
|
||||||
| Operation::LOAD_SELF
|
| Operation::LOAD_SELF
|
||||||
| Operation::ADD
|
| Operation::ADD_BYTE
|
||||||
| Operation::SUBTRACT
|
| Operation::ADD_CHAR
|
||||||
| Operation::MULTIPLY
|
| Operation::ADD_CHAR_STR
|
||||||
| Operation::DIVIDE
|
| Operation::ADD_FLOAT
|
||||||
| Operation::MODULO
|
| Operation::ADD_INT
|
||||||
| Operation::EQUAL
|
| Operation::ADD_STR
|
||||||
| Operation::LESS
|
| Operation::ADD_STR_CHAR
|
||||||
| Operation::LESS_EQUAL
|
| Operation::SUBTRACT_BYTE
|
||||||
| Operation::NEGATE
|
| Operation::SUBTRACT_FLOAT
|
||||||
|
| Operation::SUBTRACT_INT
|
||||||
|
| Operation::MULTIPLY_BYTE
|
||||||
|
| Operation::MULTIPLY_FLOAT
|
||||||
|
| Operation::MULTIPLY_INT
|
||||||
|
| Operation::DIVIDE_BYTE
|
||||||
|
| Operation::DIVIDE_FLOAT
|
||||||
|
| Operation::DIVIDE_INT
|
||||||
|
| Operation::MODULO_BYTE
|
||||||
|
| Operation::MODULO_INT
|
||||||
|
| Operation::MODULO_FLOAT
|
||||||
|
| Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::NEGATE_INT
|
||||||
|
| Operation::NEGATE_FLOAT
|
||||||
| Operation::NOT
|
| Operation::NOT
|
||||||
| Operation::CALL => (Argument::Register(instruction.a_field()), true),
|
| Operation::CALL => (Operand::Register(instruction.a_field()), true),
|
||||||
Operation::CALL_NATIVE => {
|
Operation::CALL_NATIVE => {
|
||||||
let function = NativeFunction::from(instruction.b_field());
|
let function = NativeFunction::from(instruction.b_field());
|
||||||
|
|
||||||
if function.returns_value() {
|
if function.returns_value() {
|
||||||
(Argument::Register(instruction.a_field()), true)
|
(Operand::Register(instruction.a_field()), true)
|
||||||
} else {
|
} else {
|
||||||
return Err(CompileError::ExpectedExpression {
|
return Err(CompileError::ExpectedExpression {
|
||||||
found: self.previous_token.to_owned(),
|
found: self.previous_token.to_owned(),
|
||||||
@ -786,7 +893,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if push_back_right {
|
if push_back_right {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((right_instruction, right_type, right_position));
|
.push((right_instruction, right_type.clone(), right_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
let r#type = if is_assignment {
|
let r#type = if is_assignment {
|
||||||
@ -798,18 +905,70 @@ impl<'src> Compiler<'src> {
|
|||||||
};
|
};
|
||||||
let destination = if is_assignment {
|
let destination = if is_assignment {
|
||||||
match left {
|
match left {
|
||||||
Argument::Register(register) => register,
|
Operand::Register(register) => register,
|
||||||
Argument::Constant(_) => self.next_register(),
|
Operand::Constant(_) => self.next_register(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.next_register()
|
self.next_register()
|
||||||
};
|
};
|
||||||
let instruction = match operator {
|
let instruction = match (operator, left_type, right_type) {
|
||||||
Token::Plus | Token::PlusEqual => Instruction::add(destination, left, right),
|
(Token::Plus, Type::Byte, Type::Byte) => {
|
||||||
Token::Minus | Token::MinusEqual => Instruction::subtract(destination, left, right),
|
Instruction::add_byte(destination, left, right)
|
||||||
Token::Star | Token::StarEqual => Instruction::multiply(destination, left, right),
|
}
|
||||||
Token::Slash | Token::SlashEqual => Instruction::divide(destination, left, right),
|
(Token::Plus, Type::Character, Type::Character) => {
|
||||||
Token::Percent | Token::PercentEqual => Instruction::modulo(destination, left, right),
|
Instruction::add_char(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Plus, Type::Character, Type::String) => {
|
||||||
|
Instruction::add_char_str(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Plus, Type::Float, Type::Float) => {
|
||||||
|
Instruction::add_float(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Plus, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::add_int(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Plus, Type::String, Type::Character) => {
|
||||||
|
Instruction::add_str_char(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Plus, Type::String, Type::String) => {
|
||||||
|
Instruction::add_str(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Minus, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::subtract_byte(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Minus, Type::Float, Type::Float) => {
|
||||||
|
Instruction::subtract_float(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Minus, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::subtract_int(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Star, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::multiply_byte(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Star, Type::Float, Type::Float) => {
|
||||||
|
Instruction::multiply_float(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Star, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::multiply_int(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Slash, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::divide_byte(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Slash, Type::Float, Type::Float) => {
|
||||||
|
Instruction::divide_float(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Slash, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::divide_int(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Percent, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::modulo_byte(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Percent, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::modulo_int(destination, left, right)
|
||||||
|
}
|
||||||
|
(Token::Percent, Type::Float, Type::Float) => {
|
||||||
|
Instruction::modulo_float(destination, left, right)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompileError::ExpectedTokenMultiple {
|
return Err(CompileError::ExpectedTokenMultiple {
|
||||||
expected: &[
|
expected: &[
|
||||||
@ -836,13 +995,9 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
||||||
if let Some(
|
if self
|
||||||
[
|
.get_last_operation()
|
||||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
.is_some_and(|operation| operation.is_comparison())
|
||||||
_,
|
|
||||||
_,
|
|
||||||
],
|
|
||||||
) = self.get_last_operations()
|
|
||||||
{
|
{
|
||||||
return Err(CompileError::ComparisonChain {
|
return Err(CompileError::ComparisonChain {
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
@ -863,7 +1018,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if push_back_left {
|
if push_back_left {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((left_instruction, left_type, left_position));
|
.push((left_instruction, left_type.clone(), left_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
@ -880,17 +1035,111 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if push_back_right {
|
if push_back_right {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((right_instruction, right_type, right_position));
|
.push((right_instruction, right_type.clone(), right_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let comparison = match operator {
|
let comparison = match (operator, left_type, right_type) {
|
||||||
Token::DoubleEqual => Instruction::equal(true, left, right),
|
(Token::DoubleEqual, Type::Boolean, Type::Boolean) => {
|
||||||
Token::BangEqual => Instruction::equal(false, left, right),
|
Instruction::equal_bool(true, left, right)
|
||||||
Token::Less => Instruction::less(true, left, right),
|
}
|
||||||
Token::LessEqual => Instruction::less_equal(true, left, right),
|
(Token::DoubleEqual, Type::Byte, Type::Byte) => {
|
||||||
Token::Greater => Instruction::less_equal(false, left, right),
|
Instruction::equal_byte(true, left, right)
|
||||||
Token::GreaterEqual => Instruction::less(false, left, right),
|
}
|
||||||
|
(Token::DoubleEqual, Type::Character, Type::Character) => {
|
||||||
|
Instruction::equal_char(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::DoubleEqual, Type::Character, Type::String) => {
|
||||||
|
Instruction::equal_char_str(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::DoubleEqual, Type::Float, Type::Float) => {
|
||||||
|
Instruction::equal_float(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::DoubleEqual, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::equal_int(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::DoubleEqual, Type::String, Type::String) => {
|
||||||
|
Instruction::equal_str(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::DoubleEqual, Type::String, Type::Character) => {
|
||||||
|
Instruction::equal_str_char(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Boolean, Type::Boolean) => {
|
||||||
|
Instruction::equal_bool(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::equal_byte(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Character, Type::Character) => {
|
||||||
|
Instruction::equal_char(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Character, Type::String) => {
|
||||||
|
Instruction::equal_char_str(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Float, Type::Float) => {
|
||||||
|
Instruction::equal_float(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::equal_int(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::String, Type::String) => {
|
||||||
|
Instruction::equal_str(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::BangEqual, Type::String, Type::Character) => {
|
||||||
|
Instruction::equal_str_char(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::Less, Type::Byte, Type::Byte) => Instruction::less_byte(true, left, right),
|
||||||
|
(Token::Less, Type::Character, Type::Character) => {
|
||||||
|
Instruction::less_char(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::Less, Type::Float, Type::Float) => Instruction::less_float(true, left, right),
|
||||||
|
(Token::Less, Type::Integer, Type::Integer) => Instruction::less_int(true, left, right),
|
||||||
|
(Token::Less, Type::String, Type::String) => Instruction::less_str(true, left, right),
|
||||||
|
(Token::GreaterEqual, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::less_byte(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::GreaterEqual, Type::Character, Type::Character) => {
|
||||||
|
Instruction::less_char(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::GreaterEqual, Type::Float, Type::Float) => {
|
||||||
|
Instruction::less_float(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::GreaterEqual, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::less_int(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::GreaterEqual, Type::String, Type::String) => {
|
||||||
|
Instruction::less_str(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::LessEqual, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::less_equal_byte(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::LessEqual, Type::Character, Type::Character) => {
|
||||||
|
Instruction::less_equal_char(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::LessEqual, Type::Float, Type::Float) => {
|
||||||
|
Instruction::less_equal_float(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::LessEqual, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::less_equal_int(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::LessEqual, Type::String, Type::String) => {
|
||||||
|
Instruction::less_equal_str(true, left, right)
|
||||||
|
}
|
||||||
|
(Token::Greater, Type::Byte, Type::Byte) => {
|
||||||
|
Instruction::less_equal_byte(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::Greater, Type::Character, Type::Character) => {
|
||||||
|
Instruction::less_equal_char(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::Greater, Type::Float, Type::Float) => {
|
||||||
|
Instruction::less_equal_float(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::Greater, Type::Integer, Type::Integer) => {
|
||||||
|
Instruction::less_equal_int(false, left, right)
|
||||||
|
}
|
||||||
|
(Token::Greater, Type::String, Type::String) => {
|
||||||
|
Instruction::less_equal_str(false, left, right)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompileError::ExpectedTokenMultiple {
|
return Err(CompileError::ExpectedTokenMultiple {
|
||||||
expected: &[
|
expected: &[
|
||||||
@ -974,7 +1223,23 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
instructions[0].0.operation(),
|
instructions[0].0.operation(),
|
||||||
Operation::TEST | Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL
|
Operation::TEST
|
||||||
|
| Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
| Operation::LESS_EQUAL_FLOAT
|
||||||
) || !matches!(instructions[1].0.operation(), Operation::JUMP)
|
) || !matches!(instructions[1].0.operation(), Operation::JUMP)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -982,7 +1247,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
let old_jump = &mut instructions[1].0;
|
let old_jump = &mut instructions[1].0;
|
||||||
let jump_index = instructions_length - group_index * 3 - 1;
|
let jump_index = instructions_length - group_index * 3 - 1;
|
||||||
let short_circuit_distance = (instructions_length - jump_index) as u8;
|
let short_circuit_distance = (instructions_length - jump_index) as u16;
|
||||||
|
|
||||||
*old_jump = Instruction::jump(short_circuit_distance, true);
|
*old_jump = Instruction::jump(short_circuit_distance, true);
|
||||||
}
|
}
|
||||||
@ -1009,7 +1274,7 @@ impl<'src> Compiler<'src> {
|
|||||||
return self.parse_call_native(native_function);
|
return self.parse_call_native(native_function);
|
||||||
} else if self.function_name.as_deref() == Some(identifier) && !self.is_main {
|
} else if self.function_name.as_deref() == Some(identifier) && !self.is_main {
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let load_self = Instruction::load_self(destination);
|
let load_self = Instruction::load_self(destination, false);
|
||||||
|
|
||||||
self.emit_instruction(load_self, Type::SelfFunction, start_position);
|
self.emit_instruction(load_self, Type::SelfFunction, start_position);
|
||||||
|
|
||||||
@ -1056,10 +1321,7 @@ impl<'src> Compiler<'src> {
|
|||||||
math_instruction.set_a_field(local_register_index);
|
math_instruction.set_a_field(local_register_index);
|
||||||
} else {
|
} else {
|
||||||
let register = self.next_register() - 1;
|
let register = self.next_register() - 1;
|
||||||
let set_local = Instruction::from(SetLocal {
|
let set_local = Instruction::set_local(register, local_index);
|
||||||
register_index: register,
|
|
||||||
local_index,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(set_local, Type::None, start_position);
|
self.emit_instruction(set_local, Type::None, start_position);
|
||||||
}
|
}
|
||||||
@ -1134,10 +1396,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if expected_register < actual_register {
|
if expected_register < actual_register {
|
||||||
let close = Instruction::from(Close {
|
let close = Instruction::close(expected_register, actual_register);
|
||||||
from: expected_register,
|
|
||||||
to: actual_register,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(close, Type::None, self.current_position);
|
self.emit_instruction(close, Type::None, self.current_position);
|
||||||
}
|
}
|
||||||
@ -1147,10 +1406,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let end = self.previous_position.1;
|
let end = self.previous_position.1;
|
||||||
let load_list = Instruction::from(LoadList {
|
let load_list = Instruction::load_list(destination, start_register, false);
|
||||||
destination,
|
|
||||||
start_register,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(load_list, Type::List(Box::new(item_type)), Span(start, end));
|
self.emit_instruction(load_list, Type::List(Box::new(item_type)), Span(start, end));
|
||||||
|
|
||||||
@ -1164,7 +1420,22 @@ impl<'src> Compiler<'src> {
|
|||||||
if matches!(
|
if matches!(
|
||||||
self.get_last_operations(),
|
self.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
| Operation::LESS_EQUAL_FLOAT,
|
||||||
Operation::JUMP,
|
Operation::JUMP,
|
||||||
Operation::LOAD_BOOLEAN,
|
Operation::LOAD_BOOLEAN,
|
||||||
Operation::LOAD_BOOLEAN
|
Operation::LOAD_BOOLEAN
|
||||||
@ -1194,7 +1465,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let if_block_end = self.instructions.len();
|
let if_block_end = self.instructions.len();
|
||||||
let mut if_block_distance = (if_block_end - if_block_start) as u8;
|
let mut if_block_distance = (if_block_end - if_block_start) as u16;
|
||||||
let if_block_type = self.get_last_instruction_type();
|
let if_block_type = self.get_last_instruction_type();
|
||||||
|
|
||||||
if let Token::Else = self.current_token {
|
if let Token::Else = self.current_token {
|
||||||
@ -1216,7 +1487,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let else_block_end = self.instructions.len();
|
let else_block_end = self.instructions.len();
|
||||||
let else_block_distance = (else_block_end - if_block_end) as u8;
|
let else_block_distance = (else_block_end - if_block_end) as u16;
|
||||||
let else_block_type = self.get_last_instruction_type();
|
let else_block_type = self.get_last_instruction_type();
|
||||||
|
|
||||||
if let Err(conflict) = if_block_type.check(&else_block_type) {
|
if let Err(conflict) = if_block_type.check(&else_block_type) {
|
||||||
@ -1234,13 +1505,10 @@ impl<'src> Compiler<'src> {
|
|||||||
{
|
{
|
||||||
let (loader, _, _) = self.instructions.last_mut().unwrap();
|
let (loader, _, _) = self.instructions.last_mut().unwrap();
|
||||||
|
|
||||||
loader.set_c_field(true as u8);
|
loader.set_c_field(true as u16);
|
||||||
} else {
|
} else {
|
||||||
if_block_distance += 1;
|
if_block_distance += 1;
|
||||||
let jump = Instruction::from(Jump {
|
let jump = Instruction::jump(else_block_distance, true);
|
||||||
offset: else_block_distance,
|
|
||||||
is_positive: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.instructions
|
self.instructions
|
||||||
.insert(if_block_end, (jump, Type::None, self.current_position));
|
.insert(if_block_end, (jump, Type::None, self.current_position));
|
||||||
@ -1248,10 +1516,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
2.. => {
|
2.. => {
|
||||||
if_block_distance += 1;
|
if_block_distance += 1;
|
||||||
let jump = Instruction::from(Jump {
|
let jump = Instruction::jump(else_block_distance, true);
|
||||||
offset: else_block_distance,
|
|
||||||
is_positive: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.instructions
|
self.instructions
|
||||||
.insert(if_block_end, (jump, Type::None, self.current_position));
|
.insert(if_block_end, (jump, Type::None, self.current_position));
|
||||||
@ -1270,14 +1535,29 @@ impl<'src> Compiler<'src> {
|
|||||||
fn parse_while(&mut self) -> Result<(), CompileError> {
|
fn parse_while(&mut self) -> Result<(), CompileError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let expression_start = self.instructions.len() as u8;
|
let expression_start = self.instructions.len() as u16;
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
if matches!(
|
if matches!(
|
||||||
self.get_last_operations(),
|
self.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
| Operation::LESS_EQUAL_FLOAT,
|
||||||
Operation::JUMP,
|
Operation::JUMP,
|
||||||
Operation::LOAD_BOOLEAN,
|
Operation::LOAD_BOOLEAN,
|
||||||
Operation::LOAD_BOOLEAN
|
Operation::LOAD_BOOLEAN
|
||||||
@ -1297,21 +1577,15 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
self.parse_block()?;
|
self.parse_block()?;
|
||||||
|
|
||||||
let block_end = self.instructions.len() as u8;
|
let block_end = self.instructions.len() as u16;
|
||||||
let jump_distance = block_end - block_start as u8 + 1;
|
let jump_distance = block_end - block_start as u16 + 1;
|
||||||
let jump = Instruction::from(Jump {
|
let jump = Instruction::jump(jump_distance, true);
|
||||||
offset: jump_distance,
|
|
||||||
is_positive: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.instructions
|
self.instructions
|
||||||
.insert(block_start, (jump, Type::None, self.current_position));
|
.insert(block_start, (jump, Type::None, self.current_position));
|
||||||
|
|
||||||
let jump_back_distance = block_end - expression_start + 1;
|
let jump_back_distance = block_end - expression_start + 1;
|
||||||
let jump_back = Instruction::from(Jump {
|
let jump_back = Instruction::jump(jump_back_distance, false);
|
||||||
offset: jump_back_distance,
|
|
||||||
is_positive: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(jump_back, Type::None, self.current_position);
|
self.emit_instruction(jump_back, Type::None, self.current_position);
|
||||||
|
|
||||||
@ -1330,13 +1604,9 @@ impl<'src> Compiler<'src> {
|
|||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
let actual_register = self.next_register() - 1;
|
let actual_register = self.next_register() - 1;
|
||||||
let registers_to_close = actual_register - expected_register;
|
|
||||||
|
|
||||||
if registers_to_close > 0 {
|
if expected_register < actual_register {
|
||||||
let close = Instruction::from(Close {
|
let close = Instruction::close(expected_register, actual_register);
|
||||||
from: expected_register,
|
|
||||||
to: actual_register,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(close, Type::None, self.current_position);
|
self.emit_instruction(close, Type::None, self.current_position);
|
||||||
}
|
}
|
||||||
@ -1348,11 +1618,7 @@ impl<'src> Compiler<'src> {
|
|||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let argument_count = destination - start_register;
|
let argument_count = destination - start_register;
|
||||||
let return_type = function.r#type().return_type;
|
let return_type = function.r#type().return_type;
|
||||||
let call_native = Instruction::from(CallNative {
|
let call_native = Instruction::call_native(destination, function, argument_count);
|
||||||
destination,
|
|
||||||
function,
|
|
||||||
argument_count,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(call_native, return_type, Span(start, end));
|
self.emit_instruction(call_native, return_type, Span(start, end));
|
||||||
|
|
||||||
@ -1415,10 +1681,7 @@ impl<'src> Compiler<'src> {
|
|||||||
};
|
};
|
||||||
let end = self.current_position.1;
|
let end = self.current_position.1;
|
||||||
let return_register = self.next_register() - 1;
|
let return_register = self.next_register() - 1;
|
||||||
let r#return = Instruction::from(Return {
|
let r#return = Instruction::r#return(should_return_value, return_register);
|
||||||
should_return_value,
|
|
||||||
return_register,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(r#return, Type::None, Span(start, end));
|
self.emit_instruction(r#return, Type::None, Span(start, end));
|
||||||
|
|
||||||
@ -1433,7 +1696,7 @@ impl<'src> Compiler<'src> {
|
|||||||
let offset = offset as usize;
|
let offset = offset as usize;
|
||||||
|
|
||||||
if is_positive && offset + index == instruction_length - 1 {
|
if is_positive && offset + index == instruction_length - 1 {
|
||||||
*instruction = Instruction::jump((offset + 1) as u8, true);
|
*instruction = Instruction::jump((offset + 1) as u16, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1487,7 +1750,7 @@ impl<'src> Compiler<'src> {
|
|||||||
let offset = offset as usize;
|
let offset = offset as usize;
|
||||||
|
|
||||||
if is_positive && offset + index == instruction_length - 1 {
|
if is_positive && offset + index == instruction_length - 1 {
|
||||||
*instruction = Instruction::jump((offset + 1) as u8, true);
|
*instruction = Instruction::jump((offset + 1) as u16, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1567,9 +1830,9 @@ impl<'src> Compiler<'src> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function_compiler.prototype_index = self.prototypes.len() as u8;
|
function_compiler.prototype_index = self.prototypes.len() as u16;
|
||||||
|
|
||||||
let mut value_parameters: Vec<(u8, Type)> = Vec::with_capacity(3);
|
let mut value_parameters: Vec<(u16, Type)> = Vec::with_capacity(3);
|
||||||
|
|
||||||
while !function_compiler.allow(Token::RightParenthesis)? {
|
while !function_compiler.allow(Token::RightParenthesis)? {
|
||||||
let is_mutable = function_compiler.allow(Token::Mut)?;
|
let is_mutable = function_compiler.allow(Token::Mut)?;
|
||||||
@ -1657,7 +1920,7 @@ impl<'src> Compiler<'src> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let load_function = Instruction::load_function(destination, prototype_index);
|
let load_function = Instruction::load_function(destination, prototype_index, false);
|
||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
load_function,
|
load_function,
|
||||||
@ -1717,15 +1980,12 @@ impl<'src> Compiler<'src> {
|
|||||||
let registers_to_close = (actual_register - expected_register).saturating_sub(1);
|
let registers_to_close = (actual_register - expected_register).saturating_sub(1);
|
||||||
|
|
||||||
if registers_to_close > 0 {
|
if registers_to_close > 0 {
|
||||||
let close = Instruction::from(Close {
|
let close = Instruction::close(expected_register, actual_register);
|
||||||
from: expected_register,
|
|
||||||
to: actual_register,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.emit_instruction(close, Type::None, self.current_position);
|
self.emit_instruction(close, Type::None, self.current_position);
|
||||||
}
|
|
||||||
|
|
||||||
argument_count += registers_to_close + 1;
|
argument_count += registers_to_close + 1;
|
||||||
|
}
|
||||||
|
|
||||||
self.allow(Token::Comma)?;
|
self.allow(Token::Comma)?;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ use crate::{Compiler, Instruction, Operation};
|
|||||||
/// a `POINT` instruction to prevent the VM from encountering an empty register.
|
/// a `POINT` instruction to prevent the VM from encountering an empty register.
|
||||||
///
|
///
|
||||||
/// The instructions must be in the following order:
|
/// The instructions must be in the following order:
|
||||||
/// - `EQUAL` | `LESS` | `LESS_EQUAL` | `TEST`
|
/// - `TEST` or any of the `EQUAL`, `LESS` or `LESS_EQUAL` instructions
|
||||||
/// - `JUMP`
|
/// - `JUMP`
|
||||||
/// - `LOAD_BOOLEAN` or `LOAD_CONSTANT`
|
/// - `LOAD_BOOLEAN` or `LOAD_CONSTANT`
|
||||||
/// - `LOAD_BOOLEAN` or `LOAD_CONSTANT`
|
/// - `LOAD_BOOLEAN` or `LOAD_CONSTANT`
|
||||||
@ -37,7 +37,23 @@ pub fn control_flow_register_consolidation(compiler: &mut Compiler) {
|
|||||||
if !matches!(
|
if !matches!(
|
||||||
compiler.get_last_operations(),
|
compiler.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL | Operation::TEST,
|
Operation::TEST
|
||||||
|
| Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
| Operation::LESS_EQUAL_FLOAT,
|
||||||
Operation::JUMP,
|
Operation::JUMP,
|
||||||
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
||||||
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Add {
|
|
||||||
pub destination: u8,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Add {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Add {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Add> for Instruction {
|
|
||||||
fn from(add: Add) -> Self {
|
|
||||||
let operation = Operation::ADD;
|
|
||||||
let a = add.destination;
|
|
||||||
let (b, b_is_constant) = add.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = add.right.as_index_and_constant_flag();
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, c_is_constant, false)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/add_byte.rs
Normal file
54
dust-lang/src/instruction/add_byte.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddByte {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddByte> for Instruction {
|
||||||
|
fn from(add_byte: AddByte) -> Self {
|
||||||
|
let operation = Operation::ADD_BYTE;
|
||||||
|
let a_field = add_byte.destination;
|
||||||
|
let (b_field, b_is_constant) = add_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_byte.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddByte {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let AddByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/add_char.rs
Normal file
54
dust-lang/src/instruction/add_char.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddChar {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddChar {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddChar> for Instruction {
|
||||||
|
fn from(add_char: AddChar) -> Self {
|
||||||
|
let operation = Operation::ADD_CHAR;
|
||||||
|
let a_field = add_char.destination;
|
||||||
|
let (b_field, b_is_constant) = add_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_char.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddChar {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/add_char_str.rs
Normal file
54
dust-lang/src/instruction/add_char_str.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddCharStr {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddCharStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddCharStr {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddCharStr> for Instruction {
|
||||||
|
fn from(add_char_str: AddCharStr) -> Self {
|
||||||
|
let operation = Operation::ADD_CHAR_STR;
|
||||||
|
let a_field = add_char_str.destination;
|
||||||
|
let (b_field, b_is_constant) = add_char_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_char_str.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddCharStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddCharStr {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/add_float.rs
Normal file
54
dust-lang/src/instruction/add_float.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddFloat> for Instruction {
|
||||||
|
fn from(add_float: AddFloat) -> Self {
|
||||||
|
let operation = Operation::ADD_FLOAT;
|
||||||
|
let a_field = add_float.destination;
|
||||||
|
let (b_field, b_is_constant) = add_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_float.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
56
dust-lang/src/instruction/add_int.rs
Normal file
56
dust-lang/src/instruction/add_int.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use crate::{Instruction, Operand, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
|
pub struct AddInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddInt> for Instruction {
|
||||||
|
fn from(add_int: AddInt) -> Self {
|
||||||
|
let operation = Operation::ADD_INT;
|
||||||
|
let a_field = add_int.destination;
|
||||||
|
let (b_field, b_is_constant) = add_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_int.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/add_str.rs
Normal file
54
dust-lang/src/instruction/add_str.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddStr {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddStr {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddStr> for Instruction {
|
||||||
|
fn from(add_str: AddStr) -> Self {
|
||||||
|
let operation = Operation::ADD_STR;
|
||||||
|
let a_field = add_str.destination;
|
||||||
|
let (b_field, b_is_constant) = add_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_str.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddStr {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/add_str_char.rs
Normal file
54
dust-lang/src/instruction/add_str_char.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct AddStrChar {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for AddStrChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
AddStrChar {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddStrChar> for Instruction {
|
||||||
|
fn from(add_str_char: AddStrChar) -> Self {
|
||||||
|
let operation = Operation::ADD_STR_CHAR;
|
||||||
|
let a_field = add_str_char.destination;
|
||||||
|
let (b_field, b_is_constant) = add_str_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add_str_char.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AddStrChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let AddStrChar {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} + {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub function_register: u8,
|
pub function_register: u16,
|
||||||
pub argument_count: u8,
|
pub argument_count: u16,
|
||||||
pub is_recursive: bool,
|
pub is_recursive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,11 +27,19 @@ impl From<Instruction> for Call {
|
|||||||
|
|
||||||
impl From<Call> for Instruction {
|
impl From<Call> for Instruction {
|
||||||
fn from(call: Call) -> Self {
|
fn from(call: Call) -> Self {
|
||||||
let a = call.destination;
|
let a_field = call.destination;
|
||||||
let b = call.function_register;
|
let b_field = call.function_register;
|
||||||
let c = call.argument_count;
|
let c_field = call.argument_count;
|
||||||
let d = call.is_recursive;
|
let d_field = call.is_recursive;
|
||||||
|
|
||||||
Instruction::new(Operation::CALL, a, b, c, false, false, d)
|
InstructionBuilder {
|
||||||
|
operation: Operation::CALL,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use crate::{Instruction, NativeFunction, Operation};
|
use crate::{Instruction, NativeFunction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct CallNative {
|
pub struct CallNative {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub function: NativeFunction,
|
pub function: NativeFunction,
|
||||||
pub argument_count: u8,
|
pub argument_count: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for CallNative {
|
impl From<Instruction> for CallNative {
|
||||||
@ -22,10 +24,17 @@ impl From<Instruction> for CallNative {
|
|||||||
impl From<CallNative> for Instruction {
|
impl From<CallNative> for Instruction {
|
||||||
fn from(call_native: CallNative) -> Self {
|
fn from(call_native: CallNative) -> Self {
|
||||||
let operation = Operation::CALL_NATIVE;
|
let operation = Operation::CALL_NATIVE;
|
||||||
let a = call_native.destination;
|
let a_field = call_native.destination;
|
||||||
let b = call_native.function as u8;
|
let b_field = call_native.function as u16;
|
||||||
let c = call_native.argument_count;
|
let c_field = call_native.argument_count;
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Close {
|
pub struct Close {
|
||||||
pub from: u8,
|
pub from: u16,
|
||||||
pub to: u8,
|
pub to: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for Close {
|
impl From<Instruction> for Close {
|
||||||
@ -17,8 +21,23 @@ impl From<Instruction> for Close {
|
|||||||
impl From<Close> for Instruction {
|
impl From<Close> for Instruction {
|
||||||
fn from(close: Close) -> Self {
|
fn from(close: Close) -> Self {
|
||||||
let operation = Operation::CLOSE;
|
let operation = Operation::CLOSE;
|
||||||
let (a, b, c) = (0, close.from, close.to);
|
let b_field = close.from;
|
||||||
|
let c_field = close.to;
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Close {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Close { from, to } = self;
|
||||||
|
|
||||||
|
write!(f, "{from}..={to}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Divide {
|
|
||||||
pub destination: u8,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Divide {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Divide {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Divide> for Instruction {
|
|
||||||
fn from(divide: Divide) -> Self {
|
|
||||||
let operation = Operation::DIVIDE;
|
|
||||||
let a = divide.destination;
|
|
||||||
let (b, b_is_constant) = divide.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = divide.right.as_index_and_constant_flag();
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, c_is_constant, false)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/divide_byte.rs
Normal file
54
dust-lang/src/instruction/divide_byte.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct DivideByte {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for DivideByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
DivideByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DivideByte> for Instruction {
|
||||||
|
fn from(divide_byte: DivideByte) -> Self {
|
||||||
|
let operation = Operation::DIVIDE_BYTE;
|
||||||
|
let a_field = divide_byte.destination;
|
||||||
|
let (b_field, b_is_constant) = divide_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = divide_byte.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DivideByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let DivideByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ÷ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/divide_float.rs
Normal file
54
dust-lang/src/instruction/divide_float.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct DivideFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for DivideFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
DivideFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DivideFloat> for Instruction {
|
||||||
|
fn from(divide_float: DivideFloat) -> Self {
|
||||||
|
let operation = Operation::DIVIDE_FLOAT;
|
||||||
|
let a_field = divide_float.destination;
|
||||||
|
let (b_field, b_is_constant) = divide_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = divide_float.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DivideFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let DivideFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ÷ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/divide_int.rs
Normal file
54
dust-lang/src/instruction/divide_int.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct DivideInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for DivideInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
DivideInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DivideInt> for Instruction {
|
||||||
|
fn from(divide_int: DivideInt) -> Self {
|
||||||
|
let operation = Operation::DIVIDE_INT;
|
||||||
|
let a_field = divide_int.destination;
|
||||||
|
let (b_field, b_is_constant) = divide_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = divide_int.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DivideInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let DivideInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ÷ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Equal {
|
|
||||||
pub value: bool,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Equal {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let value = instruction.d_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Equal { value, left, right }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Equal> for Instruction {
|
|
||||||
fn from(equal: Equal) -> Self {
|
|
||||||
let operation = Operation::EQUAL;
|
|
||||||
let (b, b_is_constant) = equal.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = equal.right.as_index_and_constant_flag();
|
|
||||||
let d = equal.value;
|
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, b_is_constant, c_is_constant, d)
|
|
||||||
}
|
|
||||||
}
|
|
55
dust-lang/src/instruction/equal_bool.rs
Normal file
55
dust-lang/src/instruction/equal_bool.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualBool {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualBool {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualBool {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualBool> for Instruction {
|
||||||
|
fn from(equal_bool: EqualBool) -> Self {
|
||||||
|
let operation = Operation::EQUAL_BOOL;
|
||||||
|
let (b_field, b_is_constant) = equal_bool.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_bool.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_bool.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualBool {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualBool {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_byte.rs
Normal file
55
dust-lang/src/instruction/equal_byte.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualByte {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualByte> for Instruction {
|
||||||
|
fn from(equal_byte: EqualByte) -> Self {
|
||||||
|
let operation = Operation::EQUAL_BYTE;
|
||||||
|
let (b_field, b_is_constant) = equal_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_byte.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_byte.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_char.rs
Normal file
55
dust-lang/src/instruction/equal_char.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualChar {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualChar> for Instruction {
|
||||||
|
fn from(equal_char: EqualChar) -> Self {
|
||||||
|
let operation = Operation::EQUAL_CHAR;
|
||||||
|
let (b_field, b_is_constant) = equal_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_char.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_char.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_char_str.rs
Normal file
55
dust-lang/src/instruction/equal_char_str.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualCharStr {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualCharStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualCharStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualCharStr> for Instruction {
|
||||||
|
fn from(equal_char_str: EqualCharStr) -> Self {
|
||||||
|
let operation = Operation::EQUAL_CHAR_STR;
|
||||||
|
let (b_field, b_is_constant) = equal_char_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_char_str.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_char_str.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualCharStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualCharStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_float.rs
Normal file
55
dust-lang/src/instruction/equal_float.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualFloat {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualFloat> for Instruction {
|
||||||
|
fn from(equal_float: EqualFloat) -> Self {
|
||||||
|
let operation = Operation::EQUAL_FLOAT;
|
||||||
|
let (b_field, b_is_constant) = equal_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_float.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_float.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_int.rs
Normal file
55
dust-lang/src/instruction/equal_int.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualInt {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualInt> for Instruction {
|
||||||
|
fn from(equal_int: EqualInt) -> Self {
|
||||||
|
let operation = Operation::EQUAL_INT;
|
||||||
|
let (b_field, b_is_constant) = equal_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_int.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_int.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_str.rs
Normal file
55
dust-lang/src/instruction/equal_str.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualStr {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualStr> for Instruction {
|
||||||
|
fn from(equal_str: EqualStr) -> Self {
|
||||||
|
let operation = Operation::EQUAL_STR;
|
||||||
|
let (b_field, b_is_constant) = equal_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_str.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_str.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/equal_str_char.rs
Normal file
55
dust-lang/src/instruction/equal_str_char.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct EqualStrChar {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for EqualStrChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
EqualStrChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EqualStrChar> for Instruction {
|
||||||
|
fn from(equal_str_char: EqualStrChar) -> Self {
|
||||||
|
let operation = Operation::EQUAL_STR_CHAR;
|
||||||
|
let (b_field, b_is_constant) = equal_str_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = equal_str_char.right.as_index_and_constant_flag();
|
||||||
|
let d_field = equal_str_char.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EqualStrChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let EqualStrChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct GetLocal {
|
pub struct GetLocal {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub local_index: u8,
|
pub local_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for GetLocal {
|
impl From<Instruction> for GetLocal {
|
||||||
@ -20,9 +24,26 @@ impl From<Instruction> for GetLocal {
|
|||||||
impl From<GetLocal> for Instruction {
|
impl From<GetLocal> for Instruction {
|
||||||
fn from(get_local: GetLocal) -> Self {
|
fn from(get_local: GetLocal) -> Self {
|
||||||
let operation = Operation::GET_LOCAL;
|
let operation = Operation::GET_LOCAL;
|
||||||
let a = get_local.destination;
|
let a_field = get_local.destination;
|
||||||
let b = get_local.local_index;
|
let b_field = get_local.local_index;
|
||||||
|
|
||||||
Instruction::new(operation, a, b, 0, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for GetLocal {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let GetLocal {
|
||||||
|
destination,
|
||||||
|
local_index,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = L{local_index}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Jump {
|
pub struct Jump {
|
||||||
pub offset: u8,
|
pub offset: u16,
|
||||||
pub is_positive: bool,
|
pub is_positive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,9 +19,15 @@ impl From<Instruction> for Jump {
|
|||||||
impl From<Jump> for Instruction {
|
impl From<Jump> for Instruction {
|
||||||
fn from(jump: Jump) -> Self {
|
fn from(jump: Jump) -> Self {
|
||||||
let operation = Operation::JUMP;
|
let operation = Operation::JUMP;
|
||||||
let b = jump.offset;
|
let b_field = jump.offset;
|
||||||
let c = jump.is_positive as u8;
|
let c_field = jump.is_positive as u16;
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Less {
|
|
||||||
pub value: bool,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Less {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let value = instruction.d_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Less { value, left, right }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Less> for Instruction {
|
|
||||||
fn from(less: Less) -> Self {
|
|
||||||
let operation = Operation::LESS;
|
|
||||||
let (b, b_is_constant) = less.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = less.right.as_index_and_constant_flag();
|
|
||||||
let d = less.value;
|
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, b_is_constant, c_is_constant, d)
|
|
||||||
}
|
|
||||||
}
|
|
55
dust-lang/src/instruction/less_byte.rs
Normal file
55
dust-lang/src/instruction/less_byte.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessByte {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessByte> for Instruction {
|
||||||
|
fn from(less_byte: LessByte) -> Self {
|
||||||
|
let operation = Operation::LESS_BYTE;
|
||||||
|
let (b_field, b_is_constant) = less_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_byte.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_byte.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_char.rs
Normal file
55
dust-lang/src/instruction/less_char.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessChar {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessChar> for Instruction {
|
||||||
|
fn from(less_char: LessChar) -> Self {
|
||||||
|
let operation = Operation::LESS_CHAR;
|
||||||
|
let (b_field, b_is_constant) = less_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_char.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_char.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct LessEqual {
|
|
||||||
pub value: bool,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for LessEqual {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let value = instruction.d_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
LessEqual { value, left, right }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LessEqual> for Instruction {
|
|
||||||
fn from(less_equal: LessEqual) -> Self {
|
|
||||||
let operation = Operation::LESS_EQUAL;
|
|
||||||
let (b, b_options) = less_equal.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_options) = less_equal.right.as_index_and_constant_flag();
|
|
||||||
let d = less_equal.value;
|
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, b_options, c_options, d)
|
|
||||||
}
|
|
||||||
}
|
|
55
dust-lang/src/instruction/less_equal_byte.rs
Normal file
55
dust-lang/src/instruction/less_equal_byte.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessEqualByte {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessEqualByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessEqualByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessEqualByte> for Instruction {
|
||||||
|
fn from(less_equal_byte: LessEqualByte) -> Self {
|
||||||
|
let operation = Operation::LESS_EQUAL_BYTE;
|
||||||
|
let (b_field, b_is_constant) = less_equal_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_equal_byte.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_equal_byte.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessEqualByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessEqualByte {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_equal_char.rs
Normal file
55
dust-lang/src/instruction/less_equal_char.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessEqualChar {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessEqualChar {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessEqualChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessEqualChar> for Instruction {
|
||||||
|
fn from(less_equal_char: LessEqualChar) -> Self {
|
||||||
|
let operation = Operation::LESS_EQUAL_CHAR;
|
||||||
|
let (b_field, b_is_constant) = less_equal_char.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_equal_char.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_equal_char.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessEqualChar {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessEqualChar {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_equal_float.rs
Normal file
55
dust-lang/src/instruction/less_equal_float.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessEqualFloat {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessEqualFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessEqualFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessEqualFloat> for Instruction {
|
||||||
|
fn from(less_equal_float: LessEqualFloat) -> Self {
|
||||||
|
let operation = Operation::LESS_EQUAL_FLOAT;
|
||||||
|
let (b_field, b_is_constant) = less_equal_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_equal_float.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_equal_float.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessEqualFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessEqualFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_equal_int.rs
Normal file
55
dust-lang/src/instruction/less_equal_int.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessEqualInt {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessEqualInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessEqualInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessEqualInt> for Instruction {
|
||||||
|
fn from(less_equal_int: LessEqualInt) -> Self {
|
||||||
|
let operation = Operation::LESS_EQUAL_INT;
|
||||||
|
let (b_field, b_is_constant) = less_equal_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_equal_int.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_equal_int.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessEqualInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessEqualInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_equal_str.rs
Normal file
55
dust-lang/src/instruction/less_equal_str.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessEqualStr {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessEqualStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessEqualStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessEqualStr> for Instruction {
|
||||||
|
fn from(less_equal_str: LessEqualStr) -> Self {
|
||||||
|
let operation = Operation::LESS_EQUAL_STR;
|
||||||
|
let (b_field, b_is_constant) = less_equal_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_equal_str.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_equal_str.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessEqualStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessEqualStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_float.rs
Normal file
55
dust-lang/src/instruction/less_float.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessFloat {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessFloat> for Instruction {
|
||||||
|
fn from(less_float: LessFloat) -> Self {
|
||||||
|
let operation = Operation::LESS_FLOAT;
|
||||||
|
let (b_field, b_is_constant) = less_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_float.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_float.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessFloat {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_int.rs
Normal file
55
dust-lang/src/instruction/less_int.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessInt {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessInt> for Instruction {
|
||||||
|
fn from(less_int: LessInt) -> Self {
|
||||||
|
let operation = Operation::LESS_INT;
|
||||||
|
let (b_field, b_is_constant) = less_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_int.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_int.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessInt {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
55
dust-lang/src/instruction/less_str.rs
Normal file
55
dust-lang/src/instruction/less_str.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct LessStr {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for LessStr {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
LessStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LessStr> for Instruction {
|
||||||
|
fn from(less_str: LessStr) -> Self {
|
||||||
|
let operation = Operation::LESS_STR;
|
||||||
|
let (b_field, b_is_constant) = less_str.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less_str.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less_str.comparator;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LessStr {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LessStr {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,11 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct LoadBoolean {
|
pub struct LoadBoolean {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub value: bool,
|
pub value: bool,
|
||||||
pub jump_next: bool,
|
pub jump_next: bool,
|
||||||
}
|
}
|
||||||
@ -19,10 +23,35 @@ impl From<Instruction> for LoadBoolean {
|
|||||||
impl From<LoadBoolean> for Instruction {
|
impl From<LoadBoolean> for Instruction {
|
||||||
fn from(load_boolean: LoadBoolean) -> Self {
|
fn from(load_boolean: LoadBoolean) -> Self {
|
||||||
let operation = Operation::LOAD_BOOLEAN;
|
let operation = Operation::LOAD_BOOLEAN;
|
||||||
let a = load_boolean.destination;
|
let a_field = load_boolean.destination;
|
||||||
let b = load_boolean.value as u8;
|
let b_field = load_boolean.value as u16;
|
||||||
let c = load_boolean.jump_next as u8;
|
let c_field = load_boolean.jump_next as u16;
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LoadBoolean {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LoadBoolean {
|
||||||
|
destination,
|
||||||
|
value,
|
||||||
|
jump_next,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = {value}")?;
|
||||||
|
|
||||||
|
if *jump_next {
|
||||||
|
write!(f, " JUMP +1")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct LoadConstant {
|
pub struct LoadConstant {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub constant_index: u8,
|
pub constant_index: u16,
|
||||||
pub jump_next: bool,
|
pub jump_next: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,12 +26,14 @@ impl From<Instruction> for LoadConstant {
|
|||||||
|
|
||||||
impl From<LoadConstant> for Instruction {
|
impl From<LoadConstant> for Instruction {
|
||||||
fn from(load_constant: LoadConstant) -> Self {
|
fn from(load_constant: LoadConstant) -> Self {
|
||||||
let operation = Operation::LOAD_CONSTANT;
|
InstructionBuilder {
|
||||||
let a = load_constant.destination;
|
operation: Operation::LOAD_CONSTANT,
|
||||||
let b = load_constant.constant_index;
|
a_field: load_constant.destination,
|
||||||
let c = load_constant.jump_next as u8;
|
b_field: load_constant.constant_index,
|
||||||
|
c_field: load_constant.jump_next as u16,
|
||||||
Instruction::new(operation, a, b, c, false, false, false)
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,12 +45,12 @@ impl Display for LoadConstant {
|
|||||||
jump_next,
|
jump_next,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
write!(f, "R{destination} = Constant {constant_index}")?;
|
write!(f, "R{destination} = C{constant_index}")?;
|
||||||
|
|
||||||
if *jump_next {
|
if *jump_next {
|
||||||
write!(f, " JUMP +1")
|
write!(f, " JUMP +1")?;
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,54 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use super::{Instruction, Operation};
|
use super::{Instruction, InstructionBuilder, Operation};
|
||||||
|
|
||||||
pub struct LoadFunction {
|
pub struct LoadFunction {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub prototype_index: u8,
|
pub prototype_index: u16,
|
||||||
|
pub jump_next: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for LoadFunction {
|
impl From<Instruction> for LoadFunction {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: Instruction) -> Self {
|
||||||
let destination = instruction.a_field();
|
let destination = instruction.a_field();
|
||||||
let record_index = instruction.b_field();
|
let prototype_index = instruction.b_field();
|
||||||
|
let jump_next = instruction.c_field() != 0;
|
||||||
|
|
||||||
LoadFunction {
|
LoadFunction {
|
||||||
destination,
|
destination,
|
||||||
prototype_index: record_index,
|
prototype_index,
|
||||||
|
jump_next,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LoadFunction> for Instruction {
|
impl From<LoadFunction> for Instruction {
|
||||||
fn from(load_function: LoadFunction) -> Self {
|
fn from(load_function: LoadFunction) -> Self {
|
||||||
Instruction::new(
|
InstructionBuilder {
|
||||||
Operation::LOAD_FUNCTION,
|
operation: Operation::LOAD_FUNCTION,
|
||||||
load_function.destination,
|
a_field: load_function.destination,
|
||||||
load_function.prototype_index,
|
b_field: load_function.prototype_index,
|
||||||
0,
|
c_field: load_function.jump_next as u16,
|
||||||
false,
|
..Default::default()
|
||||||
false,
|
}
|
||||||
false,
|
.build()
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for LoadFunction {
|
impl Display for LoadFunction {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "R{} = F{}", self.destination, self.prototype_index)
|
let LoadFunction {
|
||||||
|
destination,
|
||||||
|
prototype_index,
|
||||||
|
jump_next,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = P{prototype_index}")?;
|
||||||
|
|
||||||
|
if *jump_next {
|
||||||
|
write!(f, " JUMP +1")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,56 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct LoadList {
|
pub struct LoadList {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub start_register: u8,
|
pub start_register: u16,
|
||||||
|
pub jump_next: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for LoadList {
|
impl From<Instruction> for LoadList {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: Instruction) -> Self {
|
||||||
let destination = instruction.a_field();
|
let destination = instruction.a_field();
|
||||||
let start_register = instruction.b_field();
|
let start_register = instruction.b_field();
|
||||||
|
let jump_next = instruction.c_field() != 0;
|
||||||
|
|
||||||
LoadList {
|
LoadList {
|
||||||
destination,
|
destination,
|
||||||
start_register,
|
start_register,
|
||||||
|
jump_next,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LoadList> for Instruction {
|
impl From<LoadList> for Instruction {
|
||||||
fn from(load_list: LoadList) -> Self {
|
fn from(load_list: LoadList) -> Self {
|
||||||
let operation = Operation::LOAD_LIST;
|
InstructionBuilder {
|
||||||
let a = load_list.destination;
|
operation: Operation::LOAD_LIST,
|
||||||
let b = load_list.start_register;
|
a_field: load_list.destination,
|
||||||
|
b_field: load_list.start_register,
|
||||||
Instruction::new(operation, a, b, 0, false, false, false)
|
c_field: load_list.jump_next as u16,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LoadList {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LoadList {
|
||||||
|
destination,
|
||||||
|
start_register,
|
||||||
|
jump_next,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = [R{start_register}..R{destination}]")?;
|
||||||
|
|
||||||
|
if *jump_next {
|
||||||
|
write!(f, " JUMP +1")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,51 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct LoadSelf {
|
pub struct LoadSelf {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
|
pub jump_next: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for LoadSelf {
|
impl From<Instruction> for LoadSelf {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: Instruction) -> Self {
|
||||||
let destination = instruction.a_field();
|
let destination = instruction.a_field();
|
||||||
|
let jump_next = instruction.c_field() != 0;
|
||||||
|
|
||||||
LoadSelf { destination }
|
LoadSelf {
|
||||||
|
destination,
|
||||||
|
jump_next,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LoadSelf> for Instruction {
|
impl From<LoadSelf> for Instruction {
|
||||||
fn from(load_self: LoadSelf) -> Self {
|
fn from(load_self: LoadSelf) -> Self {
|
||||||
let operation = Operation::LOAD_SELF;
|
InstructionBuilder {
|
||||||
let a = load_self.destination;
|
operation: Operation::LOAD_SELF,
|
||||||
|
a_field: load_self.destination,
|
||||||
Instruction::new(operation, a, 0, 0, false, false, false)
|
c_field: load_self.jump_next as u16,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LoadSelf {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let LoadSelf {
|
||||||
|
destination,
|
||||||
|
jump_next,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = SELF")?;
|
||||||
|
|
||||||
|
if *jump_next {
|
||||||
|
write!(f, " JUMP +1")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Modulo {
|
|
||||||
pub destination: u8,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Modulo {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Modulo {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Modulo> for Instruction {
|
|
||||||
fn from(modulo: Modulo) -> Self {
|
|
||||||
let operation = Operation::MODULO;
|
|
||||||
let a = modulo.destination;
|
|
||||||
let (b, b_is_constant) = modulo.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = modulo.right.as_index_and_constant_flag();
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, c_is_constant, false)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/modulo_byte.rs
Normal file
54
dust-lang/src/instruction/modulo_byte.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct ModuloByte {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for ModuloByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
ModuloByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ModuloByte> for Instruction {
|
||||||
|
fn from(modulo_byte: ModuloByte) -> Self {
|
||||||
|
let operation = Operation::MODULO_BYTE;
|
||||||
|
let a_field = modulo_byte.destination;
|
||||||
|
let (b_field, b_is_constant) = modulo_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = modulo_byte.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ModuloByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let ModuloByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} % {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/modulo_float.rs
Normal file
54
dust-lang/src/instruction/modulo_float.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct ModuloFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for ModuloFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
ModuloFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ModuloFloat> for Instruction {
|
||||||
|
fn from(modulo_float: ModuloFloat) -> Self {
|
||||||
|
let operation = Operation::MODULO_FLOAT;
|
||||||
|
let a_field = modulo_float.destination;
|
||||||
|
let (b_field, b_is_constant) = modulo_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = modulo_float.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ModuloFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let ModuloFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} % {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/modulo_int.rs
Normal file
54
dust-lang/src/instruction/modulo_int.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct ModuloInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for ModuloInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
ModuloInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ModuloInt> for Instruction {
|
||||||
|
fn from(modulo_int: ModuloInt) -> Self {
|
||||||
|
let operation = Operation::MODULO_INT;
|
||||||
|
let a_field = modulo_int.destination;
|
||||||
|
let (b_field, b_is_constant) = modulo_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = modulo_int.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ModuloInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let ModuloInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} % {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Multiply {
|
|
||||||
pub destination: u8,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Multiply {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Multiply {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Multiply> for Instruction {
|
|
||||||
fn from(multiply: Multiply) -> Self {
|
|
||||||
let operation = Operation::MULTIPLY;
|
|
||||||
let a = multiply.destination;
|
|
||||||
let (b, b_options) = multiply.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_options) = multiply.right.as_index_and_constant_flag();
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_options, c_options, false)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/multiply_byte.rs
Normal file
54
dust-lang/src/instruction/multiply_byte.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct MultiplyByte {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for MultiplyByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
MultiplyByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiplyByte> for Instruction {
|
||||||
|
fn from(multiply_byte: MultiplyByte) -> Self {
|
||||||
|
let operation = Operation::MODULO_BYTE;
|
||||||
|
let a_field = multiply_byte.destination;
|
||||||
|
let (b_field, b_is_constant) = multiply_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = multiply_byte.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MultiplyByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let MultiplyByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ✕ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/multiply_float.rs
Normal file
54
dust-lang/src/instruction/multiply_float.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct MultiplyFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for MultiplyFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
MultiplyFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiplyFloat> for Instruction {
|
||||||
|
fn from(multiply_float: MultiplyFloat) -> Self {
|
||||||
|
let operation = Operation::MULTIPLY_FLOAT;
|
||||||
|
let a_field = multiply_float.destination;
|
||||||
|
let (b_field, b_is_constant) = multiply_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = multiply_float.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MultiplyFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let MultiplyFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ✕ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/multiply_int.rs
Normal file
54
dust-lang/src/instruction/multiply_int.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct MultiplyInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for MultiplyInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
MultiplyInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiplyInt> for Instruction {
|
||||||
|
fn from(multiply_int: MultiplyInt) -> Self {
|
||||||
|
let operation = Operation::MULTIPLY_INT;
|
||||||
|
let a_field = multiply_int.destination;
|
||||||
|
let (b_field, b_is_constant) = multiply_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = multiply_int.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MultiplyInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let MultiplyInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} ✕ {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Negate {
|
|
||||||
pub destination: u8,
|
|
||||||
pub argument: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Negate {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let argument = instruction.b_as_argument();
|
|
||||||
|
|
||||||
Negate {
|
|
||||||
destination,
|
|
||||||
argument,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Negate> for Instruction {
|
|
||||||
fn from(negate: Negate) -> Self {
|
|
||||||
let operation = Operation::NEGATE;
|
|
||||||
let a = negate.destination;
|
|
||||||
let (b, b_is_constant) = negate.argument.as_index_and_constant_flag();
|
|
||||||
let c = 0;
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, false, false)
|
|
||||||
}
|
|
||||||
}
|
|
48
dust-lang/src/instruction/negate_float.rs
Normal file
48
dust-lang/src/instruction/negate_float.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct NegateFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub argument: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for NegateFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let argument = instruction.b_as_argument();
|
||||||
|
|
||||||
|
NegateFloat {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NegateFloat> for Instruction {
|
||||||
|
fn from(negate_float: NegateFloat) -> Self {
|
||||||
|
let operation = Operation::NEGATE_FLOAT;
|
||||||
|
let a_field = negate_float.destination;
|
||||||
|
let (b_field, b_is_constant) = negate_float.argument.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
b_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for NegateFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let NegateFloat {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = -{argument}")
|
||||||
|
}
|
||||||
|
}
|
48
dust-lang/src/instruction/negate_int.rs
Normal file
48
dust-lang/src/instruction/negate_int.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct NegateInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub argument: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for NegateInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let argument = instruction.b_as_argument();
|
||||||
|
|
||||||
|
NegateInt {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NegateInt> for Instruction {
|
||||||
|
fn from(negate_int: NegateInt) -> Self {
|
||||||
|
let operation = Operation::NEGATE_INT;
|
||||||
|
let a_field = negate_int.destination;
|
||||||
|
let (b_field, b_is_constant) = negate_int.argument.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
b_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for NegateInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let NegateInt {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = -{argument}")
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
use crate::{Instruction, Operand, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Not {
|
pub struct Not {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub argument: Argument,
|
pub argument: Operand,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for Not {
|
impl From<Instruction> for Not {
|
||||||
@ -20,9 +22,16 @@ impl From<Instruction> for Not {
|
|||||||
impl From<Not> for Instruction {
|
impl From<Not> for Instruction {
|
||||||
fn from(not: Not) -> Self {
|
fn from(not: Not) -> Self {
|
||||||
let operation = Operation::NOT;
|
let operation = Operation::NOT;
|
||||||
let a = not.destination;
|
let a_field = not.destination;
|
||||||
let (b, b_is_constant) = not.argument.as_index_and_constant_flag();
|
let (b_field, b_is_constant) = not.argument.as_index_and_constant_flag();
|
||||||
|
|
||||||
Instruction::new(operation, a, b, 0, b_is_constant, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
b_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,31 +9,90 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub struct Operation(pub u8);
|
pub struct Operation(pub u8);
|
||||||
|
|
||||||
impl Operation {
|
impl Operation {
|
||||||
|
// Stack manipulation
|
||||||
pub const POINT: Operation = Operation(0);
|
pub const POINT: Operation = Operation(0);
|
||||||
pub const CLOSE: Operation = Operation(1);
|
pub const CLOSE: Operation = Operation(1);
|
||||||
|
|
||||||
|
// Loaders
|
||||||
pub const LOAD_BOOLEAN: Operation = Operation(2);
|
pub const LOAD_BOOLEAN: Operation = Operation(2);
|
||||||
pub const LOAD_CONSTANT: Operation = Operation(3);
|
pub const LOAD_CONSTANT: Operation = Operation(3);
|
||||||
pub const LOAD_FUNCTION: Operation = Operation(4);
|
pub const LOAD_FUNCTION: Operation = Operation(4);
|
||||||
pub const LOAD_LIST: Operation = Operation(5);
|
pub const LOAD_LIST: Operation = Operation(5);
|
||||||
pub const LOAD_SELF: Operation = Operation(6);
|
pub const LOAD_SELF: Operation = Operation(6);
|
||||||
|
|
||||||
|
// Locals
|
||||||
pub const GET_LOCAL: Operation = Operation(7);
|
pub const GET_LOCAL: Operation = Operation(7);
|
||||||
pub const SET_LOCAL: Operation = Operation(8);
|
pub const SET_LOCAL: Operation = Operation(8);
|
||||||
pub const ADD: Operation = Operation(9);
|
|
||||||
pub const SUBTRACT: Operation = Operation(10);
|
// Addition
|
||||||
pub const MULTIPLY: Operation = Operation(11);
|
pub const ADD_INT: Operation = Operation(9);
|
||||||
pub const DIVIDE: Operation = Operation(12);
|
pub const ADD_FLOAT: Operation = Operation(10);
|
||||||
pub const MODULO: Operation = Operation(13);
|
pub const ADD_BYTE: Operation = Operation(11);
|
||||||
pub const TEST: Operation = Operation(14);
|
pub const ADD_STR: Operation = Operation(12);
|
||||||
pub const TEST_SET: Operation = Operation(15);
|
pub const ADD_CHAR: Operation = Operation(13);
|
||||||
pub const EQUAL: Operation = Operation(16);
|
pub const ADD_STR_CHAR: Operation = Operation(14);
|
||||||
pub const LESS: Operation = Operation(17);
|
pub const ADD_CHAR_STR: Operation = Operation(15);
|
||||||
pub const LESS_EQUAL: Operation = Operation(18);
|
|
||||||
pub const NEGATE: Operation = Operation(19);
|
// Subtraction
|
||||||
pub const NOT: Operation = Operation(20);
|
pub const SUBTRACT_INT: Operation = Operation(16);
|
||||||
pub const CALL: Operation = Operation(21);
|
pub const SUBTRACT_FLOAT: Operation = Operation(17);
|
||||||
pub const CALL_NATIVE: Operation = Operation(22);
|
pub const SUBTRACT_BYTE: Operation = Operation(18);
|
||||||
pub const JUMP: Operation = Operation(23);
|
|
||||||
pub const RETURN: Operation = Operation(24);
|
// Multiplication
|
||||||
|
pub const MULTIPLY_INT: Operation = Operation(19);
|
||||||
|
pub const MULTIPLY_FLOAT: Operation = Operation(20);
|
||||||
|
pub const MULTIPLY_BYTE: Operation = Operation(21);
|
||||||
|
|
||||||
|
// Division
|
||||||
|
pub const DIVIDE_INT: Operation = Operation(22);
|
||||||
|
pub const DIVIDE_FLOAT: Operation = Operation(23);
|
||||||
|
pub const DIVIDE_BYTE: Operation = Operation(24);
|
||||||
|
|
||||||
|
// Modulo
|
||||||
|
pub const MODULO_INT: Operation = Operation(25);
|
||||||
|
pub const MODULO_FLOAT: Operation = Operation(26);
|
||||||
|
pub const MODULO_BYTE: Operation = Operation(27);
|
||||||
|
|
||||||
|
// Equality
|
||||||
|
pub const EQUAL_INT: Operation = Operation(28);
|
||||||
|
pub const EQUAL_FLOAT: Operation = Operation(29);
|
||||||
|
pub const EQUAL_BYTE: Operation = Operation(30);
|
||||||
|
pub const EQUAL_STR: Operation = Operation(31);
|
||||||
|
pub const EQUAL_CHAR: Operation = Operation(32);
|
||||||
|
pub const EQUAL_STR_CHAR: Operation = Operation(33);
|
||||||
|
pub const EQUAL_CHAR_STR: Operation = Operation(34);
|
||||||
|
pub const EQUAL_BOOL: Operation = Operation(35);
|
||||||
|
|
||||||
|
// < or >= comparison
|
||||||
|
pub const LESS_INT: Operation = Operation(36);
|
||||||
|
pub const LESS_FLOAT: Operation = Operation(37);
|
||||||
|
pub const LESS_BYTE: Operation = Operation(38);
|
||||||
|
pub const LESS_STR: Operation = Operation(39);
|
||||||
|
pub const LESS_CHAR: Operation = Operation(40);
|
||||||
|
|
||||||
|
// <= or > comparison
|
||||||
|
pub const LESS_EQUAL_INT: Operation = Operation(41);
|
||||||
|
pub const LESS_EQUAL_FLOAT: Operation = Operation(42);
|
||||||
|
pub const LESS_EQUAL_BYTE: Operation = Operation(43);
|
||||||
|
pub const LESS_EQUAL_STR: Operation = Operation(44);
|
||||||
|
pub const LESS_EQUAL_CHAR: Operation = Operation(45);
|
||||||
|
|
||||||
|
// Unary operations
|
||||||
|
pub const NEGATE_INT: Operation = Operation(46);
|
||||||
|
pub const NEGATE_FLOAT: Operation = Operation(47);
|
||||||
|
pub const NOT: Operation = Operation(48);
|
||||||
|
|
||||||
|
// Logical operations
|
||||||
|
pub const TEST: Operation = Operation(49);
|
||||||
|
pub const TEST_SET: Operation = Operation(50);
|
||||||
|
|
||||||
|
// Function calls
|
||||||
|
pub const CALL: Operation = Operation(51);
|
||||||
|
pub const CALL_NATIVE: Operation = Operation(52);
|
||||||
|
|
||||||
|
// Control flow
|
||||||
|
pub const JUMP: Operation = Operation(53);
|
||||||
|
pub const RETURN: Operation = Operation(54);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operation {
|
impl Operation {
|
||||||
@ -48,18 +107,48 @@ impl Operation {
|
|||||||
Self::LOAD_SELF => "LOAD_SELF",
|
Self::LOAD_SELF => "LOAD_SELF",
|
||||||
Self::GET_LOCAL => "GET_LOCAL",
|
Self::GET_LOCAL => "GET_LOCAL",
|
||||||
Self::SET_LOCAL => "SET_LOCAL",
|
Self::SET_LOCAL => "SET_LOCAL",
|
||||||
Self::ADD => "ADD",
|
Self::ADD_INT => "ADD_INT",
|
||||||
Self::SUBTRACT => "SUBTRACT",
|
Self::ADD_FLOAT => "ADD_FLOAT",
|
||||||
Self::MULTIPLY => "MULTIPLY",
|
Self::ADD_BYTE => "ADD_BYTE",
|
||||||
Self::DIVIDE => "DIVIDE",
|
Self::ADD_STR => "ADD_STR",
|
||||||
Self::MODULO => "MODULO",
|
Self::ADD_CHAR => "ADD_CHAR",
|
||||||
|
Self::ADD_STR_CHAR => "ADD_STR_CHAR",
|
||||||
|
Self::ADD_CHAR_STR => "ADD_CHAR_STR",
|
||||||
|
Self::SUBTRACT_INT => "SUBTRACT_INT",
|
||||||
|
Self::SUBTRACT_FLOAT => "SUBTRACT_FLOAT",
|
||||||
|
Self::SUBTRACT_BYTE => "SUBTRACT_BYTE",
|
||||||
|
Self::MULTIPLY_INT => "MULTIPLY_INT",
|
||||||
|
Self::MULTIPLY_FLOAT => "MULTIPLY_FLOAT",
|
||||||
|
Self::MULTIPLY_BYTE => "MULTIPLY_BYTE",
|
||||||
|
Self::DIVIDE_INT => "DIVIDE_INT",
|
||||||
|
Self::DIVIDE_FLOAT => "DIVIDE_FLOAT",
|
||||||
|
Self::DIVIDE_BYTE => "DIVIDE_BYTE",
|
||||||
|
Self::MODULO_INT => "MODULO_INT",
|
||||||
|
Self::MODULO_FLOAT => "MODULO_FLOAT",
|
||||||
|
Self::MODULO_BYTE => "MODULO_BYTE",
|
||||||
|
Self::EQUAL_INT => "EQUAL_INT",
|
||||||
|
Self::EQUAL_FLOAT => "EQUAL_FLOAT",
|
||||||
|
Self::EQUAL_BYTE => "EQUAL_BYTE",
|
||||||
|
Self::EQUAL_STR => "EQUAL_STR",
|
||||||
|
Self::EQUAL_CHAR => "EQUAL_CHAR",
|
||||||
|
Self::EQUAL_STR_CHAR => "EQUAL_STR_CHAR",
|
||||||
|
Self::EQUAL_CHAR_STR => "EQUAL_CHAR_STR",
|
||||||
|
Self::EQUAL_BOOL => "EQUAL_BOOL",
|
||||||
|
Self::LESS_INT => "LESS_INT",
|
||||||
|
Self::LESS_FLOAT => "LESS_FLOAT",
|
||||||
|
Self::LESS_BYTE => "LESS_BYTE",
|
||||||
|
Self::LESS_STR => "LESS_STR",
|
||||||
|
Self::LESS_CHAR => "LESS_CHAR",
|
||||||
|
Self::LESS_EQUAL_INT => "LESS_EQUAL_INT",
|
||||||
|
Self::LESS_EQUAL_FLOAT => "LESS_EQUAL_FLOAT",
|
||||||
|
Self::LESS_EQUAL_BYTE => "LESS_EQUAL_BYTE",
|
||||||
|
Self::LESS_EQUAL_STR => "LESS_EQUAL_STR",
|
||||||
|
Self::LESS_EQUAL_CHAR => "LESS_EQUAL_CHAR",
|
||||||
|
Self::NEGATE_INT => "NEGATE_INT",
|
||||||
|
Self::NEGATE_FLOAT => "NEGATE_FLOAT",
|
||||||
|
Self::NOT => "NOT",
|
||||||
Self::TEST => "TEST",
|
Self::TEST => "TEST",
|
||||||
Self::TEST_SET => "TEST_SET",
|
Self::TEST_SET => "TEST_SET",
|
||||||
Self::EQUAL => "EQUAL",
|
|
||||||
Self::LESS => "LESS",
|
|
||||||
Self::LESS_EQUAL => "LESS_EQUAL",
|
|
||||||
Self::NEGATE => "NEGATE",
|
|
||||||
Self::NOT => "NOT",
|
|
||||||
Self::CALL => "CALL",
|
Self::CALL => "CALL",
|
||||||
Self::CALL_NATIVE => "CALL_NATIVE",
|
Self::CALL_NATIVE => "CALL_NATIVE",
|
||||||
Self::JUMP => "JUMP",
|
Self::JUMP => "JUMP",
|
||||||
@ -68,6 +157,51 @@ impl Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_math(self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
Operation::ADD_INT
|
||||||
|
| Operation::ADD_FLOAT
|
||||||
|
| Operation::ADD_BYTE
|
||||||
|
| Operation::SUBTRACT_INT
|
||||||
|
| Operation::SUBTRACT_FLOAT
|
||||||
|
| Operation::SUBTRACT_BYTE
|
||||||
|
| Operation::MULTIPLY_INT
|
||||||
|
| Operation::MULTIPLY_FLOAT
|
||||||
|
| Operation::MULTIPLY_BYTE
|
||||||
|
| Operation::DIVIDE_INT
|
||||||
|
| Operation::DIVIDE_FLOAT
|
||||||
|
| Operation::DIVIDE_BYTE
|
||||||
|
| Operation::MODULO_INT
|
||||||
|
| Operation::MODULO_FLOAT
|
||||||
|
| Operation::MODULO_BYTE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_comparison(self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
Operation::EQUAL_INT
|
||||||
|
| Operation::EQUAL_FLOAT
|
||||||
|
| Operation::EQUAL_BYTE
|
||||||
|
| Operation::EQUAL_STR
|
||||||
|
| Operation::EQUAL_CHAR
|
||||||
|
| Operation::EQUAL_STR_CHAR
|
||||||
|
| Operation::EQUAL_CHAR_STR
|
||||||
|
| Operation::EQUAL_BOOL
|
||||||
|
| Operation::LESS_INT
|
||||||
|
| Operation::LESS_FLOAT
|
||||||
|
| Operation::LESS_BYTE
|
||||||
|
| Operation::LESS_STR
|
||||||
|
| Operation::LESS_CHAR
|
||||||
|
| Operation::LESS_EQUAL_INT
|
||||||
|
| Operation::LESS_EQUAL_FLOAT
|
||||||
|
| Operation::LESS_EQUAL_BYTE
|
||||||
|
| Operation::LESS_EQUAL_STR
|
||||||
|
| Operation::LESS_EQUAL_CHAR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn panic_from_unknown_code(code: u8) -> ! {
|
pub fn panic_from_unknown_code(code: u8) -> ! {
|
||||||
panic!("Unknown operation code: {code}");
|
panic!("Unknown operation code: {code}");
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub from: u8,
|
pub from: u16,
|
||||||
pub to: u8,
|
pub to: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for Point {
|
impl From<Instruction> for Point {
|
||||||
@ -16,6 +18,22 @@ impl From<Instruction> for Point {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Point> for Instruction {
|
||||||
|
fn from(r#move: Point) -> Self {
|
||||||
|
let operation = Operation::POINT;
|
||||||
|
let b_field = r#move.from;
|
||||||
|
let c_field = r#move.to;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Point {
|
impl Display for Point {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
let Point { from, to } = self;
|
let Point { from, to } = self;
|
||||||
@ -23,13 +41,3 @@ impl Display for Point {
|
|||||||
write!(f, "{from} -> {to}")
|
write!(f, "{from} -> {to}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Point> for Instruction {
|
|
||||||
fn from(r#move: Point) -> Self {
|
|
||||||
let operation = Operation::POINT;
|
|
||||||
let b = r#move.from;
|
|
||||||
let c = r#move.to;
|
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, false, false, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Return {
|
pub struct Return {
|
||||||
pub should_return_value: bool,
|
pub should_return_value: bool,
|
||||||
pub return_register: u8,
|
pub return_register: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for Return {
|
impl From<Instruction> for Return {
|
||||||
@ -20,9 +22,15 @@ impl From<Instruction> for Return {
|
|||||||
impl From<Return> for Instruction {
|
impl From<Return> for Instruction {
|
||||||
fn from(r#return: Return) -> Self {
|
fn from(r#return: Return) -> Self {
|
||||||
let operation = Operation::RETURN;
|
let operation = Operation::RETURN;
|
||||||
let b = r#return.should_return_value as u8;
|
let b_field = r#return.should_return_value as u16;
|
||||||
let c = r#return.return_register;
|
let c_field = r#return.return_register;
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct SetLocal {
|
pub struct SetLocal {
|
||||||
pub register_index: u8,
|
pub register_index: u16,
|
||||||
pub local_index: u8,
|
pub local_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for SetLocal {
|
impl From<Instruction> for SetLocal {
|
||||||
@ -20,9 +24,26 @@ impl From<Instruction> for SetLocal {
|
|||||||
impl From<SetLocal> for Instruction {
|
impl From<SetLocal> for Instruction {
|
||||||
fn from(set_local: SetLocal) -> Self {
|
fn from(set_local: SetLocal) -> Self {
|
||||||
let operation = Operation::SET_LOCAL;
|
let operation = Operation::SET_LOCAL;
|
||||||
let b = set_local.register_index;
|
let b_field = set_local.register_index;
|
||||||
let c = set_local.local_index;
|
let c_field = set_local.local_index;
|
||||||
|
|
||||||
Instruction::new(operation, 0, b, c, false, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SetLocal {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let SetLocal {
|
||||||
|
register_index,
|
||||||
|
local_index,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "L{local_index} = R{register_index}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
|
||||||
|
|
||||||
pub struct Subtract {
|
|
||||||
pub destination: u8,
|
|
||||||
pub left: Argument,
|
|
||||||
pub right: Argument,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Instruction> for Subtract {
|
|
||||||
fn from(instruction: Instruction) -> Self {
|
|
||||||
let destination = instruction.a_field();
|
|
||||||
let (left, right) = instruction.b_and_c_as_arguments();
|
|
||||||
|
|
||||||
Subtract {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Subtract> for Instruction {
|
|
||||||
fn from(subtract: Subtract) -> Self {
|
|
||||||
let operation = Operation::SUBTRACT;
|
|
||||||
let a = subtract.destination;
|
|
||||||
let (b, b_is_constant) = subtract.left.as_index_and_constant_flag();
|
|
||||||
let (c, c_is_constant) = subtract.right.as_index_and_constant_flag();
|
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, c_is_constant, false)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/subtract_byte.rs
Normal file
54
dust-lang/src/instruction/subtract_byte.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct SubtractByte {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for SubtractByte {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
SubtractByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SubtractByte> for Instruction {
|
||||||
|
fn from(subtract_byte: SubtractByte) -> Self {
|
||||||
|
let operation = Operation::SUBTRACT_BYTE;
|
||||||
|
let a_field = subtract_byte.destination;
|
||||||
|
let (b_field, b_is_constant) = subtract_byte.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = subtract_byte.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SubtractByte {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let SubtractByte {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} - {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/subtract_float.rs
Normal file
54
dust-lang/src/instruction/subtract_float.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct SubtractFloat {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for SubtractFloat {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
SubtractFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SubtractFloat> for Instruction {
|
||||||
|
fn from(subtract_float: SubtractFloat) -> Self {
|
||||||
|
let operation = Operation::SUBTRACT_FLOAT;
|
||||||
|
let a_field = subtract_float.destination;
|
||||||
|
let (b_field, b_is_constant) = subtract_float.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = subtract_float.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SubtractFloat {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let SubtractFloat {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} - {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
54
dust-lang/src/instruction/subtract_int.rs
Normal file
54
dust-lang/src/instruction/subtract_int.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
||||||
|
|
||||||
|
pub struct SubtractInt {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub right: Operand,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for SubtractInt {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
|
||||||
|
SubtractInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SubtractInt> for Instruction {
|
||||||
|
fn from(subtract_int: SubtractInt) -> Self {
|
||||||
|
let operation = Operation::SUBTRACT_INT;
|
||||||
|
let a_field = subtract_int.destination;
|
||||||
|
let (b_field, b_is_constant) = subtract_int.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = subtract_int.right.as_index_and_constant_flag();
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SubtractInt {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let SubtractInt {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{} = {} - {}", destination, left, right)
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct Test {
|
pub struct Test {
|
||||||
pub operand_register: u8,
|
pub operand_register: u16,
|
||||||
pub test_value: bool,
|
pub test_value: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,14 +21,15 @@ impl From<Instruction> for Test {
|
|||||||
|
|
||||||
impl From<Test> for Instruction {
|
impl From<Test> for Instruction {
|
||||||
fn from(test: Test) -> Self {
|
fn from(test: Test) -> Self {
|
||||||
Instruction::new(
|
let b_field = test.operand_register;
|
||||||
Operation::TEST,
|
let c_field = test.test_value as u16;
|
||||||
0,
|
|
||||||
test.operand_register,
|
InstructionBuilder {
|
||||||
test.test_value as u8,
|
operation: Operation::TEST,
|
||||||
false,
|
b_field,
|
||||||
false,
|
c_field,
|
||||||
false,
|
..Default::default()
|
||||||
)
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::{Argument, Instruction, Operation};
|
use crate::{Instruction, Operand, Operation};
|
||||||
|
|
||||||
|
use super::InstructionBuilder;
|
||||||
|
|
||||||
pub struct TestSet {
|
pub struct TestSet {
|
||||||
pub destination: u8,
|
pub destination: u16,
|
||||||
pub argument: Argument,
|
pub argument: Operand,
|
||||||
pub test_value: bool,
|
pub test_value: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,10 +25,18 @@ impl From<Instruction> for TestSet {
|
|||||||
impl From<TestSet> for Instruction {
|
impl From<TestSet> for Instruction {
|
||||||
fn from(test_set: TestSet) -> Self {
|
fn from(test_set: TestSet) -> Self {
|
||||||
let operation = Operation::TEST;
|
let operation = Operation::TEST;
|
||||||
let a = test_set.destination;
|
let a_field = test_set.destination;
|
||||||
let (b, b_is_constant) = test_set.argument.as_index_and_constant_flag();
|
let (b_field, b_is_constant) = test_set.argument.as_index_and_constant_flag();
|
||||||
let c = test_set.test_value as u8;
|
let c_field = test_set.test_value as u16;
|
||||||
|
|
||||||
Instruction::new(operation, a, b, c, b_is_constant, false, false)
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
pub struct TypeCode(pub u8);
|
|
||||||
|
|
||||||
impl TypeCode {
|
|
||||||
const INTEGER: u8 = 0;
|
|
||||||
const FLOAT: u8 = 1;
|
|
||||||
const STRING: u8 = 2;
|
|
||||||
const BOOLEAN: u8 = 3;
|
|
||||||
const CHARACTER: u8 = 4;
|
|
||||||
const BYTE: u8 = 5;
|
|
||||||
}
|
|
@ -40,17 +40,17 @@ pub mod value;
|
|||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
|
||||||
pub use crate::chunk::{Chunk, Disassembler, Local, Scope};
|
pub use crate::chunk::{Chunk, Disassembler, Local, Scope};
|
||||||
pub use crate::compiler::{compile, CompileError, Compiler};
|
pub use crate::compiler::{CompileError, Compiler, compile};
|
||||||
pub use crate::dust_error::{AnnotatedError, DustError};
|
pub use crate::dust_error::{AnnotatedError, DustError};
|
||||||
pub use crate::instruction::{Argument, Instruction, InstructionData, Operation};
|
pub use crate::instruction::{Operand, Instruction, Operation};
|
||||||
pub use crate::lexer::{lex, LexError, Lexer};
|
pub use crate::lexer::{LexError, Lexer, lex};
|
||||||
pub use crate::native_function::{NativeFunction, NativeFunctionError};
|
pub use crate::native_function::{NativeFunction, NativeFunctionError};
|
||||||
pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict};
|
|
||||||
pub use crate::token::{Token, TokenKind, TokenOwned};
|
pub use crate::token::{Token, TokenKind, TokenOwned};
|
||||||
|
pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict};
|
||||||
pub use crate::value::{
|
pub use crate::value::{
|
||||||
AbstractList, ConcreteValue, DustString, Function, RangeValue, Value, ValueError,
|
AbstractList, ConcreteValue, DustString, Function, RangeValue, Value, ValueError,
|
||||||
};
|
};
|
||||||
pub use crate::vm::{run, Pointer, Vm};
|
pub use crate::vm::{Pointer, Vm, run};
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use std::{ops::Range, panic};
|
|||||||
|
|
||||||
use crate::vm::ThreadData;
|
use crate::vm::ThreadData;
|
||||||
|
|
||||||
pub fn panic(data: &mut ThreadData, _: u8, argument_range: Range<u8>) -> bool {
|
pub fn panic(data: &mut ThreadData, _: u16, argument_range: Range<u16>) -> bool {
|
||||||
let position = data.current_position();
|
let position = data.current_position();
|
||||||
let mut message = format!("Dust panic at {position}!");
|
let mut message = format!("Dust panic at {position}!");
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
vm::{Register, ThreadData, get_next_action},
|
vm::{Register, ThreadData, get_next_action},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn read_line(data: &mut ThreadData, destination: u8, _argument_range: Range<u8>) -> bool {
|
pub fn read_line(data: &mut ThreadData, destination: u16, _argument_range: Range<u16>) -> bool {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
|
||||||
if stdin().read_line(&mut buffer).is_ok() {
|
if stdin().read_line(&mut buffer).is_ok() {
|
||||||
@ -24,7 +24,7 @@ pub fn read_line(data: &mut ThreadData, destination: u8, _argument_range: Range<
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(data: &mut ThreadData, _: u8, argument_range: Range<u8>) -> bool {
|
pub fn write(data: &mut ThreadData, _: u16, argument_range: Range<u16>) -> bool {
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
|
|
||||||
for register_index in argument_range {
|
for register_index in argument_range {
|
||||||
@ -40,7 +40,7 @@ pub fn write(data: &mut ThreadData, _: u8, argument_range: Range<u8>) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_line(data: &mut ThreadData, _: u8, argument_range: Range<u8>) -> bool {
|
pub fn write_line(data: &mut ThreadData, _: u16, argument_range: Range<u16>) -> bool {
|
||||||
let mut stdout = stdout().lock();
|
let mut stdout = stdout().lock();
|
||||||
|
|
||||||
for register_index in argument_range {
|
for register_index in argument_range {
|
||||||
|
@ -35,8 +35,8 @@ macro_rules! define_native_function {
|
|||||||
pub fn call(
|
pub fn call(
|
||||||
&self,
|
&self,
|
||||||
data: &mut ThreadData,
|
data: &mut ThreadData,
|
||||||
destination: u8,
|
destination: u16,
|
||||||
argument_range: Range<u8>,
|
argument_range: Range<u16>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
@ -80,8 +80,8 @@ macro_rules! define_native_function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u8> for NativeFunction {
|
impl From<u16> for NativeFunction {
|
||||||
fn from(bytes: u8) -> Self {
|
fn from(bytes: u16) -> Self {
|
||||||
match bytes {
|
match bytes {
|
||||||
$(
|
$(
|
||||||
$bytes => NativeFunction::$name,
|
$bytes => NativeFunction::$name,
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
vm::{Register, ThreadData, get_next_action},
|
vm::{Register, ThreadData, get_next_action},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn random_int(data: &mut ThreadData, destination: u8, argument_range: Range<u8>) -> bool {
|
pub fn random_int(data: &mut ThreadData, destination: u16, argument_range: Range<u16>) -> bool {
|
||||||
let mut argument_range_iter = argument_range.into_iter();
|
let mut argument_range_iter = argument_range.into_iter();
|
||||||
let (min, max) = {
|
let (min, max) = {
|
||||||
let mut min = None;
|
let mut min = None;
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
vm::{Register, ThreadData, get_next_action},
|
vm::{Register, ThreadData, get_next_action},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn to_string(data: &mut ThreadData, destination: u8, argument_range: Range<u8>) -> bool {
|
pub fn to_string(data: &mut ThreadData, destination: u16, argument_range: Range<u16>) -> bool {
|
||||||
let argument_value = data.open_register_unchecked(argument_range.start);
|
let argument_value = data.open_register_unchecked(argument_range.start);
|
||||||
let argument_string = argument_value.display(data);
|
let argument_string = argument_value.display(data);
|
||||||
let register = Register::Value(Value::Concrete(ConcreteValue::string(argument_string)));
|
let register = Register::Value(Value::Concrete(ConcreteValue::string(argument_string)));
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
vm::{Thread, ThreadData, get_next_action},
|
vm::{Thread, ThreadData, get_next_action},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn start_thread(data: &mut ThreadData, argument_range: Range<u8>) -> JoinHandle<()> {
|
fn start_thread(data: &mut ThreadData, argument_range: Range<u16>) -> JoinHandle<()> {
|
||||||
let mut argument_range_iter = argument_range.into_iter();
|
let mut argument_range_iter = argument_range.into_iter();
|
||||||
let function_argument = {
|
let function_argument = {
|
||||||
loop {
|
loop {
|
||||||
@ -56,7 +56,7 @@ fn start_thread(data: &mut ThreadData, argument_range: Range<u8>) -> JoinHandle<
|
|||||||
.expect("Critical VM Error: Failed to spawn thread")
|
.expect("Critical VM Error: Failed to spawn thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(data: &mut ThreadData, _: u8, argument_range: Range<u8>) -> bool {
|
pub fn spawn(data: &mut ThreadData, _: u16, argument_range: Range<u16>) -> bool {
|
||||||
let _ = start_thread(data, argument_range);
|
let _ = start_thread(data, argument_range);
|
||||||
data.next_action = get_next_action(data);
|
data.next_action = get_next_action(data);
|
||||||
|
|
||||||
|
@ -273,13 +273,13 @@ impl Ord for Type {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct FunctionType {
|
pub struct FunctionType {
|
||||||
pub type_parameters: Vec<u8>,
|
pub type_parameters: Vec<u16>,
|
||||||
pub value_parameters: Vec<(u8, Type)>,
|
pub value_parameters: Vec<(u16, Type)>,
|
||||||
pub return_type: Type,
|
pub return_type: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionType {
|
impl FunctionType {
|
||||||
pub fn new<T: Into<Vec<u8>>, U: Into<Vec<(u8, Type)>>>(
|
pub fn new<T: Into<Vec<u16>>, U: Into<Vec<(u16, Type)>>>(
|
||||||
type_parameters: T,
|
type_parameters: T,
|
||||||
value_parameters: U,
|
value_parameters: U,
|
||||||
return_type: Type,
|
return_type: Type,
|
||||||
|
@ -8,7 +8,7 @@ use super::DustString;
|
|||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: Option<DustString>,
|
pub name: Option<DustString>,
|
||||||
pub r#type: FunctionType,
|
pub r#type: FunctionType,
|
||||||
pub prototype_index: u8,
|
pub prototype_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
impl Display for Function {
|
||||||
|
@ -11,12 +11,12 @@ use super::Register;
|
|||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
pub chunk: Arc<Chunk>,
|
pub chunk: Arc<Chunk>,
|
||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: u8,
|
pub return_register: u16,
|
||||||
pub registers: Vec<Register>,
|
pub registers: Vec<Register>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCall {
|
impl FunctionCall {
|
||||||
pub fn new(chunk: Arc<Chunk>, return_register: u8) -> Self {
|
pub fn new(chunk: Arc<Chunk>, return_register: u16) -> Self {
|
||||||
let register_count = chunk.register_count;
|
let register_count = chunk.register_count;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -53,7 +53,7 @@ impl Vm {
|
|||||||
let _ = tx.send(value_option);
|
let _ = tx.send(value_option);
|
||||||
});
|
});
|
||||||
|
|
||||||
rx.recv().unwrap()
|
rx.recv().unwrap_or(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +76,9 @@ impl Display for Register {
|
|||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Pointer {
|
pub enum Pointer {
|
||||||
Register(u8),
|
Register(u16),
|
||||||
Constant(u8),
|
Constant(u16),
|
||||||
Stack(usize, u8),
|
Stack(usize, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Pointer {
|
impl Display for Pointer {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractList, Argument, ConcreteValue, Instruction, Type, Value,
|
AbstractList, ConcreteValue, Instruction, Operand, Type, Value,
|
||||||
instruction::{
|
instruction::{
|
||||||
Add, Call, CallNative, Close, Divide, Equal, GetLocal, Jump, Less, LessEqual, LoadBoolean,
|
Call, CallNative, Close, GetLocal, Jump, LoadBoolean, LoadConstant, LoadFunction, LoadList,
|
||||||
LoadConstant, LoadFunction, LoadList, LoadSelf, Modulo, Multiply, Negate, Not, Point,
|
LoadSelf, Not, Point, Return, SetLocal, Test, TestSet,
|
||||||
Return, SetLocal, Subtract, Test, TestSet,
|
|
||||||
},
|
},
|
||||||
vm::FunctionCall,
|
vm::FunctionCall,
|
||||||
};
|
};
|
||||||
@ -145,6 +144,7 @@ pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let LoadList {
|
let LoadList {
|
||||||
destination,
|
destination,
|
||||||
start_register,
|
start_register,
|
||||||
|
jump_next,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let mut item_pointers = Vec::with_capacity((destination - start_register) as usize);
|
let mut item_pointers = Vec::with_capacity((destination - start_register) as usize);
|
||||||
let mut item_type = Type::Any;
|
let mut item_type = Type::Any;
|
||||||
@ -186,6 +186,7 @@ pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let LoadFunction {
|
let LoadFunction {
|
||||||
destination,
|
destination,
|
||||||
prototype_index,
|
prototype_index,
|
||||||
|
jump_next,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let prototype_index = prototype_index as usize;
|
let prototype_index = prototype_index as usize;
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
let current_call = data.call_stack.last_mut_unchecked();
|
||||||
@ -201,7 +202,10 @@ pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> bool {
|
||||||
let LoadSelf { destination } = instruction.into();
|
let LoadSelf {
|
||||||
|
destination,
|
||||||
|
jump_next,
|
||||||
|
} = instruction.into();
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
let current_call = data.call_stack.last_mut_unchecked();
|
||||||
let prototype = ¤t_call.chunk;
|
let prototype = ¤t_call.chunk;
|
||||||
let function = prototype.as_function();
|
let function = prototype.as_function();
|
||||||
@ -397,8 +401,8 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
if boolean == test_value {
|
if boolean == test_value {
|
||||||
} else {
|
} else {
|
||||||
let pointer = match argument {
|
let pointer = match argument {
|
||||||
Argument::Constant(constant_index) => Pointer::Constant(constant_index),
|
Operand::Constant(constant_index) => Pointer::Constant(constant_index),
|
||||||
Argument::Register(register_index) => Pointer::Register(register_index),
|
Operand::Register(register_index) => Pointer::Register(register_index),
|
||||||
};
|
};
|
||||||
let register = Register::Pointer(pointer);
|
let register = Register::Pointer(pointer);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use std::{mem::replace, sync::Arc, thread::JoinHandle};
|
|||||||
|
|
||||||
use tracing::{info, trace};
|
use tracing::{info, trace};
|
||||||
|
|
||||||
use crate::{Argument, Chunk, DustString, Span, Value, vm::FunctionCall};
|
use crate::{Chunk, DustString, Operand, Span, Value, vm::FunctionCall};
|
||||||
|
|
||||||
use super::{Pointer, Register, RunAction, Stack};
|
use super::{Pointer, Register, RunAction, Stack};
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ impl Thread {
|
|||||||
pub struct ThreadData {
|
pub struct ThreadData {
|
||||||
pub call_stack: Stack<FunctionCall>,
|
pub call_stack: Stack<FunctionCall>,
|
||||||
pub next_action: RunAction,
|
pub next_action: RunAction,
|
||||||
pub return_value_index: Option<u8>,
|
pub return_value_index: Option<u16>,
|
||||||
pub spawned_threads: Vec<JoinHandle<()>>,
|
pub spawned_threads: Vec<JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_register_unchecked(&self, register_index: u8) -> &Register {
|
pub fn get_register_unchecked(&self, register_index: u16) -> &Register {
|
||||||
trace!("Get R{register_index}");
|
trace!("Get R{register_index}");
|
||||||
|
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
@ -122,13 +122,13 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_register(&mut self, to_register: u8, register: Register) {
|
pub fn set_register(&mut self, to_register: u16, register: Register) {
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
self.call_stack.last_mut_unchecked().registers[to_register] = register;
|
self.call_stack.last_mut_unchecked().registers[to_register] = register;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_register_unchecked(&self, register_index: u8) -> &Value {
|
pub fn open_register_unchecked(&self, register_index: u16) -> &Value {
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
|
|
||||||
let register = if cfg!(debug_assertions) {
|
let register = if cfg!(debug_assertions) {
|
||||||
@ -151,7 +151,7 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_register_allow_empty_unchecked(&self, register_index: u8) -> Option<&Value> {
|
pub fn open_register_allow_empty_unchecked(&self, register_index: u16) -> Option<&Value> {
|
||||||
trace!("Open R{register_index}");
|
trace!("Open R{register_index}");
|
||||||
|
|
||||||
let register = self.get_register_unchecked(register_index);
|
let register = self.get_register_unchecked(register_index);
|
||||||
@ -165,7 +165,7 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty_register_or_clone_constant_unchecked(&mut self, register_index: u8) -> Value {
|
pub fn empty_register_or_clone_constant_unchecked(&mut self, register_index: u16) -> Value {
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
let old_register = replace(
|
let old_register = replace(
|
||||||
&mut self.call_stack.last_mut_unchecked().registers[register_index],
|
&mut self.call_stack.last_mut_unchecked().registers[register_index],
|
||||||
@ -202,7 +202,7 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_register_value_or_constant_unchecked(&self, register_index: u8) -> Value {
|
pub fn clone_register_value_or_constant_unchecked(&self, register_index: u16) -> Value {
|
||||||
let register = self.get_register_unchecked(register_index);
|
let register = self.get_register_unchecked(register_index);
|
||||||
|
|
||||||
match register {
|
match register {
|
||||||
@ -232,14 +232,14 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// DRY helper to get a value from an Argument
|
/// DRY helper to get a value from an Argument
|
||||||
pub fn get_argument_unchecked(&self, argument: Argument) -> &Value {
|
pub fn get_argument_unchecked(&self, argument: Operand) -> &Value {
|
||||||
match argument {
|
match argument {
|
||||||
Argument::Constant(constant_index) => self.get_constant_unchecked(constant_index),
|
Operand::Constant(constant_index) => self.get_constant_unchecked(constant_index),
|
||||||
Argument::Register(register_index) => self.open_register_unchecked(register_index),
|
Operand::Register(register_index) => self.open_register_unchecked(register_index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_constant_unchecked(&self, constant_index: u8) -> &Value {
|
pub fn get_constant_unchecked(&self, constant_index: u16) -> &Value {
|
||||||
let constant_index = constant_index as usize;
|
let constant_index = constant_index as usize;
|
||||||
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
@ -255,7 +255,7 @@ impl ThreadData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_local_register(&self, local_index: u8) -> u8 {
|
pub fn get_local_register(&self, local_index: u16) -> u16 {
|
||||||
let local_index = local_index as usize;
|
let local_index = local_index as usize;
|
||||||
let chunk = &self.call_stack.last_unchecked().chunk;
|
let chunk = &self.call_stack.last_unchecked().chunk;
|
||||||
|
|
||||||
|
@ -61,11 +61,11 @@ fn parentheses_precedence() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::add(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::add(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(3, 4)
|
Span(3, 4)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::multiply(1, Argument::Register(0), Argument::Constant(2)),
|
Instruction::multiply(1, Operand::Register(0), Operand::Constant(2)),
|
||||||
Span(8, 9)
|
Span(8, 9)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(11, 11)),
|
(Instruction::r#return(true), Span(11, 11)),
|
||||||
@ -97,19 +97,19 @@ fn math_operator_precedence() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::add(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::add(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::multiply(1, Argument::Constant(2), Argument::Constant(3)),
|
Instruction::multiply(1, Operand::Constant(2), Operand::Constant(3)),
|
||||||
Span(10, 11)
|
Span(10, 11)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::divide(2, Argument::Register(1), Argument::Constant(4)),
|
Instruction::divide(2, Operand::Register(1), Operand::Constant(4)),
|
||||||
Span(14, 15)
|
Span(14, 15)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::subtract(3, Argument::Register(0), Argument::Register(2)),
|
Instruction::subtract(3, Operand::Register(0), Operand::Register(2)),
|
||||||
Span(6, 7)
|
Span(6, 7)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(17, 17)),
|
(Instruction::r#return(true), Span(17, 17)),
|
||||||
|
@ -15,7 +15,7 @@ fn equal() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::equal(0, true, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::equal(0, true, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 4)
|
Span(2, 4)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(6, 6)),
|
(Instruction::r#return(true), Span(6, 6)),
|
||||||
@ -43,7 +43,7 @@ fn greater() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::less_equal(0, false, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::less_equal(0, false, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
@ -71,7 +71,7 @@ fn greater_than_or_equal() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::less(0, false, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::less(0, false, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 4)
|
Span(2, 4)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(6, 6)),
|
(Instruction::r#return(true), Span(6, 6)),
|
||||||
@ -99,7 +99,7 @@ fn less_than() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::less(0, true, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::less(0, true, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
@ -127,7 +127,7 @@ fn less_than_or_equal() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::less_equal(0, true, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::less_equal(0, true, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 4)
|
Span(2, 4)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(6, 6)),
|
(Instruction::r#return(true), Span(6, 6)),
|
||||||
@ -155,7 +155,7 @@ fn not_equal() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::equal(0, false, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::equal(0, false, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 4)
|
Span(2, 4)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(6, 6)),
|
(Instruction::r#return(true), Span(6, 6)),
|
||||||
|
@ -20,7 +20,7 @@ fn function() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::add(2, Argument::Register(0), Argument::Register(1)),
|
Instruction::add(2, Operand::Register(0), Operand::Register(1)),
|
||||||
Span(30, 31)
|
Span(30, 31)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(34, 35)),
|
(Instruction::r#return(true), Span(34, 35)),
|
||||||
@ -51,7 +51,7 @@ fn function_call() {
|
|||||||
(Instruction::load_constant(0, 0, false), Span(0, 35)),
|
(Instruction::load_constant(0, 0, false), Span(0, 35)),
|
||||||
(Instruction::load_constant(1, 1, false), Span(36, 37)),
|
(Instruction::load_constant(1, 1, false), Span(36, 37)),
|
||||||
(Instruction::load_constant(2, 2, false), Span(39, 40)),
|
(Instruction::load_constant(2, 2, false), Span(39, 40)),
|
||||||
(Instruction::call(3, Argument::Constant(0), 2), Span(35, 41)),
|
(Instruction::call(3, Operand::Constant(0), 2), Span(35, 41)),
|
||||||
(Instruction::r#return(true), Span(41, 41)),
|
(Instruction::r#return(true), Span(41, 41)),
|
||||||
],
|
],
|
||||||
vec![
|
vec![
|
||||||
@ -64,7 +64,7 @@ fn function_call() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::add(2, Argument::Register(0), Argument::Register(1)),
|
Instruction::add(2, Operand::Register(0), Operand::Register(1)),
|
||||||
Span(30, 31)
|
Span(30, 31)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(34, 35)),
|
(Instruction::r#return(true), Span(34, 35)),
|
||||||
@ -112,7 +112,7 @@ fn function_declaration() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::add(2, Argument::Register(0), Argument::Register(1)),
|
Instruction::add(2, Operand::Register(0), Operand::Register(1)),
|
||||||
Span(35, 36)
|
Span(35, 36)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(39, 40)),
|
(Instruction::r#return(true), Span(39, 40)),
|
||||||
|
@ -80,15 +80,15 @@ fn list_with_complex_expression() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(1, 2)),
|
(Instruction::load_constant(0, 0, false), Span(1, 2)),
|
||||||
(
|
(
|
||||||
Instruction::add(1, Argument::Constant(1), Argument::Constant(2)),
|
Instruction::add(1, Operand::Constant(1), Operand::Constant(2)),
|
||||||
Span(6, 7)
|
Span(6, 7)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::multiply(2, Argument::Constant(3), Argument::Constant(4)),
|
Instruction::multiply(2, Operand::Constant(3), Operand::Constant(4)),
|
||||||
Span(14, 15)
|
Span(14, 15)
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Instruction::subtract(3, Argument::Register(1), Argument::Register(2)),
|
Instruction::subtract(3, Operand::Register(1), Operand::Register(2)),
|
||||||
Span(10, 11)
|
Span(10, 11)
|
||||||
),
|
),
|
||||||
(Instruction::close(1, 3), Span(17, 18)),
|
(Instruction::close(1, 3), Span(17, 18)),
|
||||||
@ -131,7 +131,7 @@ fn list_with_simple_expression() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(1, 2)),
|
(Instruction::load_constant(0, 0, false), Span(1, 2)),
|
||||||
(
|
(
|
||||||
Instruction::add(1, Argument::Constant(1), Argument::Constant(2)),
|
Instruction::add(1, Operand::Constant(1), Operand::Constant(2)),
|
||||||
Span(6, 7)
|
Span(6, 7)
|
||||||
),
|
),
|
||||||
(Instruction::load_constant(2, 3, false), Span(11, 12)),
|
(Instruction::load_constant(2, 3, false), Span(11, 12)),
|
||||||
|
@ -16,12 +16,12 @@ fn r#while() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
||||||
(
|
(
|
||||||
Instruction::less(0, true, Argument::Register(0), Argument::Constant(2)),
|
Instruction::less(0, true, Operand::Register(0), Operand::Constant(2)),
|
||||||
Span(23, 24)
|
Span(23, 24)
|
||||||
),
|
),
|
||||||
(Instruction::jump(2, true), Span(41, 42)),
|
(Instruction::jump(2, true), Span(41, 42)),
|
||||||
(
|
(
|
||||||
Instruction::add(0, Argument::Register(0), Argument::Constant(3)),
|
Instruction::add(0, Operand::Register(0), Operand::Constant(3)),
|
||||||
Span(35, 36)
|
Span(35, 36)
|
||||||
),
|
),
|
||||||
(Instruction::jump(3, false), Span(41, 42)),
|
(Instruction::jump(3, false), Span(41, 42)),
|
||||||
|
@ -15,7 +15,7 @@ fn divide_bytes() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::divide(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::divide(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(5, 6)
|
Span(5, 6)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(11, 11))
|
(Instruction::r#return(true), Span(11, 11))
|
||||||
@ -43,7 +43,7 @@ fn divide_floats() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::divide(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::divide(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(4, 5)
|
Span(4, 5)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(9, 9))
|
(Instruction::r#return(true), Span(9, 9))
|
||||||
@ -71,7 +71,7 @@ fn divide_integers() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::divide(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::divide(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5))
|
(Instruction::r#return(true), Span(5, 5))
|
||||||
|
@ -16,7 +16,7 @@ fn divide_assign() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
||||||
(
|
(
|
||||||
Instruction::divide(0, Argument::Register(0), Argument::Constant(0)),
|
Instruction::divide(0, Operand::Register(0), Operand::Constant(0)),
|
||||||
Span(17, 19)
|
Span(17, 19)
|
||||||
),
|
),
|
||||||
(Instruction::get_local(1, 0), Span(23, 24)),
|
(Instruction::get_local(1, 0), Span(23, 24)),
|
||||||
|
@ -15,7 +15,7 @@ fn modulo_floats() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::modulo(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::modulo(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(4, 5)
|
Span(4, 5)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(9, 9))
|
(Instruction::r#return(true), Span(9, 9))
|
||||||
@ -43,7 +43,7 @@ fn modulo_integers() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::modulo(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::modulo(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5))
|
(Instruction::r#return(true), Span(5, 5))
|
||||||
|
@ -15,7 +15,7 @@ fn multiply_floats() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::multiply(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::multiply(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(4, 5)
|
Span(4, 5)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(9, 9)),
|
(Instruction::r#return(true), Span(9, 9)),
|
||||||
@ -43,7 +43,7 @@ fn multiply_integers() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::multiply(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::multiply(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
|
@ -16,7 +16,7 @@ fn multiply_assign() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
(Instruction::load_constant(0, 0, false), Span(12, 13)),
|
||||||
(
|
(
|
||||||
Instruction::multiply(0, Argument::Register(0), Argument::Constant(2)),
|
Instruction::multiply(0, Operand::Register(0), Operand::Constant(2)),
|
||||||
Span(17, 19)
|
Span(17, 19)
|
||||||
),
|
),
|
||||||
(Instruction::get_local(1, 0), Span(22, 23)),
|
(Instruction::get_local(1, 0), Span(22, 23)),
|
||||||
|
@ -15,7 +15,7 @@ fn subtract_floats() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::subtract(0, Argument::Constant(0), Argument::Constant(0)),
|
Instruction::subtract(0, Operand::Constant(0), Operand::Constant(0)),
|
||||||
Span(4, 5)
|
Span(4, 5)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(9, 9)),
|
(Instruction::r#return(true), Span(9, 9)),
|
||||||
@ -43,7 +43,7 @@ fn subtract_floats_saturate() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::subtract(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::subtract(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(25, 26)
|
Span(25, 26)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(36, 36)),
|
(Instruction::r#return(true), Span(36, 36)),
|
||||||
@ -74,7 +74,7 @@ fn subtract_integers() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::subtract(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::subtract(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(2, 3)
|
Span(2, 3)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
@ -102,7 +102,7 @@ fn subtract_integers_saturate() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Instruction::subtract(0, Argument::Constant(0), Argument::Constant(1)),
|
Instruction::subtract(0, Operand::Constant(0), Operand::Constant(1)),
|
||||||
Span(21, 22)
|
Span(21, 22)
|
||||||
),
|
),
|
||||||
(Instruction::r#return(true), Span(24, 24)),
|
(Instruction::r#return(true), Span(24, 24)),
|
||||||
|
@ -16,7 +16,7 @@ fn subtract_assign() {
|
|||||||
vec![
|
vec![
|
||||||
(Instruction::load_constant(0, 0, false), Span(12, 14)),
|
(Instruction::load_constant(0, 0, false), Span(12, 14)),
|
||||||
(
|
(
|
||||||
Instruction::subtract(0, Argument::Register(0), Argument::Constant(2)),
|
Instruction::subtract(0, Operand::Register(0), Operand::Constant(2)),
|
||||||
Span(18, 20)
|
Span(18, 20)
|
||||||
),
|
),
|
||||||
(Instruction::get_local(1, 0), Span(24, 25)),
|
(Instruction::get_local(1, 0), Span(24, 25)),
|
||||||
|
@ -14,7 +14,7 @@ fn negate() {
|
|||||||
return_type: Type::Integer,
|
return_type: Type::Integer,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(Instruction::negate(0, Argument::Constant(0)), Span(0, 1)),
|
(Instruction::negate(0, Operand::Constant(0)), Span(0, 1)),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
],
|
],
|
||||||
vec![ConcreteValue::Integer(42)],
|
vec![ConcreteValue::Integer(42)],
|
||||||
@ -40,7 +40,7 @@ fn not() {
|
|||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
(Instruction::load_boolean(0, true, false), Span(1, 5)),
|
(Instruction::load_boolean(0, true, false), Span(1, 5)),
|
||||||
(Instruction::not(1, Argument::Register(0)), Span(0, 1)),
|
(Instruction::not(1, Operand::Register(0)), Span(0, 1)),
|
||||||
(Instruction::r#return(true), Span(5, 5)),
|
(Instruction::r#return(true), Span(5, 5)),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user