Use fewer operations and encode operand types in the instruction
This commit is contained in:
parent
0510e18060
commit
ac1ee793ab
@ -1,62 +0,0 @@
|
|||||||
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,14 +43,14 @@ use std::io::{self, Write};
|
|||||||
|
|
||||||
use colored::{ColoredString, Colorize};
|
use colored::{ColoredString, Colorize};
|
||||||
|
|
||||||
use crate::{Chunk, Local, Type};
|
use crate::{Chunk, Local};
|
||||||
|
|
||||||
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", 36)];
|
||||||
const INSTRUCTION_BORDERS: [&str; 3] = [
|
const INSTRUCTION_BORDERS: [&str; 3] = [
|
||||||
"╭─────┬────────────┬─────────────────┬────────────────────────╮",
|
"╭─────┬────────────┬─────────────────┬────────────────────────────────────╮",
|
||||||
"├─────┼────────────┼─────────────────┼────────────────────────┤",
|
"├─────┼────────────┼─────────────────┼────────────────────────────────────┤",
|
||||||
"╰─────┴────────────┴─────────────────┴────────────────────────╯",
|
"╰─────┴────────────┴─────────────────┴────────────────────────────────────╯",
|
||||||
];
|
];
|
||||||
|
|
||||||
const LOCAL_COLUMNS: [(&str, usize); 5] = [
|
const LOCAL_COLUMNS: [(&str, usize); 5] = [
|
||||||
@ -286,7 +286,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
.unwrap_or("stripped".to_string());
|
.unwrap_or("stripped".to_string());
|
||||||
let operation = instruction.operation().to_string();
|
let operation = instruction.operation().to_string();
|
||||||
let info = instruction.disassembly_info();
|
let info = instruction.disassembly_info();
|
||||||
let row = format!("│{index:^5}│{position:^12}│{operation:^17}│{info:^24}│");
|
let row = format!("│{index:^5}│{position:^12}│{operation:^17}│{info:^36}│");
|
||||||
|
|
||||||
self.write_center_border(&row)?;
|
self.write_center_border(&row)?;
|
||||||
}
|
}
|
||||||
@ -322,7 +322,6 @@ 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());
|
||||||
@ -353,88 +352,8 @@ 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])?;
|
||||||
|
|
||||||
if self.chunk.constants.r#true {
|
for (index, value) in self.chunk.constants.iter().enumerate() {
|
||||||
let type_display = Type::Boolean.to_string();
|
let type_display = value.r#type().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();
|
||||||
|
|
||||||
@ -455,7 +374,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("Prototypes")?;
|
self.write_center_border_bold("Functions")?;
|
||||||
|
|
||||||
for chunk in &self.chunk.prototypes {
|
for chunk in &self.chunk.prototypes {
|
||||||
chunk
|
chunk
|
||||||
|
@ -13,12 +13,10 @@
|
|||||||
//! [`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;
|
||||||
@ -29,7 +27,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{DustString, Function, FunctionType, Instruction, Span};
|
use crate::{DustString, Function, FunctionType, Instruction, Span, Value};
|
||||||
|
|
||||||
/// Representation of a Dust program or function.
|
/// Representation of a Dust program or function.
|
||||||
///
|
///
|
||||||
@ -41,7 +39,7 @@ 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: ConstantTable,
|
pub(crate) constants: Vec<Value>,
|
||||||
pub(crate) locals: Vec<Local>,
|
pub(crate) locals: Vec<Local>,
|
||||||
pub(crate) prototypes: Vec<Arc<Chunk>>,
|
pub(crate) prototypes: Vec<Arc<Chunk>>,
|
||||||
|
|
||||||
@ -56,7 +54,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: ConstantTable,
|
constants: impl Into<Vec<Value>>,
|
||||||
locals: impl Into<Vec<Local>>,
|
locals: impl Into<Vec<Local>>,
|
||||||
prototypes: impl IntoIterator<Item = Chunk>,
|
prototypes: impl IntoIterator<Item = Chunk>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -65,7 +63,7 @@ impl Chunk {
|
|||||||
r#type,
|
r#type,
|
||||||
instructions: instructions.into(),
|
instructions: instructions.into(),
|
||||||
positions: positions.into(),
|
positions: positions.into(),
|
||||||
constants,
|
constants: constants.into(),
|
||||||
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,
|
||||||
|
@ -104,6 +104,14 @@ pub enum CompileError {
|
|||||||
right_type: Type,
|
right_type: Type,
|
||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
|
CannotNegateType {
|
||||||
|
argument_type: Type,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
|
CannotNotType {
|
||||||
|
argument_type: Type,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
CannotSubtractType {
|
CannotSubtractType {
|
||||||
argument_type: Type,
|
argument_type: Type,
|
||||||
position: Span,
|
position: Span,
|
||||||
@ -182,6 +190,8 @@ impl AnnotatedError for CompileError {
|
|||||||
Self::CannotMutateImmutableVariable { .. } => "Cannot mutate immutable variable",
|
Self::CannotMutateImmutableVariable { .. } => "Cannot mutate immutable variable",
|
||||||
Self::CannotMultiplyArguments { .. } => "Cannot multiply these types",
|
Self::CannotMultiplyArguments { .. } => "Cannot multiply these types",
|
||||||
Self::CannotMultiplyType { .. } => "Cannot multiply this type",
|
Self::CannotMultiplyType { .. } => "Cannot multiply this type",
|
||||||
|
Self::CannotNegateType { .. } => "Cannot negate this type",
|
||||||
|
Self::CannotNotType { .. } => "Cannot apply \"not\" operation to this type",
|
||||||
Self::CannotResolveRegisterType { .. } => "Cannot resolve register type",
|
Self::CannotResolveRegisterType { .. } => "Cannot resolve register type",
|
||||||
Self::CannotResolveVariableType { .. } => "Cannot resolve type",
|
Self::CannotResolveVariableType { .. } => "Cannot resolve type",
|
||||||
Self::CannotSubtractType { .. } => "Cannot subtract from this type",
|
Self::CannotSubtractType { .. } => "Cannot subtract from this type",
|
||||||
@ -251,8 +261,10 @@ impl AnnotatedError for CompileError {
|
|||||||
right_position,
|
right_position,
|
||||||
} => {
|
} => {
|
||||||
vec![(
|
vec![(
|
||||||
format!("Type \"{left_type}\" cannot be added to type \"{right_type}\". Try converting one of the values to the other type."),
|
format!(
|
||||||
Span(left_position.0, right_position.1)
|
"Type \"{left_type}\" cannot be, added to type \"{right_type}\". Try converting one of the values to the other type."
|
||||||
|
),
|
||||||
|
Span(left_position.0, right_position.1),
|
||||||
)]
|
)]
|
||||||
}
|
}
|
||||||
_ => Vec::with_capacity(0),
|
_ => Vec::with_capacity(0),
|
||||||
|
@ -35,8 +35,7 @@ use optimize::control_flow_register_consolidation;
|
|||||||
use crate::{
|
use crate::{
|
||||||
Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
|
Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
|
||||||
NativeFunction, Operand, Operation, Scope, Span, Token, TokenKind, Type, Value,
|
NativeFunction, Operand, Operation, Scope, Span, Token, TokenKind, Type, Value,
|
||||||
chunk::ConstantTable,
|
instruction::{CallNative, Close, GetLocal, Jump, LoadList, Return, SetLocal, TypeCode},
|
||||||
instruction::{GetLocal, Jump, LoadList},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Compiles the input and returns a chunk.
|
/// Compiles the input and returns a chunk.
|
||||||
@ -89,7 +88,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: ConstantTable,
|
constants: Vec<Value>,
|
||||||
|
|
||||||
/// 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.
|
||||||
@ -145,7 +144,7 @@ impl<'src> Compiler<'src> {
|
|||||||
return_type: Type::None,
|
return_type: Type::None,
|
||||||
},
|
},
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
constants: ConstantTable::new(),
|
constants: Vec::new(),
|
||||||
locals: Vec::new(),
|
locals: Vec::new(),
|
||||||
prototypes: Vec::new(),
|
prototypes: Vec::new(),
|
||||||
stack_size: 0,
|
stack_size: 0,
|
||||||
@ -216,7 +215,7 @@ impl<'src> Compiler<'src> {
|
|||||||
r#type: self.r#type,
|
r#type: self.r#type,
|
||||||
instructions,
|
instructions,
|
||||||
positions,
|
positions,
|
||||||
constants: self.constants,
|
constants: self.constants.to_vec(),
|
||||||
locals,
|
locals,
|
||||||
prototypes: self.prototypes,
|
prototypes: self.prototypes,
|
||||||
register_count: self.stack_size,
|
register_count: self.stack_size,
|
||||||
@ -276,10 +275,13 @@ impl<'src> Compiler<'src> {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(index, (local, _))| {
|
.find_map(|(index, (local, _))| {
|
||||||
let identifier = self
|
let constant = self.constants.get(local.identifier_index as usize)?;
|
||||||
.constants
|
let identifier =
|
||||||
.strings
|
if let Value::Concrete(ConcreteValue::String(identifier)) = constant {
|
||||||
.get(local.identifier_index as usize)?;
|
identifier
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
if identifier == identifier_text {
|
if identifier == identifier_text {
|
||||||
Some(index as u16)
|
Some(index as u16)
|
||||||
@ -303,8 +305,8 @@ impl<'src> Compiler<'src> {
|
|||||||
) -> (u16, u16) {
|
) -> (u16, u16) {
|
||||||
info!("Declaring local {identifier}");
|
info!("Declaring local {identifier}");
|
||||||
|
|
||||||
let identifier = DustString::from(identifier);
|
let identifier = Value::Concrete(ConcreteValue::string(identifier));
|
||||||
let identifier_index = self.push_or_get_constant_string(identifier);
|
let identifier_index = self.push_or_get_constant(identifier);
|
||||||
let local_index = self.locals.len() as u16;
|
let local_index = self.locals.len() as u16;
|
||||||
|
|
||||||
self.locals.push((
|
self.locals.push((
|
||||||
@ -320,102 +322,24 @@ impl<'src> Compiler<'src> {
|
|||||||
.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_bool(&mut self, boolean: bool) -> u16 {
|
fn push_or_get_constant(&mut self, value: Value) -> 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(|&byte| byte == new_byte)
|
.position(|constant| constant == &value)
|
||||||
{
|
{
|
||||||
index as u16
|
index as u16
|
||||||
} else {
|
} else {
|
||||||
self.constants.bytes.push(new_byte);
|
let index = self.constants.len() as u16;
|
||||||
|
|
||||||
(self.constants.bytes.len() - 1) as u16
|
self.constants.push(value);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_or_get_constant_character(&mut self, new_character: char) -> u16 {
|
index
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,14 +481,6 @@ 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;
|
||||||
|
|
||||||
@ -735,17 +651,39 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let instruction = match (operator, &previous_type) {
|
let type_code = match previous_type {
|
||||||
(Token::Bang, Type::Boolean) => Instruction::not(destination, argument),
|
Type::Boolean => TypeCode::BOOLEAN,
|
||||||
(Token::Minus, Type::Float) => Instruction::negate_float(destination, argument),
|
Type::Byte => TypeCode::BYTE,
|
||||||
(Token::Minus, Type::Integer) => Instruction::negate_int(destination, argument),
|
Type::Character => TypeCode::CHARACTER,
|
||||||
_ => {
|
Type::Float => TypeCode::FLOAT,
|
||||||
return Err(CompileError::ExpectedTokenMultiple {
|
Type::Integer => TypeCode::INTEGER,
|
||||||
expected: &[TokenKind::Bang, TokenKind::Minus],
|
Type::String => TypeCode::STRING,
|
||||||
found: operator.to_owned(),
|
_ => match operator {
|
||||||
position: operator_position,
|
Token::Minus => {
|
||||||
});
|
return Err(CompileError::CannotNegateType {
|
||||||
}
|
argument_type: previous_type,
|
||||||
|
position: previous_position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Token::Bang => {
|
||||||
|
return Err(CompileError::CannotNotType {
|
||||||
|
argument_type: previous_type,
|
||||||
|
position: previous_position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(CompileError::ExpectedTokenMultiple {
|
||||||
|
expected: &[TokenKind::Bang, TokenKind::Minus],
|
||||||
|
found: operator.to_owned(),
|
||||||
|
position: operator_position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let instruction = match operator {
|
||||||
|
Token::Bang => Instruction::not(destination, argument),
|
||||||
|
Token::Minus => Instruction::negate(destination, argument, type_code),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.emit_instruction(instruction, previous_type, operator_position);
|
self.emit_instruction(instruction, previous_type, operator_position);
|
||||||
@ -768,43 +706,15 @@ impl<'src> Compiler<'src> {
|
|||||||
Operation::LOAD_BOOLEAN
|
Operation::LOAD_BOOLEAN
|
||||||
| Operation::LOAD_LIST
|
| Operation::LOAD_LIST
|
||||||
| Operation::LOAD_SELF
|
| Operation::LOAD_SELF
|
||||||
| Operation::ADD_BYTE
|
| Operation::ADD
|
||||||
| Operation::ADD_CHAR
|
| Operation::SUBTRACT
|
||||||
| Operation::ADD_CHAR_STR
|
| Operation::MULTIPLY
|
||||||
| Operation::ADD_FLOAT
|
| Operation::DIVIDE
|
||||||
| Operation::ADD_INT
|
| Operation::MODULO
|
||||||
| Operation::ADD_STR
|
| Operation::EQUAL
|
||||||
| Operation::ADD_STR_CHAR
|
| Operation::LESS
|
||||||
| Operation::SUBTRACT_BYTE
|
| Operation::LESS_EQUAL
|
||||||
| Operation::SUBTRACT_FLOAT
|
| Operation::NEGATE
|
||||||
| 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 => (Operand::Register(instruction.a_field()), true),
|
| Operation::CALL => (Operand::Register(instruction.a_field()), true),
|
||||||
Operation::CALL_NATIVE => {
|
Operation::CALL_NATIVE => {
|
||||||
@ -869,6 +779,16 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
check_math_type(&left_type, operator, &left_position)?;
|
check_math_type(&left_type, operator, &left_position)?;
|
||||||
|
|
||||||
|
let left_type_code = match left_type {
|
||||||
|
Type::Boolean => TypeCode::BOOLEAN,
|
||||||
|
Type::Byte => TypeCode::BYTE,
|
||||||
|
Type::Character => TypeCode::CHARACTER,
|
||||||
|
Type::Float => TypeCode::FLOAT,
|
||||||
|
Type::Integer => TypeCode::INTEGER,
|
||||||
|
Type::String => TypeCode::STRING,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
if is_assignment && !left_is_mutable_local {
|
if is_assignment && !left_is_mutable_local {
|
||||||
return Err(CompileError::ExpectedMutableVariable {
|
return Err(CompileError::ExpectedMutableVariable {
|
||||||
found: self.previous_token.to_owned(),
|
found: self.previous_token.to_owned(),
|
||||||
@ -891,9 +811,19 @@ impl<'src> Compiler<'src> {
|
|||||||
&right_position,
|
&right_position,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let right_type_code = match right_type {
|
||||||
|
Type::Boolean => TypeCode::BOOLEAN,
|
||||||
|
Type::Byte => TypeCode::BYTE,
|
||||||
|
Type::Character => TypeCode::CHARACTER,
|
||||||
|
Type::Float => TypeCode::FLOAT,
|
||||||
|
Type::Integer => TypeCode::INTEGER,
|
||||||
|
Type::String => TypeCode::STRING,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
if push_back_right {
|
if push_back_right {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((right_instruction, right_type.clone(), right_position));
|
.push((right_instruction, right_type, right_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
let r#type = if is_assignment {
|
let r#type = if is_assignment {
|
||||||
@ -911,63 +841,21 @@ impl<'src> Compiler<'src> {
|
|||||||
} else {
|
} else {
|
||||||
self.next_register()
|
self.next_register()
|
||||||
};
|
};
|
||||||
let instruction = match (operator, left_type, right_type) {
|
let instruction = match operator {
|
||||||
(Token::Plus, Type::Byte, Type::Byte) => {
|
Token::Plus | Token::PlusEqual => {
|
||||||
Instruction::add_byte(destination, left, right)
|
Instruction::add(destination, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::Plus, Type::Character, Type::Character) => {
|
Token::Minus | Token::MinusEqual => {
|
||||||
Instruction::add_char(destination, left, right)
|
Instruction::subtract(destination, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::Plus, Type::Character, Type::String) => {
|
Token::Star | Token::StarEqual => {
|
||||||
Instruction::add_char_str(destination, left, right)
|
Instruction::multiply(destination, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::Plus, Type::Float, Type::Float) => {
|
Token::Slash | Token::SlashEqual => {
|
||||||
Instruction::add_float(destination, left, right)
|
Instruction::divide(destination, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::Plus, Type::Integer, Type::Integer) => {
|
Token::Percent | Token::PercentEqual => {
|
||||||
Instruction::add_int(destination, left, right)
|
Instruction::modulo(destination, left, left_type_code, right, right_type_code)
|
||||||
}
|
|
||||||
(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 {
|
||||||
@ -995,9 +883,13 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
fn parse_comparison_binary(&mut self) -> Result<(), CompileError> {
|
||||||
if self
|
if let Some(
|
||||||
.get_last_operation()
|
[
|
||||||
.is_some_and(|operation| operation.is_comparison())
|
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
],
|
||||||
|
) = self.get_last_operations()
|
||||||
{
|
{
|
||||||
return Err(CompileError::ComparisonChain {
|
return Err(CompileError::ComparisonChain {
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
@ -1016,9 +908,21 @@ impl<'src> Compiler<'src> {
|
|||||||
let operator_position = self.current_position;
|
let operator_position = self.current_position;
|
||||||
let rule = ParseRule::from(&operator);
|
let rule = ParseRule::from(&operator);
|
||||||
|
|
||||||
|
// TODO: Check if the left type is a valid type for comparison
|
||||||
|
|
||||||
|
let left_type_code = match left_type {
|
||||||
|
Type::Boolean => TypeCode::BOOLEAN,
|
||||||
|
Type::Byte => TypeCode::BYTE,
|
||||||
|
Type::Character => TypeCode::CHARACTER,
|
||||||
|
Type::Float => TypeCode::FLOAT,
|
||||||
|
Type::Integer => TypeCode::INTEGER,
|
||||||
|
Type::String => TypeCode::STRING,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
if push_back_left {
|
if push_back_left {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((left_instruction, left_type.clone(), left_position));
|
.push((left_instruction, left_type, left_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
@ -1033,112 +937,41 @@ impl<'src> Compiler<'src> {
|
|||||||
})?;
|
})?;
|
||||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?;
|
let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?;
|
||||||
|
|
||||||
|
// TODO: Check if the right type is a valid type for comparison
|
||||||
|
// TODO: Check if the left and right types are compatible
|
||||||
|
|
||||||
|
let right_type_code = match right_type {
|
||||||
|
Type::Boolean => TypeCode::BOOLEAN,
|
||||||
|
Type::Byte => TypeCode::BYTE,
|
||||||
|
Type::Character => TypeCode::CHARACTER,
|
||||||
|
Type::Float => TypeCode::FLOAT,
|
||||||
|
Type::Integer => TypeCode::INTEGER,
|
||||||
|
Type::String => TypeCode::STRING,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
if push_back_right {
|
if push_back_right {
|
||||||
self.instructions
|
self.instructions
|
||||||
.push((right_instruction, right_type.clone(), right_position));
|
.push((right_instruction, right_type, right_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let comparison = match (operator, left_type, right_type) {
|
let comparison = match operator {
|
||||||
(Token::DoubleEqual, Type::Boolean, Type::Boolean) => {
|
Token::DoubleEqual => {
|
||||||
Instruction::equal_bool(true, left, right)
|
Instruction::equal(true, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::DoubleEqual, Type::Byte, Type::Byte) => {
|
Token::BangEqual => {
|
||||||
Instruction::equal_byte(true, left, right)
|
Instruction::equal(false, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::DoubleEqual, Type::Character, Type::Character) => {
|
Token::Less => Instruction::less(true, left, left_type_code, right, right_type_code),
|
||||||
Instruction::equal_char(true, left, right)
|
Token::LessEqual => {
|
||||||
|
Instruction::less_equal(true, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::DoubleEqual, Type::Character, Type::String) => {
|
Token::Greater => {
|
||||||
Instruction::equal_char_str(true, left, right)
|
Instruction::less_equal(false, left, left_type_code, right, right_type_code)
|
||||||
}
|
}
|
||||||
(Token::DoubleEqual, Type::Float, Type::Float) => {
|
Token::GreaterEqual => {
|
||||||
Instruction::equal_float(true, left, right)
|
Instruction::less(false, left, left_type_code, right, right_type_code)
|
||||||
}
|
|
||||||
(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 {
|
||||||
@ -1223,23 +1056,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
instructions[0].0.operation(),
|
instructions[0].0.operation(),
|
||||||
Operation::TEST
|
Operation::TEST | 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
|
|
||||||
) || !matches!(instructions[1].0.operation(), Operation::JUMP)
|
) || !matches!(instructions[1].0.operation(), Operation::JUMP)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -1321,7 +1138,10 @@ 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::set_local(register, local_index);
|
let set_local = Instruction::from(SetLocal {
|
||||||
|
register_index: register,
|
||||||
|
local_index,
|
||||||
|
});
|
||||||
|
|
||||||
self.emit_instruction(set_local, Type::None, start_position);
|
self.emit_instruction(set_local, Type::None, start_position);
|
||||||
}
|
}
|
||||||
@ -1396,7 +1216,10 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if expected_register < actual_register {
|
if expected_register < actual_register {
|
||||||
let close = Instruction::close(expected_register, actual_register);
|
let close = Instruction::from(Close {
|
||||||
|
from: expected_register,
|
||||||
|
to: actual_register,
|
||||||
|
});
|
||||||
|
|
||||||
self.emit_instruction(close, Type::None, self.current_position);
|
self.emit_instruction(close, Type::None, self.current_position);
|
||||||
}
|
}
|
||||||
@ -1420,22 +1243,7 @@ impl<'src> Compiler<'src> {
|
|||||||
if matches!(
|
if matches!(
|
||||||
self.get_last_operations(),
|
self.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::EQUAL_INT
|
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
||||||
| 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
|
||||||
@ -1508,7 +1316,10 @@ impl<'src> Compiler<'src> {
|
|||||||
loader.set_c_field(true as u16);
|
loader.set_c_field(true as u16);
|
||||||
} else {
|
} else {
|
||||||
if_block_distance += 1;
|
if_block_distance += 1;
|
||||||
let jump = Instruction::jump(else_block_distance, true);
|
let jump = Instruction::from(Jump {
|
||||||
|
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));
|
||||||
@ -1516,7 +1327,10 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
2.. => {
|
2.. => {
|
||||||
if_block_distance += 1;
|
if_block_distance += 1;
|
||||||
let jump = Instruction::jump(else_block_distance, true);
|
let jump = Instruction::from(Jump {
|
||||||
|
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));
|
||||||
@ -1535,29 +1349,14 @@ 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 u16;
|
let expression_start = self.instructions.len();
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
if matches!(
|
if matches!(
|
||||||
self.get_last_operations(),
|
self.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::EQUAL_INT
|
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
||||||
| 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
|
||||||
@ -1577,15 +1376,21 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
self.parse_block()?;
|
self.parse_block()?;
|
||||||
|
|
||||||
let block_end = self.instructions.len() as u16;
|
let block_end = self.instructions.len();
|
||||||
let jump_distance = block_end - block_start as u16 + 1;
|
let jump_distance = (block_end - block_start + 1) as u16;
|
||||||
let jump = Instruction::jump(jump_distance, true);
|
let jump = Instruction::from(Jump {
|
||||||
|
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) as u16;
|
||||||
let jump_back = Instruction::jump(jump_back_distance, false);
|
let jump_back = Instruction::from(Jump {
|
||||||
|
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);
|
||||||
|
|
||||||
@ -1604,9 +1409,13 @@ 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 expected_register < actual_register {
|
if registers_to_close > 0 {
|
||||||
let close = Instruction::close(expected_register, actual_register);
|
let close = Instruction::from(Close {
|
||||||
|
from: expected_register,
|
||||||
|
to: actual_register,
|
||||||
|
});
|
||||||
|
|
||||||
self.emit_instruction(close, Type::None, self.current_position);
|
self.emit_instruction(close, Type::None, self.current_position);
|
||||||
}
|
}
|
||||||
@ -1618,7 +1427,11 @@ 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::call_native(destination, function, argument_count);
|
let call_native = Instruction::from(CallNative {
|
||||||
|
destination,
|
||||||
|
function,
|
||||||
|
argument_count,
|
||||||
|
});
|
||||||
|
|
||||||
self.emit_instruction(call_native, return_type, Span(start, end));
|
self.emit_instruction(call_native, return_type, Span(start, end));
|
||||||
|
|
||||||
@ -1681,7 +1494,10 @@ 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::r#return(should_return_value, return_register);
|
let r#return = Instruction::from(Return {
|
||||||
|
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));
|
||||||
|
|
||||||
@ -1980,13 +1796,16 @@ 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::close(expected_register, actual_register);
|
let close = Instruction::from(Close {
|
||||||
|
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)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,23 +37,7 @@ pub fn control_flow_register_consolidation(compiler: &mut Compiler) {
|
|||||||
if !matches!(
|
if !matches!(
|
||||||
compiler.get_last_operations(),
|
compiler.get_last_operations(),
|
||||||
Some([
|
Some([
|
||||||
Operation::TEST
|
Operation::TEST | 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_CONSTANT,
|
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
||||||
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT,
|
||||||
|
69
dust-lang/src/instruction/add.rs
Normal file
69
dust-lang/src/instruction/add.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Add {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Add {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Add {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Add> for Instruction {
|
||||||
|
fn from(add: Add) -> Self {
|
||||||
|
let operation = Operation::ADD;
|
||||||
|
let a_field = add.destination;
|
||||||
|
let (b_field, b_is_constant) = add.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = add.right.as_index_and_constant_flag();
|
||||||
|
let b_type = add.left_type;
|
||||||
|
let c_type = add.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Add {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Add {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = {left}({left_type}) + {right}({right_type})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -43,3 +45,29 @@ impl From<Call> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Call {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Call {
|
||||||
|
destination,
|
||||||
|
function_register,
|
||||||
|
argument_count,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
let arguments_start = destination.saturating_sub(*argument_count);
|
||||||
|
|
||||||
|
match argument_count {
|
||||||
|
0 => write!(f, "R{destination} = R{function_register}()"),
|
||||||
|
1 => write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = R{function_register}(R{arguments_start})"
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = R{function_register}(R{arguments_start}..R{destination})"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::{Instruction, NativeFunction, Operation};
|
use crate::{Instruction, NativeFunction, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -38,3 +40,27 @@ impl From<CallNative> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for CallNative {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let CallNative {
|
||||||
|
destination,
|
||||||
|
function,
|
||||||
|
argument_count,
|
||||||
|
} = self;
|
||||||
|
let arguments_start = destination.saturating_sub(*argument_count);
|
||||||
|
let arguments_end = arguments_start + argument_count;
|
||||||
|
|
||||||
|
if function.returns_value() {
|
||||||
|
write!(f, "R{destination} = ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
match argument_count {
|
||||||
|
0 => {
|
||||||
|
write!(f, "{function}()")
|
||||||
|
}
|
||||||
|
1 => write!(f, "{function}(R{arguments_start})"),
|
||||||
|
_ => write!(f, "{function}(R{arguments_start}..R{arguments_end})"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
69
dust-lang/src/instruction/divide.rs
Normal file
69
dust-lang/src/instruction/divide.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Divide {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Divide {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Divide {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Divide> for Instruction {
|
||||||
|
fn from(divide: Divide) -> Self {
|
||||||
|
let operation = Operation::DIVIDE;
|
||||||
|
let a_field = divide.destination;
|
||||||
|
let (b_field, b_is_constant) = divide.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = divide.right.as_index_and_constant_flag();
|
||||||
|
let b_type = divide.left_type;
|
||||||
|
let c_type = divide.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Divide {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Divide {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = {left_type}({left}) ÷ {right_type}({right})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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,32 +1,40 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
pub struct EqualBool {
|
pub struct Equal {
|
||||||
pub comparator: bool,
|
pub comparator: bool,
|
||||||
pub left: Operand,
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
pub right: Operand,
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for EqualBool {
|
impl From<Instruction> for Equal {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: Instruction) -> Self {
|
||||||
let comparator = instruction.d_field();
|
let comparator = instruction.d_field();
|
||||||
let (left, right) = instruction.b_and_c_as_operands();
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
EqualBool {
|
Equal {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EqualBool> for Instruction {
|
impl From<Equal> for Instruction {
|
||||||
fn from(equal_bool: EqualBool) -> Self {
|
fn from(equal_bool: Equal) -> Self {
|
||||||
let operation = Operation::EQUAL_BOOL;
|
let operation = Operation::EQUAL;
|
||||||
let (b_field, b_is_constant) = equal_bool.left.as_index_and_constant_flag();
|
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 (c_field, c_is_constant) = equal_bool.right.as_index_and_constant_flag();
|
||||||
let d_field = equal_bool.comparator;
|
let d_field = equal_bool.comparator;
|
||||||
|
let b_type = equal_bool.left_type;
|
||||||
|
let c_type = equal_bool.right_type;
|
||||||
|
|
||||||
InstructionBuilder {
|
InstructionBuilder {
|
||||||
operation,
|
operation,
|
||||||
@ -35,21 +43,28 @@ impl From<EqualBool> for Instruction {
|
|||||||
d_field,
|
d_field,
|
||||||
b_is_constant,
|
b_is_constant,
|
||||||
c_is_constant,
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for EqualBool {
|
impl Display for Equal {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
let EqualBool {
|
let Equal {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = self;
|
} = self;
|
||||||
let operator = if *comparator { "==" } else { "≠" };
|
let operator = if *comparator { "==" } else { "≠" };
|
||||||
|
|
||||||
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
write!(
|
||||||
|
f,
|
||||||
|
"if {left}({left_type}) {operator} {right}({right_type}) {{ JUMP +1 }}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -31,3 +33,15 @@ impl From<Jump> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Jump {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Jump {
|
||||||
|
offset,
|
||||||
|
is_positive,
|
||||||
|
} = self;
|
||||||
|
let sign = if *is_positive { "+" } else { "-" };
|
||||||
|
|
||||||
|
write!(f, "JUMP {sign}{offset}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
70
dust-lang/src/instruction/less.rs
Normal file
70
dust-lang/src/instruction/less.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Less {
|
||||||
|
pub comparator: bool,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Less {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Less {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Less> for Instruction {
|
||||||
|
fn from(less: Less) -> Self {
|
||||||
|
let operation = Operation::LESS;
|
||||||
|
let (b_field, b_is_constant) = less.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = less.right.as_index_and_constant_flag();
|
||||||
|
let d_field = less.comparator;
|
||||||
|
let b_type = less.left_type;
|
||||||
|
let c_type = less.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
d_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Less {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Less {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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,32 +1,40 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use super::{Instruction, InstructionBuilder, Operand, Operation};
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
pub struct LessEqualByte {
|
pub struct LessEqual {
|
||||||
pub comparator: bool,
|
pub comparator: bool,
|
||||||
pub left: Operand,
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
pub right: Operand,
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for LessEqualByte {
|
impl From<Instruction> for LessEqual {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: Instruction) -> Self {
|
||||||
let comparator = instruction.d_field();
|
let comparator = instruction.d_field();
|
||||||
let (left, right) = instruction.b_and_c_as_operands();
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
LessEqualByte {
|
LessEqual {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LessEqualByte> for Instruction {
|
impl From<LessEqual> for Instruction {
|
||||||
fn from(less_equal_byte: LessEqualByte) -> Self {
|
fn from(less_equal_byte: LessEqual) -> Self {
|
||||||
let operation = Operation::LESS_EQUAL_BYTE;
|
let operation = Operation::LESS_EQUAL;
|
||||||
let (b_field, b_is_constant) = less_equal_byte.left.as_index_and_constant_flag();
|
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 (c_field, c_is_constant) = less_equal_byte.right.as_index_and_constant_flag();
|
||||||
let d_field = less_equal_byte.comparator;
|
let d_field = less_equal_byte.comparator;
|
||||||
|
let b_type = less_equal_byte.left_type;
|
||||||
|
let c_type = less_equal_byte.right_type;
|
||||||
|
|
||||||
InstructionBuilder {
|
InstructionBuilder {
|
||||||
operation,
|
operation,
|
||||||
@ -35,21 +43,28 @@ impl From<LessEqualByte> for Instruction {
|
|||||||
d_field,
|
d_field,
|
||||||
b_is_constant,
|
b_is_constant,
|
||||||
c_is_constant,
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for LessEqualByte {
|
impl Display for LessEqual {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
let LessEqualByte {
|
let LessEqual {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = self;
|
} = self;
|
||||||
let operator = if *comparator { "≤" } else { ">" };
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
write!(
|
||||||
|
f,
|
||||||
|
"if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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 }}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,11 +7,11 @@
|
|||||||
//! Bits | Description
|
//! Bits | Description
|
||||||
//! ----- | -----------
|
//! ----- | -----------
|
||||||
//! 0-6 | Operation
|
//! 0-6 | Operation
|
||||||
//! 7 | Unused
|
//! 7 | Flag indicating if the B field is a constant
|
||||||
//! 8 | Flag indicating if the B field is a constant
|
//! 8 | Flag indicating if the C field is a constant
|
||||||
//! 9 | Flag indicating if the C field is a constant
|
//! 9 | D field (boolean)
|
||||||
//! 10 | D field (boolean)
|
//! 10-12 | B field type
|
||||||
//! 11-15 | Unused
|
//! 13-15 | C field type
|
||||||
//! 16-31 | A field (unsigned 16-bit integer)
|
//! 16-31 | A field (unsigned 16-bit integer)
|
||||||
//! 32-47 | B field (unsigned 16-bit integer)
|
//! 32-47 | B field (unsigned 16-bit integer)
|
||||||
//! 48-63 | C field (unsigned 16-bit integer)
|
//! 48-63 | C field (unsigned 16-bit integer)
|
||||||
@ -93,122 +93,64 @@
|
|||||||
//!
|
//!
|
||||||
//! assert!(is_add_assign);
|
//! assert!(is_add_assign);
|
||||||
//! ```
|
//! ```
|
||||||
mod add_byte;
|
mod add;
|
||||||
mod add_char;
|
|
||||||
mod add_char_str;
|
|
||||||
mod add_float;
|
|
||||||
mod add_int;
|
|
||||||
mod add_str;
|
|
||||||
mod add_str_char;
|
|
||||||
mod call;
|
mod call;
|
||||||
mod call_native;
|
mod call_native;
|
||||||
mod close;
|
mod close;
|
||||||
mod divide_byte;
|
mod divide;
|
||||||
mod divide_float;
|
mod equal;
|
||||||
mod divide_int;
|
|
||||||
mod equal_bool;
|
|
||||||
mod equal_byte;
|
|
||||||
mod equal_char;
|
|
||||||
mod equal_char_str;
|
|
||||||
mod equal_float;
|
|
||||||
mod equal_int;
|
|
||||||
mod equal_str;
|
|
||||||
mod equal_str_char;
|
|
||||||
mod get_local;
|
mod get_local;
|
||||||
mod jump;
|
mod jump;
|
||||||
mod less_byte;
|
mod less;
|
||||||
mod less_char;
|
mod less_equal;
|
||||||
mod less_equal_byte;
|
|
||||||
mod less_equal_char;
|
|
||||||
mod less_equal_float;
|
|
||||||
mod less_equal_int;
|
|
||||||
mod less_equal_str;
|
|
||||||
mod less_float;
|
|
||||||
mod less_int;
|
|
||||||
mod less_str;
|
|
||||||
mod load_boolean;
|
mod load_boolean;
|
||||||
mod load_constant;
|
mod load_constant;
|
||||||
mod load_function;
|
mod load_function;
|
||||||
mod load_list;
|
mod load_list;
|
||||||
mod load_self;
|
mod load_self;
|
||||||
mod modulo_byte;
|
mod modulo;
|
||||||
mod modulo_float;
|
mod multiply;
|
||||||
mod modulo_int;
|
mod negate;
|
||||||
mod multiply_byte;
|
|
||||||
mod multiply_float;
|
|
||||||
mod multiply_int;
|
|
||||||
mod negate_float;
|
|
||||||
mod negate_int;
|
|
||||||
mod not;
|
mod not;
|
||||||
mod operation;
|
mod operation;
|
||||||
mod point;
|
mod point;
|
||||||
mod r#return;
|
mod r#return;
|
||||||
mod set_local;
|
mod set_local;
|
||||||
mod subtract_byte;
|
mod subtract;
|
||||||
mod subtract_float;
|
|
||||||
mod subtract_int;
|
|
||||||
mod test;
|
mod test;
|
||||||
mod test_set;
|
mod test_set;
|
||||||
|
mod type_code;
|
||||||
|
|
||||||
pub use add_byte::AddByte;
|
pub use add::Add;
|
||||||
pub use add_char::AddChar;
|
|
||||||
pub use add_char_str::AddCharStr;
|
|
||||||
pub use add_float::AddFloat;
|
|
||||||
pub use add_int::AddInt;
|
|
||||||
pub use add_str::AddStr;
|
|
||||||
pub use add_str_char::AddStrChar;
|
|
||||||
pub use call::Call;
|
pub use call::Call;
|
||||||
pub use call_native::CallNative;
|
pub use call_native::CallNative;
|
||||||
pub use close::Close;
|
pub use close::Close;
|
||||||
pub use divide_byte::DivideByte;
|
pub use divide::Divide;
|
||||||
pub use divide_float::DivideFloat;
|
pub use equal::Equal;
|
||||||
pub use divide_int::DivideInt;
|
|
||||||
pub use equal_bool::EqualBool;
|
|
||||||
pub use equal_byte::EqualByte;
|
|
||||||
pub use equal_char::EqualChar;
|
|
||||||
pub use equal_char_str::EqualCharStr;
|
|
||||||
pub use equal_float::EqualFloat;
|
|
||||||
pub use equal_int::EqualInt;
|
|
||||||
pub use equal_str::EqualStr;
|
|
||||||
pub use equal_str_char::EqualStrChar;
|
|
||||||
pub use get_local::GetLocal;
|
pub use get_local::GetLocal;
|
||||||
pub use jump::Jump;
|
pub use jump::Jump;
|
||||||
pub use less_byte::LessByte;
|
pub use less::Less;
|
||||||
pub use less_char::LessChar;
|
pub use less_equal::LessEqual;
|
||||||
pub use less_equal_byte::LessEqualByte;
|
|
||||||
pub use less_equal_char::LessEqualChar;
|
|
||||||
pub use less_equal_float::LessEqualFloat;
|
|
||||||
pub use less_equal_int::LessEqualInt;
|
|
||||||
pub use less_equal_str::LessEqualStr;
|
|
||||||
pub use less_float::LessFloat;
|
|
||||||
pub use less_int::LessInt;
|
|
||||||
pub use less_str::LessStr;
|
|
||||||
pub use load_boolean::LoadBoolean;
|
pub use load_boolean::LoadBoolean;
|
||||||
pub use load_constant::LoadConstant;
|
pub use load_constant::LoadConstant;
|
||||||
pub use load_function::LoadFunction;
|
pub use load_function::LoadFunction;
|
||||||
pub use load_list::LoadList;
|
pub use load_list::LoadList;
|
||||||
pub use load_self::LoadSelf;
|
pub use load_self::LoadSelf;
|
||||||
pub use modulo_byte::ModuloByte;
|
pub use modulo::Modulo;
|
||||||
pub use modulo_float::ModuloFloat;
|
pub use multiply::Multiply;
|
||||||
pub use modulo_int::ModuloInt;
|
pub use negate::Negate;
|
||||||
pub use multiply_byte::MultiplyByte;
|
|
||||||
pub use multiply_float::MultiplyFloat;
|
|
||||||
pub use multiply_int::MultiplyInt;
|
|
||||||
pub use negate_float::NegateFloat;
|
|
||||||
pub use negate_int::NegateInt;
|
|
||||||
pub use not::Not;
|
pub use not::Not;
|
||||||
pub use operation::Operation;
|
pub use operation::Operation;
|
||||||
pub use point::Point;
|
pub use point::Point;
|
||||||
pub use r#return::Return;
|
pub use r#return::Return;
|
||||||
pub use set_local::SetLocal;
|
pub use set_local::SetLocal;
|
||||||
pub use subtract_byte::SubtractByte;
|
pub use subtract::Subtract;
|
||||||
pub use subtract_float::SubtractFloat;
|
|
||||||
pub use subtract_int::SubtractInt;
|
|
||||||
pub use test::Test;
|
pub use test::Test;
|
||||||
pub use test_set::TestSet;
|
pub use test_set::TestSet;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
pub use type_code::TypeCode;
|
||||||
|
|
||||||
use crate::NativeFunction;
|
use crate::NativeFunction;
|
||||||
|
|
||||||
@ -220,17 +162,21 @@ pub struct InstructionBuilder {
|
|||||||
pub d_field: bool,
|
pub d_field: bool,
|
||||||
pub b_is_constant: bool,
|
pub b_is_constant: bool,
|
||||||
pub c_is_constant: bool,
|
pub c_is_constant: bool,
|
||||||
|
pub b_type: TypeCode,
|
||||||
|
pub c_type: TypeCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionBuilder {
|
impl InstructionBuilder {
|
||||||
pub fn build(self) -> Instruction {
|
pub fn build(self) -> Instruction {
|
||||||
let bits = self.operation.0 as u64
|
let bits = ((self.operation.0 as u64) << 57)
|
||||||
| ((self.b_is_constant as u64) << 7)
|
| ((self.b_is_constant as u64) << 56)
|
||||||
| ((self.c_is_constant as u64) << 8)
|
| ((self.c_is_constant as u64) << 55)
|
||||||
| ((self.d_field as u64) << 9)
|
| ((self.d_field as u64) << 54)
|
||||||
| ((self.a_field as u64) << 31)
|
| ((self.b_type.0 as u64) << 51)
|
||||||
| ((self.b_field as u64) << 47)
|
| ((self.c_type.0 as u64) << 48)
|
||||||
| ((self.c_field as u64) << 63);
|
| ((self.a_field as u64) << 32)
|
||||||
|
| ((self.b_field as u64) << 16)
|
||||||
|
| (self.c_field as u64);
|
||||||
|
|
||||||
Instruction(bits)
|
Instruction(bits)
|
||||||
}
|
}
|
||||||
@ -246,11 +192,13 @@ impl Default for InstructionBuilder {
|
|||||||
d_field: false,
|
d_field: false,
|
||||||
b_is_constant: false,
|
b_is_constant: false,
|
||||||
c_is_constant: false,
|
c_is_constant: false,
|
||||||
|
b_type: TypeCode::BOOLEAN,
|
||||||
|
c_type: TypeCode::BOOLEAN,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An operation and its arguments for the Dust virtual machine.
|
/// An instruction for the Dust virtual machine.
|
||||||
///
|
///
|
||||||
/// See the [module-level documentation](index.html) for more information.
|
/// See the [module-level documentation](index.html) for more information.
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -258,33 +206,45 @@ pub struct Instruction(u64);
|
|||||||
|
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
pub fn operation(&self) -> Operation {
|
pub fn operation(&self) -> Operation {
|
||||||
let first_byte = (self.0 & 0b0111_1111) as u8;
|
let first_7_bits = (self.0 >> 57) as u8;
|
||||||
|
|
||||||
Operation(first_byte)
|
Operation(first_7_bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn b_is_constant(&self) -> bool {
|
pub fn b_is_constant(&self) -> bool {
|
||||||
(self.0 >> 8) & 1 == 0
|
(self.0 >> 56) & 1 != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn c_is_constant(&self) -> bool {
|
pub fn c_is_constant(&self) -> bool {
|
||||||
(self.0 >> 9) & 1 == 0
|
(self.0 >> 55) & 1 != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn d_field(&self) -> bool {
|
pub fn d_field(&self) -> bool {
|
||||||
(self.0 >> 10) & 1 == 0
|
(self.0 >> 54) & 1 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn b_type(&self) -> TypeCode {
|
||||||
|
let byte = ((self.0 >> 51) & 0b111) as u8;
|
||||||
|
|
||||||
|
TypeCode(byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c_type(&self) -> TypeCode {
|
||||||
|
let byte = ((self.0 >> 48) & 0b111) as u8;
|
||||||
|
|
||||||
|
TypeCode(byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_field(&self) -> u16 {
|
pub fn a_field(&self) -> u16 {
|
||||||
((self.0 >> 31) & 0xFFFF) as u16
|
((self.0 >> 32) & 0xFFFF) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn b_field(&self) -> u16 {
|
pub fn b_field(&self) -> u16 {
|
||||||
((self.0 >> 47) & 0xFFFF) as u16
|
((self.0 >> 16) & 0xFFFF) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn c_field(&self) -> u16 {
|
pub fn c_field(&self) -> u16 {
|
||||||
(self.0 >> 48) as u16
|
(self.0 & 0xFFFF) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_a_field(&mut self, bits: u16) {
|
pub fn set_a_field(&mut self, bits: u16) {
|
||||||
@ -360,313 +320,139 @@ impl Instruction {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_int(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn add(
|
||||||
Instruction::from(AddInt {
|
destination: u16,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Add {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_float(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn subtract(
|
||||||
Instruction::from(AddFloat {
|
destination: u16,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Subtract {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_byte(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn multiply(
|
||||||
Instruction::from(AddByte {
|
destination: u16,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Multiply {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_str(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn divide(
|
||||||
Instruction::from(AddStr {
|
destination: u16,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Divide {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_char(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn modulo(
|
||||||
Instruction::from(AddChar {
|
destination: u16,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Modulo {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_str_char(destination: u16, left: Operand, right: Operand) -> Instruction {
|
pub fn equal(
|
||||||
Instruction::from(AddStrChar {
|
comparator: bool,
|
||||||
destination,
|
left: Operand,
|
||||||
left,
|
left_type: TypeCode,
|
||||||
right,
|
right: Operand,
|
||||||
})
|
right_type: TypeCode,
|
||||||
}
|
) -> Instruction {
|
||||||
|
Instruction::from(Equal {
|
||||||
pub fn add_char_str(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(AddCharStr {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract_int(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(SubtractInt {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract_float(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(SubtractFloat {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract_byte(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(SubtractByte {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn multiply_int(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(MultiplyInt {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn multiply_float(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(MultiplyFloat {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn multiply_byte(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(MultiplyByte {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn divide_int(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(DivideInt {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn divide_float(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(DivideFloat {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn divide_byte(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(DivideByte {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulo_int(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(ModuloInt {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulo_float(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(ModuloFloat {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulo_byte(destination: u16, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(ModuloByte {
|
|
||||||
destination,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn equal_int(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(EqualInt {
|
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_float(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
pub fn less(
|
||||||
Instruction::from(EqualFloat {
|
comparator: bool,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(Less {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_byte(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
pub fn less_equal(
|
||||||
Instruction::from(EqualByte {
|
comparator: bool,
|
||||||
|
left: Operand,
|
||||||
|
left_type: TypeCode,
|
||||||
|
right: Operand,
|
||||||
|
right_type: TypeCode,
|
||||||
|
) -> Instruction {
|
||||||
|
Instruction::from(LessEqual {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_str(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
pub fn negate(destination: u16, argument: Operand, argument_type: TypeCode) -> Instruction {
|
||||||
Instruction::from(EqualStr {
|
Instruction::from(Negate {
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn equal_char(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(EqualChar {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn equal_str_char(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(EqualStrChar {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn equal_char_str(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(EqualCharStr {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn equal_bool(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(EqualBool {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_int(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessInt {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_float(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessFloat {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_byte(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessByte {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_str(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessStr {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_char(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessChar {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_equal_int(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessEqualInt {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_equal_float(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessEqualFloat {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_equal_byte(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessEqualByte {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_equal_str(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessEqualStr {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_equal_char(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
|
||||||
Instruction::from(LessEqualChar {
|
|
||||||
comparator,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn negate_int(destination: u16, argument: Operand) -> Instruction {
|
|
||||||
Instruction::from(NegateInt {
|
|
||||||
destination,
|
|
||||||
argument,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn negate_float(destination: u16, argument: Operand) -> Instruction {
|
|
||||||
Instruction::from(NegateFloat {
|
|
||||||
destination,
|
destination,
|
||||||
argument,
|
argument,
|
||||||
|
argument_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,45 +533,15 @@ impl Instruction {
|
|||||||
| Operation::LOAD_LIST
|
| Operation::LOAD_LIST
|
||||||
| Operation::LOAD_SELF
|
| Operation::LOAD_SELF
|
||||||
| Operation::GET_LOCAL
|
| Operation::GET_LOCAL
|
||||||
| Operation::ADD_INT
|
| Operation::ADD
|
||||||
| Operation::ADD_FLOAT
|
| Operation::SUBTRACT
|
||||||
| Operation::ADD_BYTE
|
| Operation::MULTIPLY
|
||||||
| Operation::ADD_STR
|
| Operation::DIVIDE
|
||||||
| Operation::ADD_CHAR
|
| Operation::MODULO
|
||||||
| Operation::ADD_STR_CHAR
|
| Operation::EQUAL
|
||||||
| Operation::ADD_CHAR_STR
|
| Operation::LESS
|
||||||
| Operation::SUBTRACT_INT
|
| Operation::LESS_EQUAL
|
||||||
| Operation::SUBTRACT_FLOAT
|
| Operation::NEGATE
|
||||||
| 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
|
|
||||||
| 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
|
|
||||||
| Operation::NEGATE_INT
|
|
||||||
| Operation::NEGATE_FLOAT
|
|
||||||
| Operation::NOT
|
| Operation::NOT
|
||||||
| Operation::CALL => Some(Operand::Register(self.a_field())),
|
| Operation::CALL => Some(Operand::Register(self.a_field())),
|
||||||
Operation::CALL_NATIVE => {
|
Operation::CALL_NATIVE => {
|
||||||
@ -833,27 +589,12 @@ impl Instruction {
|
|||||||
| Operation::LOAD_LIST
|
| Operation::LOAD_LIST
|
||||||
| Operation::LOAD_SELF
|
| Operation::LOAD_SELF
|
||||||
| Operation::GET_LOCAL
|
| Operation::GET_LOCAL
|
||||||
| Operation::ADD_INT
|
| Operation::ADD
|
||||||
| Operation::ADD_FLOAT
|
| Operation::SUBTRACT
|
||||||
| Operation::ADD_BYTE
|
| Operation::MULTIPLY
|
||||||
| Operation::ADD_STR
|
| Operation::DIVIDE
|
||||||
| Operation::ADD_CHAR
|
| Operation::MODULO
|
||||||
| Operation::ADD_STR_CHAR
|
| Operation::NEGATE
|
||||||
| Operation::ADD_CHAR_STR
|
|
||||||
| 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
|
|
||||||
| Operation::NEGATE_INT
|
|
||||||
| Operation::NEGATE_FLOAT
|
|
||||||
| Operation::NOT
|
| Operation::NOT
|
||||||
| Operation::CALL => true,
|
| Operation::CALL => true,
|
||||||
Operation::CALL_NATIVE => {
|
Operation::CALL_NATIVE => {
|
||||||
@ -863,29 +604,14 @@ impl Instruction {
|
|||||||
}
|
}
|
||||||
Operation::CLOSE
|
Operation::CLOSE
|
||||||
| Operation::SET_LOCAL
|
| Operation::SET_LOCAL
|
||||||
| Operation::EQUAL_INT
|
| Operation::EQUAL
|
||||||
| Operation::EQUAL_FLOAT
|
| Operation::LESS
|
||||||
| Operation::EQUAL_BYTE
|
| Operation::LESS_EQUAL
|
||||||
| 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
|
|
||||||
| Operation::TEST
|
| Operation::TEST
|
||||||
| Operation::TEST_SET
|
| Operation::TEST_SET
|
||||||
| Operation::JUMP
|
| Operation::JUMP
|
||||||
| Operation::RETURN => false,
|
| Operation::RETURN => false,
|
||||||
_ => Operation::panic_from_unknown_code(self.operation().0),
|
_ => self.operation().panic_from_unknown_code(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,9 +628,24 @@ impl Instruction {
|
|||||||
Operation::LOAD_SELF => LoadSelf::from(*self).to_string(),
|
Operation::LOAD_SELF => LoadSelf::from(*self).to_string(),
|
||||||
Operation::GET_LOCAL => GetLocal::from(*self).to_string(),
|
Operation::GET_LOCAL => GetLocal::from(*self).to_string(),
|
||||||
Operation::SET_LOCAL => SetLocal::from(*self).to_string(),
|
Operation::SET_LOCAL => SetLocal::from(*self).to_string(),
|
||||||
Operation::ADD_INT => AddInt::from(*self).to_string(),
|
Operation::ADD => Add::from(*self).to_string(),
|
||||||
|
Operation::SUBTRACT => Subtract::from(*self).to_string(),
|
||||||
|
Operation::MULTIPLY => Multiply::from(*self).to_string(),
|
||||||
|
Operation::DIVIDE => Divide::from(*self).to_string(),
|
||||||
|
Operation::MODULO => Modulo::from(*self).to_string(),
|
||||||
|
Operation::NEGATE => Negate::from(*self).to_string(),
|
||||||
|
Operation::NOT => Not::from(*self).to_string(),
|
||||||
|
Operation::EQUAL => Equal::from(*self).to_string(),
|
||||||
|
Operation::LESS => Less::from(*self).to_string(),
|
||||||
|
Operation::LESS_EQUAL => LessEqual::from(*self).to_string(),
|
||||||
|
Operation::TEST => Test::from(*self).to_string(),
|
||||||
|
Operation::TEST_SET => TestSet::from(*self).to_string(),
|
||||||
|
Operation::CALL => Call::from(*self).to_string(),
|
||||||
|
Operation::CALL_NATIVE => CallNative::from(*self).to_string(),
|
||||||
|
Operation::JUMP => Jump::from(*self).to_string(),
|
||||||
|
Operation::RETURN => Return::from(*self).to_string(),
|
||||||
|
|
||||||
_ => Operation::panic_from_unknown_code(operation.0),
|
_ => operation.panic_from_unknown_code(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -966,50 +707,118 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_operation() {
|
fn decode_operation() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Constant(4), Operand::Register(2));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(instruction.operation(), Operation::ADD_INT);
|
assert_eq!(instruction.operation(), Operation::ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_a_field() {
|
fn decode_a_field() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Constant(4), Operand::Register(2));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(42, instruction.a_field());
|
assert_eq!(42, instruction.a_field());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_b_field() {
|
fn decode_b_field() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Constant(4), Operand::Register(2));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(4, instruction.b_field());
|
assert_eq!(4, instruction.b_field());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_c_field() {
|
fn decode_c_field() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Constant(4), Operand::Register(2));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(2, instruction.c_field());
|
assert_eq!(2, instruction.c_field());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_d_field() {
|
fn decode_d_field() {
|
||||||
let instruction = Instruction::call(42, 4, 2, true);
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert!(instruction.d_field());
|
assert!(instruction.d_field());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_b_is_constant() {
|
fn decode_b_is_constant() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Constant(4), Operand::Register(2));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert!(instruction.b_is_constant());
|
assert!(instruction.b_is_constant());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_c_is_constant() {
|
fn decode_c_is_constant() {
|
||||||
let instruction = Instruction::add_int(42, Operand::Register(2), Operand::Constant(4));
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
assert!(instruction.c_is_constant());
|
assert!(instruction.c_is_constant());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_b_type() {
|
||||||
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(TypeCode::STRING, instruction.b_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_c_type() {
|
||||||
|
let instruction = Instruction::add(
|
||||||
|
42,
|
||||||
|
Operand::Constant(4),
|
||||||
|
TypeCode::STRING,
|
||||||
|
Operand::Register(2),
|
||||||
|
TypeCode::CHARACTER,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(TypeCode::CHARACTER, instruction.c_type());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
69
dust-lang/src/instruction/modulo.rs
Normal file
69
dust-lang/src/instruction/modulo.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Modulo {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Modulo {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Modulo {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Modulo> for Instruction {
|
||||||
|
fn from(modulo: Modulo) -> Self {
|
||||||
|
let operation = Operation::MODULO;
|
||||||
|
let a_field = modulo.destination;
|
||||||
|
let (b_field, b_is_constant) = modulo.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = modulo.right.as_index_and_constant_flag();
|
||||||
|
let b_type = modulo.left_type;
|
||||||
|
let c_type = modulo.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Modulo {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Modulo {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = {left_type}({left}) % {right_type}({right})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
69
dust-lang/src/instruction/multiply.rs
Normal file
69
dust-lang/src/instruction/multiply.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Multiply {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Multiply {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Multiply {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Multiply> for Instruction {
|
||||||
|
fn from(multiply: Multiply) -> Self {
|
||||||
|
let operation = Operation::MULTIPLY;
|
||||||
|
let a_field = multiply.destination;
|
||||||
|
let (b_field, b_is_constant) = multiply.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = multiply.right.as_index_and_constant_flag();
|
||||||
|
let b_type = multiply.left_type;
|
||||||
|
let c_type = multiply.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Multiply {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Multiply {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = {left_type}({left}) ✕ {right_type}({right})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
54
dust-lang/src/instruction/negate.rs
Normal file
54
dust-lang/src/instruction/negate.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Negate {
|
||||||
|
pub destination: u16,
|
||||||
|
pub argument: Operand,
|
||||||
|
pub argument_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Negate {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let argument = instruction.b_as_argument();
|
||||||
|
let argument_type = instruction.b_type();
|
||||||
|
|
||||||
|
Negate {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
argument_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Negate> for Instruction {
|
||||||
|
fn from(negate: Negate) -> Self {
|
||||||
|
let operation = Operation::NEGATE;
|
||||||
|
let a_field = negate.destination;
|
||||||
|
let (b_field, b_is_constant) = negate.argument.as_index_and_constant_flag();
|
||||||
|
let b_type = negate.argument_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
b_is_constant,
|
||||||
|
b_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Negate {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Negate {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
argument_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = -{argument_type}({argument})")
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
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}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
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,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::{Instruction, Operand, Operation};
|
use crate::{Instruction, Operand, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -35,3 +37,14 @@ impl From<Not> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Not {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Not {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(f, "R{destination} = !{argument}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,62 +24,20 @@ impl Operation {
|
|||||||
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);
|
||||||
|
|
||||||
// Addition
|
// Arithmetic
|
||||||
pub const ADD_INT: Operation = Operation(9);
|
pub const ADD: Operation = Operation(9);
|
||||||
pub const ADD_FLOAT: Operation = Operation(10);
|
pub const SUBTRACT: Operation = Operation(16);
|
||||||
pub const ADD_BYTE: Operation = Operation(11);
|
pub const MULTIPLY: Operation = Operation(19);
|
||||||
pub const ADD_STR: Operation = Operation(12);
|
pub const DIVIDE: Operation = Operation(22);
|
||||||
pub const ADD_CHAR: Operation = Operation(13);
|
pub const MODULO: Operation = Operation(25);
|
||||||
pub const ADD_STR_CHAR: Operation = Operation(14);
|
|
||||||
pub const ADD_CHAR_STR: Operation = Operation(15);
|
|
||||||
|
|
||||||
// Subtraction
|
// Comparison
|
||||||
pub const SUBTRACT_INT: Operation = Operation(16);
|
pub const EQUAL: Operation = Operation(28);
|
||||||
pub const SUBTRACT_FLOAT: Operation = Operation(17);
|
pub const LESS: Operation = Operation(36);
|
||||||
pub const SUBTRACT_BYTE: Operation = Operation(18);
|
pub const LESS_EQUAL: Operation = Operation(41);
|
||||||
|
|
||||||
// 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
|
// Unary operations
|
||||||
pub const NEGATE_INT: Operation = Operation(46);
|
pub const NEGATE: Operation = Operation(46);
|
||||||
pub const NEGATE_FLOAT: Operation = Operation(47);
|
|
||||||
pub const NOT: Operation = Operation(48);
|
pub const NOT: Operation = Operation(48);
|
||||||
|
|
||||||
// Logical operations
|
// Logical operations
|
||||||
@ -107,45 +65,15 @@ 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_INT => "ADD_INT",
|
Self::ADD => "ADD",
|
||||||
Self::ADD_FLOAT => "ADD_FLOAT",
|
Self::SUBTRACT => "SUBTRACT",
|
||||||
Self::ADD_BYTE => "ADD_BYTE",
|
Self::MULTIPLY => "MULTIPLY",
|
||||||
Self::ADD_STR => "ADD_STR",
|
Self::DIVIDE => "DIVIDE",
|
||||||
Self::ADD_CHAR => "ADD_CHAR",
|
Self::MODULO => "MODULO",
|
||||||
Self::ADD_STR_CHAR => "ADD_STR_CHAR",
|
Self::EQUAL => "EQUAL",
|
||||||
Self::ADD_CHAR_STR => "ADD_CHAR_STR",
|
Self::LESS => "LESS",
|
||||||
Self::SUBTRACT_INT => "SUBTRACT_INT",
|
Self::LESS_EQUAL => "LESS_EQUAL",
|
||||||
Self::SUBTRACT_FLOAT => "SUBTRACT_FLOAT",
|
Self::NEGATE => "NEGATE",
|
||||||
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::NOT => "NOT",
|
||||||
Self::TEST => "TEST",
|
Self::TEST => "TEST",
|
||||||
Self::TEST_SET => "TEST_SET",
|
Self::TEST_SET => "TEST_SET",
|
||||||
@ -153,57 +81,30 @@ impl Operation {
|
|||||||
Self::CALL_NATIVE => "CALL_NATIVE",
|
Self::CALL_NATIVE => "CALL_NATIVE",
|
||||||
Self::JUMP => "JUMP",
|
Self::JUMP => "JUMP",
|
||||||
Self::RETURN => "RETURN",
|
Self::RETURN => "RETURN",
|
||||||
_ => Self::panic_from_unknown_code(self.0),
|
_ => self.panic_from_unknown_code(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_math(self) -> bool {
|
pub fn is_math(self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
Operation::ADD_INT
|
Operation::ADD
|
||||||
| Operation::ADD_FLOAT
|
| Operation::SUBTRACT
|
||||||
| Operation::ADD_BYTE
|
| Operation::MULTIPLY
|
||||||
| Operation::SUBTRACT_INT
|
| Operation::DIVIDE
|
||||||
| Operation::SUBTRACT_FLOAT
|
| Operation::MODULO
|
||||||
| 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 {
|
pub fn is_comparison(self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
Operation::EQUAL_INT
|
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL
|
||||||
| 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(self) -> ! {
|
||||||
panic!("Unknown operation code: {code}");
|
panic!("Unknown operation code: {}", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -34,3 +36,18 @@ impl From<Return> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Return {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Return {
|
||||||
|
should_return_value,
|
||||||
|
return_register,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
if *should_return_value {
|
||||||
|
write!(f, "RETURN R{return_register}")
|
||||||
|
} else {
|
||||||
|
write!(f, "RETURN")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
69
dust-lang/src/instruction/subtract.rs
Normal file
69
dust-lang/src/instruction/subtract.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use super::{Instruction, InstructionBuilder, Operand, Operation, TypeCode};
|
||||||
|
|
||||||
|
pub struct Subtract {
|
||||||
|
pub destination: u16,
|
||||||
|
pub left: Operand,
|
||||||
|
pub left_type: TypeCode,
|
||||||
|
pub right: Operand,
|
||||||
|
pub right_type: TypeCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Instruction> for Subtract {
|
||||||
|
fn from(instruction: Instruction) -> Self {
|
||||||
|
let destination = instruction.a_field();
|
||||||
|
let (left, right) = instruction.b_and_c_as_operands();
|
||||||
|
let left_type = instruction.b_type();
|
||||||
|
let right_type = instruction.c_type();
|
||||||
|
|
||||||
|
Subtract {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Subtract> for Instruction {
|
||||||
|
fn from(subtract: Subtract) -> Self {
|
||||||
|
let operation = Operation::SUBTRACT;
|
||||||
|
let a_field = subtract.destination;
|
||||||
|
let (b_field, b_is_constant) = subtract.left.as_index_and_constant_flag();
|
||||||
|
let (c_field, c_is_constant) = subtract.right.as_index_and_constant_flag();
|
||||||
|
let b_type = subtract.left_type;
|
||||||
|
let c_type = subtract.right_type;
|
||||||
|
|
||||||
|
InstructionBuilder {
|
||||||
|
operation,
|
||||||
|
a_field,
|
||||||
|
b_field,
|
||||||
|
c_field,
|
||||||
|
b_is_constant,
|
||||||
|
c_is_constant,
|
||||||
|
b_type,
|
||||||
|
c_type,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Subtract {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Subtract {
|
||||||
|
destination,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"R{destination} = {left_type}({left}) - {right_type}({right})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operation};
|
use crate::{Instruction, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -33,3 +35,15 @@ impl From<Test> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Test {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let Test {
|
||||||
|
operand_register,
|
||||||
|
test_value,
|
||||||
|
} = self;
|
||||||
|
let bang = if *test_value { "" } else { "!" };
|
||||||
|
|
||||||
|
write!(f, "if {bang}R{operand_register} {{ JUMP +1 }}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{Instruction, Operand, Operation};
|
use crate::{Instruction, Operand, Operation};
|
||||||
|
|
||||||
use super::InstructionBuilder;
|
use super::InstructionBuilder;
|
||||||
@ -40,3 +42,19 @@ impl From<TestSet> for Instruction {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for TestSet {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let TestSet {
|
||||||
|
destination,
|
||||||
|
argument,
|
||||||
|
test_value,
|
||||||
|
} = self;
|
||||||
|
let bang = if *test_value { "" } else { "!" };
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"if {bang}{argument} {{ JUMP +1 }} else {{ R{destination} = {argument} }}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
31
dust-lang/src/instruction/type_code.rs
Normal file
31
dust-lang/src/instruction/type_code.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct TypeCode(pub u8);
|
||||||
|
|
||||||
|
impl TypeCode {
|
||||||
|
pub const BOOLEAN: TypeCode = TypeCode(0);
|
||||||
|
pub const BYTE: TypeCode = TypeCode(1);
|
||||||
|
pub const CHARACTER: TypeCode = TypeCode(2);
|
||||||
|
pub const FLOAT: TypeCode = TypeCode(3);
|
||||||
|
pub const INTEGER: TypeCode = TypeCode(4);
|
||||||
|
pub const STRING: TypeCode = TypeCode(5);
|
||||||
|
|
||||||
|
pub fn panic_from_unknown_code(self) -> ! {
|
||||||
|
panic!("Unknown type code: {}", self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TypeCode {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match *self {
|
||||||
|
TypeCode::BOOLEAN => write!(f, "bool"),
|
||||||
|
TypeCode::BYTE => write!(f, "byte"),
|
||||||
|
TypeCode::CHARACTER => write!(f, "char"),
|
||||||
|
TypeCode::FLOAT => write!(f, "float"),
|
||||||
|
TypeCode::INTEGER => write!(f, "int"),
|
||||||
|
TypeCode::STRING => write!(f, "str"),
|
||||||
|
_ => self.panic_from_unknown_code(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -58,6 +58,30 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_byte(&self) -> Option<u8> {
|
||||||
|
if let Value::Concrete(ConcreteValue::Byte(byte)) = self {
|
||||||
|
Some(*byte)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_character(&self) -> Option<char> {
|
||||||
|
if let Value::Concrete(ConcreteValue::Character(character)) = self {
|
||||||
|
Some(*character)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_float(&self) -> Option<f64> {
|
||||||
|
if let Value::Concrete(ConcreteValue::Float(float)) = self {
|
||||||
|
Some(*float)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_function(&self) -> Option<&Function> {
|
pub fn as_function(&self) -> Option<&Function> {
|
||||||
if let Value::Function(function) = self {
|
if let Value::Function(function) = self {
|
||||||
Some(function)
|
Some(function)
|
||||||
|
@ -3,8 +3,9 @@ use tracing::trace;
|
|||||||
use crate::{
|
use crate::{
|
||||||
AbstractList, ConcreteValue, Instruction, Operand, Type, Value,
|
AbstractList, ConcreteValue, Instruction, Operand, Type, Value,
|
||||||
instruction::{
|
instruction::{
|
||||||
Call, CallNative, Close, GetLocal, Jump, LoadBoolean, LoadConstant, LoadFunction, LoadList,
|
Add, Call, CallNative, Close, Divide, Equal, GetLocal, Jump, Less, LessEqual, LoadBoolean,
|
||||||
LoadSelf, Not, Point, Return, SetLocal, Test, TestSet,
|
LoadConstant, LoadFunction, LoadList, LoadSelf, Modulo, Multiply, Negate, Not, Point,
|
||||||
|
Return, SetLocal, Subtract, Test, TestSet, TypeCode,
|
||||||
},
|
},
|
||||||
vm::FunctionCall,
|
vm::FunctionCall,
|
||||||
};
|
};
|
||||||
@ -252,12 +253,42 @@ pub fn add(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Add {
|
let Add {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let sum = match (left_type, right_type) {
|
||||||
let right = data.get_argument_unchecked(right);
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
let sum = left.add(right);
|
let left = unsafe {
|
||||||
let register = Register::Value(sum);
|
data.get_argument_unchecked(left)
|
||||||
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Integer(left + right)
|
||||||
|
}
|
||||||
|
(TypeCode::FLOAT, TypeCode::FLOAT) => {
|
||||||
|
let left = unsafe {
|
||||||
|
data.get_argument_unchecked(left)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Float(left + right)
|
||||||
|
}
|
||||||
|
_ => panic!("VM Error: Cannot add values"),
|
||||||
|
};
|
||||||
|
let register = Register::Value(Value::Concrete(sum));
|
||||||
|
|
||||||
data.set_register(destination, register);
|
data.set_register(destination, register);
|
||||||
|
|
||||||
@ -270,12 +301,42 @@ pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Subtract {
|
let Subtract {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let difference = match (left_type, right_type) {
|
||||||
let right = data.get_argument_unchecked(right);
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
let difference = left.subtract(right);
|
let left = unsafe {
|
||||||
let register = Register::Value(difference);
|
data.get_argument_unchecked(left)
|
||||||
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Integer(left - right)
|
||||||
|
}
|
||||||
|
(TypeCode::FLOAT, TypeCode::FLOAT) => {
|
||||||
|
let left = unsafe {
|
||||||
|
data.get_argument_unchecked(left)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Float(left - right)
|
||||||
|
}
|
||||||
|
_ => panic!("VM Error: Cannot subtract values"),
|
||||||
|
};
|
||||||
|
let register = Register::Value(Value::Concrete(difference));
|
||||||
|
|
||||||
data.set_register(destination, register);
|
data.set_register(destination, register);
|
||||||
|
|
||||||
@ -288,20 +349,42 @@ pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Multiply {
|
let Multiply {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let product = match (left_type, right_type) {
|
||||||
let right = data.get_argument_unchecked(right);
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
let product = match (left, right) {
|
let left = unsafe {
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
|
data.get_argument_unchecked(left)
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
.as_integer()
|
||||||
ConcreteValue::Integer(left * right).to_value()
|
.unwrap_unchecked()
|
||||||
}
|
};
|
||||||
_ => panic!("Value Error: Cannot multiply values"),
|
let right = unsafe {
|
||||||
},
|
data.get_argument_unchecked(right)
|
||||||
_ => panic!("Value Error: Cannot multiply values"),
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Integer(left * right)
|
||||||
|
}
|
||||||
|
(TypeCode::FLOAT, TypeCode::FLOAT) => {
|
||||||
|
let left = unsafe {
|
||||||
|
data.get_argument_unchecked(left)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Float(left * right)
|
||||||
|
}
|
||||||
|
_ => panic!("VM Error: Cannot multiply values"),
|
||||||
};
|
};
|
||||||
let register = Register::Value(product);
|
let register = Register::Value(Value::Concrete(product));
|
||||||
|
|
||||||
data.set_register(destination, register);
|
data.set_register(destination, register);
|
||||||
|
|
||||||
@ -314,20 +397,42 @@ pub fn divide(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Divide {
|
let Divide {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let quotient = match (left_type, right_type) {
|
||||||
let right = data.get_argument_unchecked(right);
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
let quotient = match (left, right) {
|
let left = unsafe {
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
|
data.get_argument_unchecked(left)
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
.as_integer()
|
||||||
ConcreteValue::Integer(left / right).to_value()
|
.unwrap_unchecked()
|
||||||
}
|
};
|
||||||
_ => panic!("Value Error: Cannot divide values"),
|
let right = unsafe {
|
||||||
},
|
data.get_argument_unchecked(right)
|
||||||
_ => panic!("Value Error: Cannot divide values"),
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Integer(left / right)
|
||||||
|
}
|
||||||
|
(TypeCode::FLOAT, TypeCode::FLOAT) => {
|
||||||
|
let left = unsafe {
|
||||||
|
data.get_argument_unchecked(left)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
let right = unsafe {
|
||||||
|
data.get_argument_unchecked(right)
|
||||||
|
.as_float()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Float(left / right)
|
||||||
|
}
|
||||||
|
_ => panic!("VM Error: Cannot divide values"),
|
||||||
};
|
};
|
||||||
let register = Register::Value(quotient);
|
let register = Register::Value(Value::Concrete(quotient));
|
||||||
|
|
||||||
data.set_register(destination, register);
|
data.set_register(destination, register);
|
||||||
|
|
||||||
@ -340,20 +445,28 @@ pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Modulo {
|
let Modulo {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
|
left_type,
|
||||||
right,
|
right,
|
||||||
|
right_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let remainder = match (left_type, right_type) {
|
||||||
let right = data.get_argument_unchecked(right);
|
(TypeCode::INTEGER, TypeCode::INTEGER) => {
|
||||||
let remainder = match (left, right) {
|
let left = unsafe {
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
|
data.get_argument_unchecked(left)
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
.as_integer()
|
||||||
ConcreteValue::Integer(left % right).to_value()
|
.unwrap_unchecked()
|
||||||
}
|
};
|
||||||
_ => panic!("Value Error: Cannot modulo values"),
|
let right = unsafe {
|
||||||
},
|
data.get_argument_unchecked(right)
|
||||||
_ => panic!("Value Error: Cannot modulo values"),
|
.as_integer()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
ConcreteValue::Integer(left % right)
|
||||||
|
}
|
||||||
|
_ => panic!("VM Error: Cannot modulo values"),
|
||||||
};
|
};
|
||||||
let register = Register::Value(remainder);
|
let register = Register::Value(Value::Concrete(remainder));
|
||||||
|
|
||||||
data.set_register(destination, register);
|
data.set_register(destination, register);
|
||||||
|
|
||||||
@ -415,12 +528,18 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
||||||
let Equal { value, left, right } = instruction.into();
|
let Equal {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let left = data.get_argument_unchecked(left);
|
||||||
let right = data.get_argument_unchecked(right);
|
let right = data.get_argument_unchecked(right);
|
||||||
let is_equal = left.equals(right);
|
let is_equal = left.equals(right);
|
||||||
|
|
||||||
if is_equal == value {
|
if is_equal == comparator {
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
let current_call = data.call_stack.last_mut_unchecked();
|
||||||
|
|
||||||
current_call.ip += 1;
|
current_call.ip += 1;
|
||||||
@ -432,12 +551,18 @@ pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
|
||||||
let Less { value, left, right } = instruction.into();
|
let Less {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let left = data.get_argument_unchecked(left);
|
||||||
let right = data.get_argument_unchecked(right);
|
let right = data.get_argument_unchecked(right);
|
||||||
let is_less = left < right;
|
let is_less = left < right;
|
||||||
|
|
||||||
if is_less == value {
|
if is_less == comparator {
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
let current_call = data.call_stack.last_mut_unchecked();
|
||||||
|
|
||||||
current_call.ip += 1;
|
current_call.ip += 1;
|
||||||
@ -449,12 +574,18 @@ pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
||||||
let LessEqual { value, left, right } = instruction.into();
|
let LessEqual {
|
||||||
|
comparator,
|
||||||
|
left,
|
||||||
|
left_type,
|
||||||
|
right,
|
||||||
|
right_type,
|
||||||
|
} = instruction.into();
|
||||||
let left = data.get_argument_unchecked(left);
|
let left = data.get_argument_unchecked(left);
|
||||||
let right = data.get_argument_unchecked(right);
|
let right = data.get_argument_unchecked(right);
|
||||||
let is_less_or_equal = left <= right;
|
let is_less_or_equal = left <= right;
|
||||||
|
|
||||||
if is_less_or_equal == value {
|
if is_less_or_equal == comparator {
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
let current_call = data.call_stack.last_mut_unchecked();
|
||||||
|
|
||||||
current_call.ip += 1;
|
current_call.ip += 1;
|
||||||
@ -469,6 +600,7 @@ pub fn negate(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
let Negate {
|
let Negate {
|
||||||
destination,
|
destination,
|
||||||
argument,
|
argument,
|
||||||
|
argument_type,
|
||||||
} = instruction.into();
|
} = instruction.into();
|
||||||
let argument = data.get_argument_unchecked(argument);
|
let argument = data.get_argument_unchecked(argument);
|
||||||
let negated = argument.negate();
|
let negated = argument.negate();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user