Use Operand type to store instruction argument types
This commit is contained in:
parent
b90adcb9f0
commit
25b4230aa4
@ -785,7 +785,7 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
let (previous_instruction, previous_type, previous_position) =
|
||||
self.instructions.pop().unwrap();
|
||||
let (argument, push_back) = self.handle_binary_argument(&previous_instruction)?;
|
||||
let (argument, push_back) = self.handle_binary_argument(&previous_instruction);
|
||||
|
||||
if push_back {
|
||||
self.instructions.push((
|
||||
@ -832,48 +832,10 @@ impl<'src> Compiler<'src> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_binary_argument(
|
||||
&mut self,
|
||||
instruction: &Instruction,
|
||||
) -> Result<(Operand, bool), CompileError> {
|
||||
let (argument, push_back) = match instruction.operation() {
|
||||
Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false),
|
||||
Operation::POINT => (instruction.b_as_operand(), false),
|
||||
Operation::LOAD_ENCODED
|
||||
| Operation::LOAD_LIST
|
||||
| Operation::LOAD_SELF
|
||||
| Operation::ADD
|
||||
| Operation::SUBTRACT
|
||||
| Operation::MULTIPLY
|
||||
| Operation::DIVIDE
|
||||
| Operation::MODULO
|
||||
| Operation::EQUAL
|
||||
| Operation::LESS
|
||||
| Operation::LESS_EQUAL
|
||||
| Operation::NEGATE
|
||||
| Operation::NOT
|
||||
| Operation::CALL => (Operand::Register(instruction.a_field()), true),
|
||||
Operation::CALL_NATIVE => {
|
||||
let function = NativeFunction::from(instruction.b_field());
|
||||
fn handle_binary_argument(&mut self, instruction: &Instruction) -> (Operand, bool) {
|
||||
let (argument, push_back) = (instruction.as_operand(), !instruction.yields_value());
|
||||
|
||||
if function.returns_value() {
|
||||
(Operand::Register(instruction.a_field()), true)
|
||||
} else {
|
||||
return Err(CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Ok((argument, push_back))
|
||||
(argument, push_back)
|
||||
}
|
||||
|
||||
fn parse_math_binary(&mut self) -> Result<(), CompileError> {
|
||||
@ -884,7 +846,7 @@ impl<'src> Compiler<'src> {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
|
||||
let left_is_mutable_local = if left_instruction.operation() == Operation::POINT {
|
||||
let Point { to, .. } = Point::from(left_instruction);
|
||||
|
||||
@ -915,13 +877,13 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
check_math_type(&left_type, operator, &left_position)?;
|
||||
|
||||
let (left_type_code, destination) = match left_type {
|
||||
Type::Boolean => (TypeCode::BOOLEAN, self.next_boolean_register()),
|
||||
Type::Byte => (TypeCode::BYTE, self.next_byte_register()),
|
||||
Type::Character => (TypeCode::CHARACTER, self.next_character_register()),
|
||||
Type::Float => (TypeCode::FLOAT, self.next_float_register()),
|
||||
Type::Integer => (TypeCode::INTEGER, self.next_integer_register()),
|
||||
Type::String => (TypeCode::STRING, self.next_string_register()),
|
||||
let destination = match left_type {
|
||||
Type::Boolean => self.next_boolean_register(),
|
||||
Type::Byte => self.next_byte_register(),
|
||||
Type::Character => self.next_character_register(),
|
||||
Type::Float => self.next_float_register(),
|
||||
Type::Integer => self.next_integer_register(),
|
||||
Type::String => self.next_string_register(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -936,7 +898,7 @@ impl<'src> Compiler<'src> {
|
||||
self.parse_sub_expression(&rule.precedence)?;
|
||||
|
||||
let (right_instruction, right_type, right_position) = self.instructions.pop().unwrap();
|
||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?;
|
||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction);
|
||||
|
||||
check_math_type(&right_type, operator, &right_position)?;
|
||||
check_math_types(
|
||||
@ -947,16 +909,6 @@ impl<'src> Compiler<'src> {
|
||||
&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 {
|
||||
self.instructions
|
||||
.push((right_instruction, right_type, right_position));
|
||||
@ -970,21 +922,11 @@ impl<'src> Compiler<'src> {
|
||||
left_type.clone()
|
||||
};
|
||||
let instruction = match operator {
|
||||
Token::Plus | Token::PlusEqual => {
|
||||
Instruction::add(destination, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Minus | Token::MinusEqual => {
|
||||
Instruction::subtract(destination, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Star | Token::StarEqual => {
|
||||
Instruction::multiply(destination, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Slash | Token::SlashEqual => {
|
||||
Instruction::divide(destination, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Percent | Token::PercentEqual => {
|
||||
Instruction::modulo(destination, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Plus | Token::PlusEqual => Instruction::add(destination, left, right),
|
||||
Token::Minus | Token::MinusEqual => Instruction::subtract(destination, left, right),
|
||||
Token::Star | Token::StarEqual => Instruction::multiply(destination, left, right),
|
||||
Token::Slash | Token::SlashEqual => Instruction::divide(destination, left, right),
|
||||
Token::Percent | Token::PercentEqual => Instruction::modulo(destination, left, right),
|
||||
_ => {
|
||||
return Err(CompileError::ExpectedTokenMultiple {
|
||||
expected: &[
|
||||
@ -1031,23 +973,13 @@ impl<'src> Compiler<'src> {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
|
||||
let operator = self.current_token;
|
||||
let operator_position = self.current_position;
|
||||
let rule = ParseRule::from(&operator);
|
||||
|
||||
// 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 {
|
||||
self.instructions
|
||||
.push((left_instruction, left_type, left_position));
|
||||
@ -1063,21 +995,11 @@ impl<'src> Compiler<'src> {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
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 {
|
||||
self.instructions
|
||||
.push((right_instruction, right_type, right_position));
|
||||
@ -1085,22 +1007,12 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
let destination = self.next_boolean_register();
|
||||
let comparison = match operator {
|
||||
Token::DoubleEqual => {
|
||||
Instruction::equal(true, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::BangEqual => {
|
||||
Instruction::equal(false, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Less => Instruction::less(true, left, left_type_code, right, right_type_code),
|
||||
Token::LessEqual => {
|
||||
Instruction::less_equal(true, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::Greater => {
|
||||
Instruction::less_equal(false, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::GreaterEqual => {
|
||||
Instruction::less(false, left, left_type_code, right, right_type_code)
|
||||
}
|
||||
Token::DoubleEqual => Instruction::equal(true, left, right),
|
||||
Token::BangEqual => Instruction::equal(false, left, right),
|
||||
Token::Less => Instruction::less(true, left, right),
|
||||
Token::LessEqual => Instruction::less_equal(true, left, right),
|
||||
Token::Greater => Instruction::less_equal(false, left, right),
|
||||
Token::GreaterEqual => Instruction::less(false, left, right),
|
||||
_ => {
|
||||
return Err(CompileError::ExpectedTokenMultiple {
|
||||
expected: &[
|
||||
@ -1289,8 +1201,7 @@ impl<'src> Compiler<'src> {
|
||||
};
|
||||
let point = Instruction::point(
|
||||
local_register_index,
|
||||
Operand::Register(register),
|
||||
r#type.type_code(),
|
||||
Operand::Register(register, r#type.type_code()),
|
||||
);
|
||||
|
||||
self.emit_instruction(point, r#type, start_position);
|
||||
@ -1310,8 +1221,7 @@ impl<'src> Compiler<'src> {
|
||||
};
|
||||
let point = Instruction::point(
|
||||
destination,
|
||||
Operand::Register(local_register_index),
|
||||
r#type.type_code(),
|
||||
Operand::Register(local_register_index, r#type.type_code()),
|
||||
);
|
||||
|
||||
self.emit_instruction(point, r#type, self.previous_position);
|
||||
@ -1704,14 +1614,10 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
fn parse_implicit_return(&mut self) -> Result<(), CompileError> {
|
||||
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
|
||||
let Point {
|
||||
destination,
|
||||
r#type: type_code,
|
||||
..
|
||||
} = Point::from(self.instructions.last().unwrap().0);
|
||||
let Point { destination, to } = Point::from(self.instructions.last().unwrap().0);
|
||||
|
||||
let (_, r#type, _) = self.instructions.pop().unwrap();
|
||||
let r#return = Instruction::r#return(true, destination, type_code);
|
||||
let r#return = Instruction::r#return(true, destination, to.as_type());
|
||||
|
||||
self.emit_instruction(r#return, r#type, self.current_position);
|
||||
} else if matches!(self.get_last_operation(), Some(Operation::RETURN))
|
||||
|
@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Add> for Instruction {
|
||||
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;
|
||||
let b_type = add.left.as_type();
|
||||
let c_type = add.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,15 +50,13 @@ impl Display for Add {
|
||||
let Add {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
|
||||
match *left_type {
|
||||
match left.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?,
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?,
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?,
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{destination}")?,
|
||||
TypeCode::STRING => write!(f, "R_STR_{destination}")?,
|
||||
|
@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Divide> for Instruction {
|
||||
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;
|
||||
let b_type = divide.left.as_type();
|
||||
let c_type = divide.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,11 +50,19 @@ impl Display for Divide {
|
||||
let Divide {
|
||||
destination,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
|
||||
write!(f, "R{destination} = {left} ÷ {right}",)
|
||||
match left.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?,
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?,
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?,
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{destination}")?,
|
||||
TypeCode::STRING => write!(f, "R_STR_{destination}")?,
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
write!(f, " = {left} ÷ {right}",)
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,22 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use super::{Instruction, InstructionFields, Operand, Operation, TypeCode};
|
||||
use super::{Instruction, InstructionFields, Operand, Operation};
|
||||
|
||||
pub struct Equal {
|
||||
pub comparator: bool,
|
||||
pub left: Operand,
|
||||
pub left_type: TypeCode,
|
||||
pub right: Operand,
|
||||
pub right_type: TypeCode,
|
||||
}
|
||||
|
||||
impl From<Instruction> for Equal {
|
||||
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();
|
||||
|
||||
Equal {
|
||||
comparator,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Equal> for Instruction {
|
||||
let (b_field, b_is_constant) = equal_bool.left.as_index_and_constant_flag();
|
||||
let (c_field, c_is_constant) = equal_bool.right.as_index_and_constant_flag();
|
||||
let d_field = equal_bool.comparator;
|
||||
let b_type = equal_bool.left_type;
|
||||
let c_type = equal_bool.right_type;
|
||||
let b_type = equal_bool.left.as_type();
|
||||
let c_type = equal_bool.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,9 +50,7 @@ impl Display for Equal {
|
||||
let Equal {
|
||||
comparator,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
let operator = if *comparator { "==" } else { "≠" };
|
||||
|
||||
|
@ -1,28 +1,22 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use super::{Instruction, InstructionFields, Operand, Operation, TypeCode};
|
||||
use super::{Instruction, InstructionFields, Operand, Operation};
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Less> for Instruction {
|
||||
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;
|
||||
let b_type = less.left.as_type();
|
||||
let c_type = less.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,9 +50,7 @@ impl Display for Less {
|
||||
let Less {
|
||||
comparator,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
let operator = if *comparator { "<" } else { "≥" };
|
||||
|
||||
|
@ -1,28 +1,22 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use super::{Instruction, InstructionFields, Operand, Operation, TypeCode};
|
||||
use super::{Instruction, InstructionFields, Operand, Operation};
|
||||
|
||||
pub struct LessEqual {
|
||||
pub comparator: bool,
|
||||
pub left: Operand,
|
||||
pub left_type: TypeCode,
|
||||
pub right: Operand,
|
||||
pub right_type: TypeCode,
|
||||
}
|
||||
|
||||
impl From<Instruction> for LessEqual {
|
||||
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();
|
||||
|
||||
LessEqual {
|
||||
comparator,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<LessEqual> for Instruction {
|
||||
let (b_field, b_is_constant) = less_equal_byte.left.as_index_and_constant_flag();
|
||||
let (c_field, c_is_constant) = less_equal_byte.right.as_index_and_constant_flag();
|
||||
let d_field = less_equal_byte.comparator;
|
||||
let b_type = less_equal_byte.left_type;
|
||||
let c_type = less_equal_byte.right_type;
|
||||
let b_type = less_equal_byte.left.as_type();
|
||||
let c_type = less_equal_byte.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,9 +50,7 @@ impl Display for LessEqual {
|
||||
let LessEqual {
|
||||
comparator,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
let operator = if *comparator { "≤" } else { ">" };
|
||||
|
||||
|
@ -278,12 +278,52 @@ impl Instruction {
|
||||
*self = fields.build();
|
||||
}
|
||||
|
||||
pub fn point(destination: u16, to: Operand, r#type: TypeCode) -> Instruction {
|
||||
Instruction::from(Point {
|
||||
destination,
|
||||
to,
|
||||
r#type,
|
||||
})
|
||||
pub fn as_operand(&self) -> Operand {
|
||||
match self.operation() {
|
||||
Operation::POINT => {
|
||||
let Point { destination, to } = Point::from(*self);
|
||||
|
||||
Operand::Register(destination, to.as_type())
|
||||
}
|
||||
Operation::LOAD_ENCODED => {
|
||||
let LoadEncoded {
|
||||
destination,
|
||||
value_type,
|
||||
..
|
||||
} = LoadEncoded::from(*self);
|
||||
|
||||
Operand::Register(destination, value_type)
|
||||
}
|
||||
Operation::LOAD_CONSTANT => {
|
||||
let LoadConstant {
|
||||
constant_type,
|
||||
constant_index,
|
||||
..
|
||||
} = LoadConstant::from(*self);
|
||||
|
||||
Operand::Constant(constant_index, constant_type)
|
||||
}
|
||||
Operation::LOAD_LIST => {
|
||||
let LoadList { destination, .. } = LoadList::from(*self);
|
||||
|
||||
Operand::Register(destination, TypeCode::LIST)
|
||||
}
|
||||
Operation::LOAD_FUNCTION => {
|
||||
let LoadFunction { destination, .. } = LoadFunction::from(*self);
|
||||
|
||||
Operand::Register(destination, TypeCode::FUNCTION)
|
||||
}
|
||||
Operation::LOAD_SELF => {
|
||||
let LoadSelf { destination, .. } = LoadSelf::from(*self);
|
||||
|
||||
Operand::Register(destination, TypeCode::FUNCTION)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn point(destination: u16, to: Operand) -> Instruction {
|
||||
Instruction::from(Point { destination, to })
|
||||
}
|
||||
|
||||
pub fn close(from: u16, to: u16) -> Instruction {
|
||||
@ -341,131 +381,67 @@ impl Instruction {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add(
|
||||
destination: u16,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn add(destination: u16, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Add {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subtract(
|
||||
destination: u16,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn subtract(destination: u16, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Subtract {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn multiply(
|
||||
destination: u16,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn multiply(destination: u16, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Multiply {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn divide(
|
||||
destination: u16,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn divide(destination: u16, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Divide {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn modulo(
|
||||
destination: u16,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn modulo(destination: u16, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Modulo {
|
||||
destination,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn equal(
|
||||
comparator: bool,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn equal(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Equal {
|
||||
comparator,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn less(
|
||||
comparator: bool,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn less(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(Less {
|
||||
comparator,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn less_equal(
|
||||
comparator: bool,
|
||||
left: Operand,
|
||||
left_type: TypeCode,
|
||||
right: Operand,
|
||||
right_type: TypeCode,
|
||||
) -> Instruction {
|
||||
pub fn less_equal(comparator: bool, left: Operand, right: Operand) -> Instruction {
|
||||
Instruction::from(LessEqual {
|
||||
comparator,
|
||||
left,
|
||||
left_type,
|
||||
right,
|
||||
right_type,
|
||||
})
|
||||
}
|
||||
|
||||
@ -552,55 +528,20 @@ impl Instruction {
|
||||
self.operation().is_comparison()
|
||||
}
|
||||
|
||||
pub fn as_argument(&self) -> Option<Operand> {
|
||||
match self.operation() {
|
||||
Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())),
|
||||
Operation::POINT
|
||||
| Operation::LOAD_ENCODED
|
||||
| Operation::LOAD_LIST
|
||||
| Operation::LOAD_SELF
|
||||
| Operation::ADD
|
||||
| Operation::SUBTRACT
|
||||
| Operation::MULTIPLY
|
||||
| Operation::DIVIDE
|
||||
| Operation::MODULO
|
||||
| Operation::EQUAL
|
||||
| Operation::LESS
|
||||
| Operation::LESS_EQUAL
|
||||
| Operation::NEGATE
|
||||
| Operation::NOT
|
||||
| Operation::CALL => Some(Operand::Register(self.a_field())),
|
||||
Operation::CALL_NATIVE => {
|
||||
let function = NativeFunction::from(self.b_field());
|
||||
|
||||
if function.returns_value() {
|
||||
Some(Operand::Register(self.a_field()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn b_as_operand(&self) -> Operand {
|
||||
if self.b_is_constant() {
|
||||
Operand::Constant(self.b_field())
|
||||
Operand::Constant(self.b_field(), self.b_type())
|
||||
} else {
|
||||
Operand::Register(self.b_field())
|
||||
Operand::Register(self.b_field(), self.b_type())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn b_and_c_as_operands(&self) -> (Operand, Operand) {
|
||||
let left = if self.b_is_constant() {
|
||||
Operand::Constant(self.b_field())
|
||||
} else {
|
||||
Operand::Register(self.b_field())
|
||||
};
|
||||
let left = self.b_as_operand();
|
||||
let right = if self.c_is_constant() {
|
||||
Operand::Constant(self.c_field())
|
||||
Operand::Constant(self.c_field(), self.c_type())
|
||||
} else {
|
||||
Operand::Register(self.c_field())
|
||||
Operand::Register(self.c_field(), self.c_type())
|
||||
};
|
||||
|
||||
(left, right)
|
||||
@ -684,30 +625,37 @@ impl Display for Instruction {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Operand {
|
||||
Constant(u16),
|
||||
Register(u16),
|
||||
Constant(u16, TypeCode),
|
||||
Register(u16, TypeCode),
|
||||
}
|
||||
|
||||
impl Operand {
|
||||
pub fn index(&self) -> u16 {
|
||||
match self {
|
||||
Operand::Constant(index) => *index,
|
||||
Operand::Register(index) => *index,
|
||||
Operand::Constant(index, _) => *index,
|
||||
Operand::Register(index, _) => *index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_constant(&self) -> bool {
|
||||
matches!(self, Operand::Constant(_))
|
||||
matches!(self, Operand::Constant(_, _))
|
||||
}
|
||||
|
||||
pub fn is_register(&self) -> bool {
|
||||
matches!(self, Operand::Register(_))
|
||||
matches!(self, Operand::Register(_, _))
|
||||
}
|
||||
|
||||
pub fn as_index_and_constant_flag(&self) -> (u16, bool) {
|
||||
match self {
|
||||
Operand::Constant(index) => (*index, true),
|
||||
Operand::Register(index) => (*index, false),
|
||||
Operand::Constant(index, _) => (*index, true),
|
||||
Operand::Register(index, _) => (*index, false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_type(&self) -> TypeCode {
|
||||
match self {
|
||||
Operand::Constant(_, r#type) => *r#type,
|
||||
Operand::Register(_, r#type) => *r#type,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -715,8 +663,26 @@ impl Operand {
|
||||
impl Display for Operand {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Operand::Constant(index) => write!(f, "{index}"),
|
||||
Operand::Register(index) => write!(f, "{index}"),
|
||||
Operand::Constant(index, r#type) => match *r#type {
|
||||
TypeCode::BOOLEAN => write!(f, "C_{}", index),
|
||||
TypeCode::CHARACTER => write!(f, "C_{}", index),
|
||||
TypeCode::INTEGER => write!(f, "C_{}", index),
|
||||
TypeCode::FLOAT => write!(f, "C_{}", index),
|
||||
TypeCode::STRING => write!(f, "C_{}", index),
|
||||
TypeCode::LIST => write!(f, "C_{}", index),
|
||||
TypeCode::FUNCTION => write!(f, "C_{}", index),
|
||||
_ => panic!("Unknown type code: {}", r#type.0),
|
||||
},
|
||||
Operand::Register(index, r#type) => match *r#type {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{}", index),
|
||||
TypeCode::CHARACTER => write!(f, "R_CHAR_{}", index),
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{}", index),
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{}", index),
|
||||
TypeCode::STRING => write!(f, "R_STR_{}", index),
|
||||
TypeCode::LIST => write!(f, "R_LIST_{}", index),
|
||||
TypeCode::FUNCTION => write!(f, "R_FN_{}", index),
|
||||
_ => panic!("Unknown type code: {}", r#type.0),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -729,10 +695,8 @@ mod tests {
|
||||
fn decode_operation() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(instruction.operation(), Operation::ADD);
|
||||
@ -742,10 +706,8 @@ mod tests {
|
||||
fn decode_a_field() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(42, instruction.a_field());
|
||||
@ -755,10 +717,8 @@ mod tests {
|
||||
fn decode_b_field() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(4, instruction.b_field());
|
||||
@ -768,10 +728,8 @@ mod tests {
|
||||
fn decode_c_field() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(2, instruction.c_field());
|
||||
@ -781,10 +739,8 @@ mod tests {
|
||||
fn decode_d_field() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert!(!instruction.d_field());
|
||||
@ -794,10 +750,8 @@ mod tests {
|
||||
fn decode_b_is_constant() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert!(instruction.b_is_constant());
|
||||
@ -807,10 +761,8 @@ mod tests {
|
||||
fn decode_c_is_constant() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Register(2),
|
||||
TypeCode::STRING,
|
||||
Operand::Constant(4),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Register(2, TypeCode::STRING),
|
||||
Operand::Constant(4, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert!(instruction.c_is_constant());
|
||||
@ -820,10 +772,8 @@ mod tests {
|
||||
fn decode_b_type() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(TypeCode::STRING, instruction.b_type());
|
||||
@ -833,10 +783,8 @@ mod tests {
|
||||
fn decode_c_type() {
|
||||
let instruction = Instruction::add(
|
||||
42,
|
||||
Operand::Constant(4),
|
||||
TypeCode::STRING,
|
||||
Operand::Register(2),
|
||||
TypeCode::CHARACTER,
|
||||
Operand::Constant(4, TypeCode::STRING),
|
||||
Operand::Register(2, TypeCode::CHARACTER),
|
||||
);
|
||||
|
||||
assert_eq!(TypeCode::CHARACTER, instruction.c_type());
|
||||
|
@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Modulo> for Instruction {
|
||||
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;
|
||||
let b_type = modulo.left.as_type();
|
||||
let c_type = modulo.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,11 +50,19 @@ impl Display for Modulo {
|
||||
let Modulo {
|
||||
destination,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
|
||||
write!(f, "R{destination} = {left} % {right}",)
|
||||
match left.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?,
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?,
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?,
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{destination}")?,
|
||||
TypeCode::STRING => write!(f, "R_STR_{destination}")?,
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
write!(f, " = {left} % {right}",)
|
||||
}
|
||||
}
|
||||
|
@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Multiply> for Instruction {
|
||||
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;
|
||||
let b_type = multiply.left.as_type();
|
||||
let c_type = multiply.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,11 +50,19 @@ impl Display for Multiply {
|
||||
let Multiply {
|
||||
destination,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
|
||||
write!(f, "R{destination} = {left} ✕ {right}",)
|
||||
match left.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?,
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?,
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?,
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{destination}")?,
|
||||
TypeCode::STRING => write!(f, "R_STR_{destination}")?,
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
write!(f, " = {left} ✕ {right}",)
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ use super::{InstructionFields, Operand, TypeCode};
|
||||
pub struct Point {
|
||||
pub destination: u16,
|
||||
pub to: Operand,
|
||||
pub r#type: TypeCode,
|
||||
}
|
||||
|
||||
impl From<Instruction> for Point {
|
||||
@ -15,7 +14,6 @@ impl From<Instruction> for Point {
|
||||
Point {
|
||||
destination: instruction.a_field(),
|
||||
to: instruction.b_as_operand(),
|
||||
r#type: instruction.b_type(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,7 +23,7 @@ impl From<Point> for Instruction {
|
||||
let operation = Operation::POINT;
|
||||
let a_field = r#move.destination;
|
||||
let (b_field, b_is_constant) = r#move.to.as_index_and_constant_flag();
|
||||
let b_type = r#move.r#type;
|
||||
let b_type = r#move.to.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -41,13 +39,9 @@ impl From<Point> for Instruction {
|
||||
|
||||
impl Display for Point {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let Point {
|
||||
destination,
|
||||
to,
|
||||
r#type,
|
||||
} = self;
|
||||
let Point { destination, to } = self;
|
||||
|
||||
match *r#type {
|
||||
match to.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> R_BOOL_{to}"),
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> R_BYTE_{to}"),
|
||||
TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> R_CHAR_{to}"),
|
||||
|
@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,8 +27,8 @@ impl From<Subtract> for Instruction {
|
||||
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;
|
||||
let b_type = subtract.left.as_type();
|
||||
let c_type = subtract.right.as_type();
|
||||
|
||||
InstructionFields {
|
||||
operation,
|
||||
@ -56,11 +50,19 @@ impl Display for Subtract {
|
||||
let Subtract {
|
||||
destination,
|
||||
left,
|
||||
left_type: _,
|
||||
right,
|
||||
right_type: _,
|
||||
} = self;
|
||||
|
||||
write!(f, "R{destination} = {left} - {right}",)
|
||||
match left.as_type() {
|
||||
TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?,
|
||||
TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?,
|
||||
TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?,
|
||||
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?,
|
||||
TypeCode::INTEGER => write!(f, "R_INT_{destination}")?,
|
||||
TypeCode::STRING => write!(f, "R_STR_{destination}")?,
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
write!(f, " = {left} - {right}",)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct TypeCode(pub u8);
|
||||
|
||||
impl TypeCode {
|
||||
@ -11,6 +11,8 @@ impl TypeCode {
|
||||
pub const FLOAT: TypeCode = TypeCode(4);
|
||||
pub const INTEGER: TypeCode = TypeCode(5);
|
||||
pub const STRING: TypeCode = TypeCode(6);
|
||||
pub const LIST: TypeCode = TypeCode(7);
|
||||
pub const FUNCTION: TypeCode = TypeCode(8);
|
||||
|
||||
pub fn panic_from_unknown_code(self) -> ! {
|
||||
panic!("Unknown type code: {}", self.0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user