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 { if let Token::Boolean(text) = self.current_token {
self.advance()?; self.advance()?;
let boolean = text.parse::<bool>().unwrap(); let boolean = text.parse::<bool>().unwrap() as u16;
let destination = self.next_boolean_register(); 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(()) Ok(())
} else { } else {
@ -652,10 +653,12 @@ impl<'src> Compiler<'src> {
self.advance()?; self.advance()?;
let byte = u8::from_str_radix(&text[2..], 16) let byte = u8::from_str_radix(&text[2..], 16)
.map_err(|error| CompileError::ParseIntError { error, position })?; .map_err(|error| CompileError::ParseIntError { error, position })?
let value = ConcreteValue::Byte(byte); 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(()) Ok(())
} else { } else {
@ -836,7 +839,7 @@ impl<'src> Compiler<'src> {
let (argument, push_back) = match instruction.operation() { let (argument, push_back) = match instruction.operation() {
Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false), Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false),
Operation::POINT => (instruction.b_as_operand(), false), Operation::POINT => (instruction.b_as_operand(), false),
Operation::LOAD_BOOLEAN Operation::LOAD_ENCODED
| Operation::LOAD_LIST | Operation::LOAD_LIST
| Operation::LOAD_SELF | Operation::LOAD_SELF
| Operation::ADD | Operation::ADD
@ -1114,8 +1117,10 @@ impl<'src> Compiler<'src> {
} }
}; };
let jump = Instruction::jump(1, true); let jump = Instruction::jump(1, true);
let load_true = Instruction::load_boolean(destination, true, true); let load_true =
let load_false = Instruction::load_boolean(destination, false, false); 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(comparison, Type::Boolean, operator_position);
self.emit_instruction(jump, Type::None, operator_position); self.emit_instruction(jump, Type::None, operator_position);
@ -1385,8 +1390,8 @@ impl<'src> Compiler<'src> {
Some([ Some([
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
Operation::JUMP, Operation::JUMP,
Operation::LOAD_BOOLEAN, Operation::LOAD_ENCODED,
Operation::LOAD_BOOLEAN Operation::LOAD_ENCODED
]), ]),
) { ) {
self.instructions.pop(); self.instructions.pop();
@ -1456,7 +1461,7 @@ impl<'src> Compiler<'src> {
match else_block_distance { match else_block_distance {
0 => {} 0 => {}
1 => { 1 => {
if let Some([Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT, _]) = if let Some([Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT, _]) =
self.get_last_operations() self.get_last_operations()
{ {
let loader_index = self.instructions.len() - 2; let loader_index = self.instructions.len() - 2;
@ -1491,7 +1496,7 @@ impl<'src> Compiler<'src> {
self.instructions self.instructions
.insert(if_block_start, (jump, Type::None, if_block_start_position)); .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 else_block_last_instruction_index = self.instructions.len() - 1;
let if_block_last_instruction = self.instructions[if_block_last_instruction_index].0; 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()); 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(()) Ok(())
} }
@ -1517,8 +1520,8 @@ impl<'src> Compiler<'src> {
Some([ Some([
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
Operation::JUMP, Operation::JUMP,
Operation::LOAD_BOOLEAN, Operation::LOAD_ENCODED,
Operation::LOAD_BOOLEAN Operation::LOAD_ENCODED
]), ]),
) { ) {
self.instructions.pop(); 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 jump;
mod less; mod less;
mod less_equal; mod less_equal;
mod load_boolean;
mod load_constant; mod load_constant;
mod load_encoded;
mod load_function; mod load_function;
mod load_list; mod load_list;
mod load_self; mod load_self;
@ -128,8 +128,8 @@ pub use equal::Equal;
pub use jump::Jump; pub use jump::Jump;
pub use less::Less; pub use less::Less;
pub use less_equal::LessEqual; pub use less_equal::LessEqual;
pub use load_boolean::LoadBoolean;
pub use load_constant::LoadConstant; pub use load_constant::LoadConstant;
pub use load_encoded::LoadEncoded;
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;
@ -286,10 +286,16 @@ impl Instruction {
Instruction::from(Close { from, to }) Instruction::from(Close { from, to })
} }
pub fn load_boolean(destination: u16, value: bool, jump_next: bool) -> Instruction { pub fn load_encoded(
Instruction::from(LoadBoolean { destination: u16,
value: u16,
value_type: TypeCode,
jump_next: bool,
) -> Instruction {
Instruction::from(LoadEncoded {
destination, destination,
value, value,
value_type,
jump_next, jump_next,
}) })
} }
@ -546,7 +552,7 @@ impl Instruction {
match self.operation() { match self.operation() {
Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())), Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())),
Operation::POINT Operation::POINT
| Operation::LOAD_BOOLEAN | Operation::LOAD_ENCODED
| Operation::LOAD_LIST | Operation::LOAD_LIST
| Operation::LOAD_SELF | Operation::LOAD_SELF
| Operation::ADD | Operation::ADD
@ -599,7 +605,7 @@ impl Instruction {
pub fn yields_value(&self) -> bool { pub fn yields_value(&self) -> bool {
match self.operation() { match self.operation() {
Operation::POINT Operation::POINT
| Operation::LOAD_BOOLEAN | Operation::LOAD_ENCODED
| Operation::LOAD_CONSTANT | Operation::LOAD_CONSTANT
| Operation::LOAD_FUNCTION | Operation::LOAD_FUNCTION
| Operation::LOAD_LIST | Operation::LOAD_LIST
@ -633,7 +639,7 @@ impl Instruction {
match operation { match operation {
Operation::POINT => Point::from(*self).to_string(), 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_CONSTANT => LoadConstant::from(*self).to_string(),
Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(), Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(),
Operation::LOAD_LIST => LoadList::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); pub const CLOSE: Operation = Operation(1);
// Loaders // 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_CONSTANT: Operation = Operation(3);
pub const LOAD_FUNCTION: Operation = Operation(4); pub const LOAD_FUNCTION: Operation = Operation(4);
pub const LOAD_LIST: Operation = Operation(5); pub const LOAD_LIST: Operation = Operation(5);
@ -53,7 +53,7 @@ impl Operation {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
match *self { match *self {
Self::POINT => "POINT", Self::POINT => "POINT",
Self::LOAD_BOOLEAN => "LOAD_BOOLEAN", Self::LOAD_ENCODED => "LOAD_ENCODED",
Self::LOAD_CONSTANT => "LOAD_CONSTANT", Self::LOAD_CONSTANT => "LOAD_CONSTANT",
Self::LOAD_FUNCTION => "LOAD_FUNCTION", Self::LOAD_FUNCTION => "LOAD_FUNCTION",
Self::LOAD_LIST => "LOAD_LIST", Self::LOAD_LIST => "LOAD_LIST",

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ fn not() {
return_type: Type::Boolean, return_type: Type::Boolean,
}, },
vec![ 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::not(1, Operand::Register(0)), Span(0, 1)),
(Instruction::r#return(true), Span(5, 5)), (Instruction::r#return(true), Span(5, 5)),
], ],