1
0

Convert LoadBoolean to LoadEncoded; Fix register handling

This commit is contained in:
Jeff 2025-02-06 13:10:11 -05:00
parent 6f0955c29a
commit bd273035aa
10 changed files with 124 additions and 98 deletions

View File

@ -629,11 +629,12 @@ impl<'src> Compiler<'src> {
if let Token::Boolean(text) = self.current_token {
self.advance()?;
let boolean = text.parse::<bool>().unwrap();
let boolean = text.parse::<bool>().unwrap() as u16;
let destination = self.next_boolean_register();
let load_boolean = Instruction::load_boolean(destination, boolean, false);
let load_encoded =
Instruction::load_encoded(destination, boolean, TypeCode::BOOLEAN, false);
self.emit_instruction(load_boolean, Type::Boolean, position);
self.emit_instruction(load_encoded, Type::Boolean, position);
Ok(())
} else {
@ -652,10 +653,12 @@ impl<'src> Compiler<'src> {
self.advance()?;
let byte = u8::from_str_radix(&text[2..], 16)
.map_err(|error| CompileError::ParseIntError { error, position })?;
let value = ConcreteValue::Byte(byte);
.map_err(|error| CompileError::ParseIntError { error, position })?
as u16;
let destination = self.next_byte_register();
let load_encoded = Instruction::load_encoded(destination, byte, TypeCode::BYTE, false);
self.emit_constant(value, position)?;
self.emit_instruction(load_encoded, Type::Byte, position);
Ok(())
} else {
@ -836,7 +839,7 @@ impl<'src> Compiler<'src> {
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_BOOLEAN
Operation::LOAD_ENCODED
| Operation::LOAD_LIST
| Operation::LOAD_SELF
| Operation::ADD
@ -1114,8 +1117,10 @@ impl<'src> Compiler<'src> {
}
};
let jump = Instruction::jump(1, true);
let load_true = Instruction::load_boolean(destination, true, true);
let load_false = Instruction::load_boolean(destination, false, false);
let load_true =
Instruction::load_encoded(destination, true as u16, TypeCode::BOOLEAN, true);
let load_false =
Instruction::load_encoded(destination, false as u16, TypeCode::BOOLEAN, false);
self.emit_instruction(comparison, Type::Boolean, operator_position);
self.emit_instruction(jump, Type::None, operator_position);
@ -1385,8 +1390,8 @@ impl<'src> Compiler<'src> {
Some([
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
Operation::JUMP,
Operation::LOAD_BOOLEAN,
Operation::LOAD_BOOLEAN
Operation::LOAD_ENCODED,
Operation::LOAD_ENCODED
]),
) {
self.instructions.pop();
@ -1456,7 +1461,7 @@ impl<'src> Compiler<'src> {
match else_block_distance {
0 => {}
1 => {
if let Some([Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT, _]) =
if let Some([Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT, _]) =
self.get_last_operations()
{
let loader_index = self.instructions.len() - 2;
@ -1491,7 +1496,7 @@ impl<'src> Compiler<'src> {
self.instructions
.insert(if_block_start, (jump, Type::None, if_block_start_position));
let if_block_last_instruction_index = self.instructions.len() - else_block_distance - 1;
let if_block_last_instruction_index = self.instructions.len() - else_block_distance;
let else_block_last_instruction_index = self.instructions.len() - 1;
let if_block_last_instruction = self.instructions[if_block_last_instruction_index].0;
@ -1500,8 +1505,6 @@ impl<'src> Compiler<'src> {
else_block_last_instruction.set_a_field(if_block_last_instruction.a_field());
println!("{if_block_last_instruction_index} {else_block_last_instruction_index}");
Ok(())
}
@ -1517,8 +1520,8 @@ impl<'src> Compiler<'src> {
Some([
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
Operation::JUMP,
Operation::LOAD_BOOLEAN,
Operation::LOAD_BOOLEAN
Operation::LOAD_ENCODED,
Operation::LOAD_ENCODED
]),
) {
self.instructions.pop();

View File

@ -1,57 +0,0 @@
use std::fmt::{self, Display, Formatter};
use crate::{Instruction, Operation};
use super::InstructionFields;
pub struct LoadBoolean {
pub destination: u16,
pub value: bool,
pub jump_next: bool,
}
impl From<Instruction> for LoadBoolean {
fn from(instruction: Instruction) -> Self {
LoadBoolean {
destination: instruction.a_field(),
value: instruction.b_field() != 0,
jump_next: instruction.c_field() != 0,
}
}
}
impl From<LoadBoolean> for Instruction {
fn from(load_boolean: LoadBoolean) -> Self {
let operation = Operation::LOAD_BOOLEAN;
let a_field = load_boolean.destination;
let b_field = load_boolean.value as u16;
let c_field = load_boolean.jump_next as u16;
InstructionFields {
operation,
a_field,
b_field,
c_field,
..Default::default()
}
.build()
}
}
impl Display for LoadBoolean {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let LoadBoolean {
destination,
value,
jump_next,
} = self;
write!(f, "R{destination} = {value}")?;
if *jump_next {
write!(f, " JUMP +1")?;
}
Ok(())
}
}

View File

@ -0,0 +1,74 @@
use std::fmt::{self, Display, Formatter};
use crate::{Instruction, Operation};
use super::{InstructionFields, TypeCode};
pub struct LoadEncoded {
pub destination: u16,
pub value: u16,
pub value_type: TypeCode,
pub jump_next: bool,
}
impl From<Instruction> for LoadEncoded {
fn from(instruction: Instruction) -> Self {
LoadEncoded {
destination: instruction.a_field(),
value: instruction.b_field(),
value_type: instruction.b_type(),
jump_next: instruction.c_field() != 0,
}
}
}
impl From<LoadEncoded> for Instruction {
fn from(load_boolean: LoadEncoded) -> Self {
let operation = Operation::LOAD_ENCODED;
let a_field = load_boolean.destination;
let b_field = load_boolean.value;
let b_type = load_boolean.value_type;
let c_field = load_boolean.jump_next as u16;
InstructionFields {
operation,
a_field,
b_field,
b_type,
c_field,
..Default::default()
}
.build()
}
}
impl Display for LoadEncoded {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let LoadEncoded {
destination,
value,
value_type,
jump_next,
} = self;
match *value_type {
TypeCode::BOOLEAN => {
let boolean = *value != 0;
write!(f, "R_BOOL_{destination} = {boolean}")?
}
TypeCode::BYTE => {
let byte = *value as u8;
write!(f, "R_BYTE_{destination} = 0x{byte:0X}")?
}
_ => panic!("Invalid type code {value_type} for LoadEncoded instruction"),
}
if *jump_next {
write!(f, " JUMP +1")?;
}
Ok(())
}
}

View File

@ -102,8 +102,8 @@ mod equal;
mod jump;
mod less;
mod less_equal;
mod load_boolean;
mod load_constant;
mod load_encoded;
mod load_function;
mod load_list;
mod load_self;
@ -128,8 +128,8 @@ pub use equal::Equal;
pub use jump::Jump;
pub use less::Less;
pub use less_equal::LessEqual;
pub use load_boolean::LoadBoolean;
pub use load_constant::LoadConstant;
pub use load_encoded::LoadEncoded;
pub use load_function::LoadFunction;
pub use load_list::LoadList;
pub use load_self::LoadSelf;
@ -286,10 +286,16 @@ impl Instruction {
Instruction::from(Close { from, to })
}
pub fn load_boolean(destination: u16, value: bool, jump_next: bool) -> Instruction {
Instruction::from(LoadBoolean {
pub fn load_encoded(
destination: u16,
value: u16,
value_type: TypeCode,
jump_next: bool,
) -> Instruction {
Instruction::from(LoadEncoded {
destination,
value,
value_type,
jump_next,
})
}
@ -546,7 +552,7 @@ impl Instruction {
match self.operation() {
Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())),
Operation::POINT
| Operation::LOAD_BOOLEAN
| Operation::LOAD_ENCODED
| Operation::LOAD_LIST
| Operation::LOAD_SELF
| Operation::ADD
@ -599,7 +605,7 @@ impl Instruction {
pub fn yields_value(&self) -> bool {
match self.operation() {
Operation::POINT
| Operation::LOAD_BOOLEAN
| Operation::LOAD_ENCODED
| Operation::LOAD_CONSTANT
| Operation::LOAD_FUNCTION
| Operation::LOAD_LIST
@ -633,7 +639,7 @@ impl Instruction {
match operation {
Operation::POINT => Point::from(*self).to_string(),
Operation::LOAD_BOOLEAN => LoadBoolean::from(*self).to_string(),
Operation::LOAD_ENCODED => LoadEncoded::from(*self).to_string(),
Operation::LOAD_CONSTANT => LoadConstant::from(*self).to_string(),
Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(),
Operation::LOAD_LIST => LoadList::from(*self).to_string(),

View File

@ -14,7 +14,7 @@ impl Operation {
pub const CLOSE: Operation = Operation(1);
// Loaders
pub const LOAD_BOOLEAN: Operation = Operation(2);
pub const LOAD_ENCODED: Operation = Operation(2);
pub const LOAD_CONSTANT: Operation = Operation(3);
pub const LOAD_FUNCTION: Operation = Operation(4);
pub const LOAD_LIST: Operation = Operation(5);
@ -53,7 +53,7 @@ impl Operation {
pub fn name(&self) -> &'static str {
match *self {
Self::POINT => "POINT",
Self::LOAD_BOOLEAN => "LOAD_BOOLEAN",
Self::LOAD_ENCODED => "LOAD_ENCODED",
Self::LOAD_CONSTANT => "LOAD_CONSTANT",
Self::LOAD_FUNCTION => "LOAD_FUNCTION",
Self::LOAD_LIST => "LOAD_LIST",

View File

@ -276,7 +276,7 @@ mod tests {
const ALL_OPERATIONS: [(Operation, RunnerLogic); 23] = [
(Operation::POINT, point),
(Operation::CLOSE, close),
(Operation::LOAD_BOOLEAN, load_boolean),
(Operation::LOAD_ENCODED, load_boolean),
(Operation::LOAD_CONSTANT, load_constant),
(Operation::LOAD_FUNCTION, load_function),
(Operation::LOAD_LIST, load_list),

View File

@ -15,10 +15,10 @@ fn true_and_true() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, true, false),
Instruction::load_encoded(0, true, false),
Instruction::test(0, true),
Instruction::jump(1, true),
Instruction::load_boolean(1, true, false),
Instruction::load_encoded(1, true, false),
Instruction::r#return(true),
],
smallvec![
@ -51,10 +51,10 @@ fn false_and_false() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, false, false),
Instruction::load_encoded(0, false, false),
Instruction::test(0, true),
Instruction::jump(1, true),
Instruction::load_boolean(1, false, false),
Instruction::load_encoded(1, false, false),
Instruction::r#return(true),
],
smallvec![
@ -87,10 +87,10 @@ fn false_and_true() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, false, false),
Instruction::load_encoded(0, false, false),
Instruction::test(0, true),
Instruction::jump(1, true),
Instruction::load_boolean(1, true, false),
Instruction::load_encoded(1, true, false),
Instruction::r#return(true),
],
smallvec![
@ -123,10 +123,10 @@ fn true_and_false() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, true, false),
Instruction::load_encoded(0, true, false),
Instruction::test(0, true),
Instruction::jump(1, true),
Instruction::load_boolean(1, false, false),
Instruction::load_encoded(1, false, false),
Instruction::r#return(true),
],
smallvec![

View File

@ -15,13 +15,13 @@ fn true_and_true_and_true() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, true, false),
Instruction::load_encoded(0, true, false),
Instruction::test(0, true),
Instruction::jump(1, true),
Instruction::load_boolean(1, true, false),
Instruction::load_encoded(1, true, false),
Instruction::test(1, true),
Instruction::jump(1, true),
Instruction::load_boolean(2, true, false),
Instruction::load_encoded(2, true, false),
Instruction::r#return(true),
],
smallvec![

View File

@ -15,10 +15,10 @@ fn true_or_false() {
return_type: Type::Boolean,
},
smallvec![
Instruction::load_boolean(0, true, false),
Instruction::load_encoded(0, true, false),
Instruction::test(0, false),
Instruction::jump(1, true),
Instruction::load_boolean(1, false, false),
Instruction::load_encoded(1, false, false),
Instruction::r#return(true),
],
smallvec![

View File

@ -39,7 +39,7 @@ fn not() {
return_type: Type::Boolean,
},
vec![
(Instruction::load_boolean(0, true, false), Span(1, 5)),
(Instruction::load_encoded(0, true, false), Span(1, 5)),
(Instruction::not(1, Operand::Register(0)), Span(0, 1)),
(Instruction::r#return(true), Span(5, 5)),
],