1
0

Consolidate point instructions into return instructions

This commit is contained in:
Jeff 2025-02-06 14:34:31 -05:00
parent bd273035aa
commit 75d6948e82
8 changed files with 163 additions and 79 deletions

View File

@ -1287,7 +1287,11 @@ impl<'src> Compiler<'src> {
Type::String => self.next_string_register(),
_ => todo!(),
};
let point = Instruction::point(local_register_index, Operand::Register(register));
let point = Instruction::point(
local_register_index,
Operand::Register(register),
r#type.type_code(),
);
self.emit_instruction(point, r#type, start_position);
}
@ -1304,7 +1308,11 @@ impl<'src> Compiler<'src> {
Type::String => self.next_string_register(),
_ => todo!(),
};
let point = Instruction::point(destination, Operand::Register(local_register_index));
let point = Instruction::point(
destination,
Operand::Register(local_register_index),
r#type.type_code(),
);
self.emit_instruction(point, r#type, self.previous_position);
@ -1695,7 +1703,18 @@ impl<'src> Compiler<'src> {
}
fn parse_implicit_return(&mut self) -> Result<(), CompileError> {
if matches!(self.get_last_operation(), Some(Operation::RETURN))
if matches!(self.get_last_operation(), Some(Operation::POINT)) {
let Point {
destination,
r#type: type_code,
..
} = Point::from(self.instructions.last().unwrap().0);
let (_, r#type, _) = self.instructions.pop().unwrap();
let r#return = Instruction::r#return(true, destination, type_code);
self.emit_instruction(r#return, r#type, self.current_position);
} else if matches!(self.get_last_operation(), Some(Operation::RETURN))
|| matches!(
self.get_last_operations(),
Some([Operation::RETURN, Operation::JUMP])

View File

@ -278,8 +278,12 @@ impl Instruction {
*self = fields.build();
}
pub fn point(destination: u16, to: Operand) -> Instruction {
Instruction::from(Point { destination, to })
pub fn point(destination: u16, to: Operand, r#type: TypeCode) -> Instruction {
Instruction::from(Point {
destination,
to,
r#type,
})
}
pub fn close(from: u16, to: u16) -> Instruction {
@ -711,8 +715,8 @@ impl Operand {
impl Display for Operand {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Operand::Constant(index) => write!(f, "C{index}"),
Operand::Register(index) => write!(f, "R{index}"),
Operand::Constant(index) => write!(f, "{index}"),
Operand::Register(index) => write!(f, "{index}"),
}
}
}

View File

@ -2,11 +2,12 @@ use std::fmt::{self, Display, Formatter};
use crate::{Instruction, Operation};
use super::{InstructionFields, Operand};
use super::{InstructionFields, Operand, TypeCode};
pub struct Point {
pub destination: u16,
pub to: Operand,
pub r#type: TypeCode,
}
impl From<Instruction> for Point {
@ -14,6 +15,7 @@ impl From<Instruction> for Point {
Point {
destination: instruction.a_field(),
to: instruction.b_as_operand(),
r#type: instruction.b_type(),
}
}
}
@ -23,11 +25,13 @@ 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;
InstructionFields {
operation,
a_field,
b_field,
b_type,
b_is_constant,
..Default::default()
}
@ -37,8 +41,23 @@ impl From<Point> for Instruction {
impl Display for Point {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let Point { destination, to } = self;
let Point {
destination,
to,
r#type,
} = self;
write!(f, "R{destination} -> {to}")
match *r#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}"),
TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} -> R_FLOAT_{to}"),
TypeCode::INTEGER => write!(f, "R_INT_{destination} -> R_INT_{to}"),
TypeCode::STRING => write!(f, "R_STR_{destination} -> R_STR_{to}"),
unsupported => write!(
f,
"Unsupported type code: {unsupported} for Point instruction"
),
}
}
}

View File

@ -2,7 +2,7 @@ use std::io::{Write, stdin, stdout};
use std::ops::Range;
use crate::DustString;
use crate::vm::Thread;
use crate::vm::{Register, Thread};
pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<usize>) {
let mut buffer = String::new();
@ -13,8 +13,9 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<u
buffer.truncate(length.saturating_sub(1));
let string = DustString::from(buffer);
let register = Register::Value(string);
data.set_string_register(destination, string);
data.set_string_register(destination, register);
}
}

View File

@ -2,7 +2,7 @@ use std::ops::Range;
use rand::Rng;
use crate::vm::Thread;
use crate::vm::{Register, Thread};
pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<usize>) {
let mut argument_range_iter = argument_range.into_iter();
@ -16,14 +16,15 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<u
let integer = data.get_integer_register(register_index);
if min.is_none() {
min = Some(integer);
min = Some(*integer);
} else {
break (min, integer);
break (min, *integer);
}
}
};
let random_integer = rand::thread_rng().gen_range(min.unwrap()..max);
let register = Register::Value(random_integer);
data.set_integer_register(destination, random_integer);
data.set_integer_register(destination, register);
}

View File

@ -35,41 +35,41 @@ impl ConcreteValue {
ConcreteValue::String(to_string.into())
}
pub fn as_boolean(&self) -> Option<bool> {
pub fn as_boolean(&self) -> Option<&bool> {
if let ConcreteValue::Boolean(boolean) = self {
Some(*boolean)
Some(boolean)
} else {
None
}
}
pub fn as_byte(&self) -> Option<u8> {
pub fn as_byte(&self) -> Option<&u8> {
if let ConcreteValue::Byte(byte) = self {
Some(*byte)
Some(byte)
} else {
None
}
}
pub fn as_character(&self) -> Option<char> {
pub fn as_character(&self) -> Option<&char> {
if let ConcreteValue::Character(character) = self {
Some(*character)
Some(character)
} else {
None
}
}
pub fn as_float(&self) -> Option<f64> {
pub fn as_float(&self) -> Option<&f64> {
if let ConcreteValue::Float(float) = self {
Some(*float)
Some(float)
} else {
None
}
}
pub fn as_integer(&self) -> Option<i64> {
pub fn as_integer(&self) -> Option<&i64> {
if let ConcreteValue::Integer(integer) = self {
Some(*integer)
Some(integer)
} else {
None
}

View File

@ -3,7 +3,7 @@ use crate::{
instruction::{InstructionFields, TypeCode},
};
use super::thread::Thread;
use super::{Pointer, Register, thread::Thread};
#[derive(Debug)]
pub struct ActionSequence {
@ -74,7 +74,39 @@ pub fn close(instruction: InstructionFields, thread: &mut Thread) {}
pub fn load_boolean(instruction: InstructionFields, thread: &mut Thread) {}
pub fn load_constant(instruction: InstructionFields, thread: &mut Thread) {}
pub fn load_constant(instruction: InstructionFields, thread: &mut Thread) {
let destination = instruction.a_field as usize;
let constant_index = instruction.b_field as usize;
let constant_type = instruction.b_type;
let jump_next = instruction.c_field != 0;
match constant_type {
TypeCode::CHARACTER => {
let constant = *thread.get_constant(constant_index).as_character().unwrap();
let register = Register::Value(constant);
thread.set_character_register(destination, register);
}
TypeCode::FLOAT => {
let constant = *thread.get_constant(constant_index).as_float().unwrap();
let register = Register::Value(constant);
thread.set_float_register(destination, register);
}
TypeCode::INTEGER => {
let constant = *thread.get_constant(constant_index).as_integer().unwrap();
let register = Register::Value(constant);
thread.set_integer_register(destination as usize, register);
}
TypeCode::STRING => {
let register = Register::Pointer(Pointer::Constant(constant_index));
thread.set_string_register(destination as usize, register);
}
_ => unimplemented!(),
}
}
pub fn load_list(instruction: InstructionFields, thread: &mut Thread) {}
@ -111,9 +143,10 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) {
} else {
thread.get_integer_register(right)
};
let result = left_value + right_value;
let sum = left_value + right_value;
let register = Register::Value(sum);
thread.set_integer_register(destination, result);
thread.set_integer_register(destination, register);
}
(TypeCode::STRING, TypeCode::STRING) => {
let left_value = if left_is_constant {
@ -146,9 +179,10 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) {
} else {
thread.get_string_register(right).clone()
};
let result = left_value + &right_value;
let concatenated = left_value + &right_value;
let register = Register::Value(concatenated);
thread.set_string_register(destination, result);
thread.set_string_register(destination, register);
}
_ => unimplemented!(),
}
@ -220,7 +254,7 @@ pub fn jump(instruction: InstructionFields, thread: &mut Thread) {
if is_positive {
thread.current_frame_mut().ip += offset;
} else {
thread.current_frame_mut().ip -= offset;
thread.current_frame_mut().ip -= offset + 1;
}
}
@ -236,23 +270,23 @@ pub fn r#return(instruction: InstructionFields, thread: &mut Thread) {
if should_return_value {
match return_type {
TypeCode::BOOLEAN => {
let return_value = thread.get_boolean_register(return_register);
let return_value = *thread.get_boolean_register(return_register);
thread.return_value = Some(Some(Value::boolean(return_value)));
}
TypeCode::BYTE => {
let return_value = thread.get_byte_register(return_register);
let return_value = *thread.get_byte_register(return_register);
thread.return_value = Some(Some(Value::byte(return_value)));
}
TypeCode::CHARACTER => {
let return_value = thread.get_character_register(return_register);
let return_value = *thread.get_character_register(return_register);
thread.return_value = Some(Some(Value::character(return_value)));
}
TypeCode::FLOAT => {
let return_value = thread.get_float_register(return_register);
let return_value = *thread.get_float_register(return_register);
thread.return_value = Some(Some(Value::float(return_value)));
}
TypeCode::INTEGER => {
let return_value = thread.get_integer_register(return_register);
let return_value = *thread.get_integer_register(return_register);
thread.return_value = Some(Some(Value::integer(return_value)));
}
TypeCode::STRING => {

View File

@ -1,4 +1,4 @@
use std::{sync::Arc, thread::JoinHandle};
use std::{collections::HashMap, sync::Arc, thread::JoinHandle};
use tracing::{info, trace};
@ -10,6 +10,7 @@ pub struct Thread {
chunk: Arc<Chunk>,
call_stack: Vec<CallFrame>,
pub return_value: Option<Option<Value>>,
pub integer_cache: HashMap<usize, *const i64>,
_spawned_threads: Vec<JoinHandle<()>>,
}
@ -24,6 +25,7 @@ impl Thread {
chunk,
call_stack,
return_value: None,
integer_cache: HashMap::new(),
_spawned_threads: Vec::new(),
}
}
@ -46,9 +48,9 @@ impl Thread {
ip
};
let current_action = if cfg!(debug_assertions) {
current_frame.action_sequence.actions.get(ip).unwrap()
current_frame.action_sequence.actions.get_mut(ip).unwrap()
} else {
unsafe { current_frame.action_sequence.actions.get_unchecked(ip) }
unsafe { current_frame.action_sequence.actions.get_unchecked_mut(ip) }
};
trace!(
@ -86,7 +88,7 @@ impl Thread {
}
}
pub fn get_boolean_register(&self, register_index: usize) -> bool {
pub fn get_boolean_register(&self, register_index: usize) -> &bool {
let register = if cfg!(debug_assertions) {
self.call_stack
.last()
@ -107,13 +109,13 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
}
pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> bool {
pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> &bool {
match pointer {
Pointer::Register(register_index) => self.get_boolean_register(*register_index),
Pointer::Constant(constant_index) => {
@ -132,7 +134,7 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
@ -140,8 +142,8 @@ impl Thread {
}
}
pub fn set_boolean_register(&mut self, register_index: usize, value: bool) {
let register = if cfg!(debug_assertions) {
pub fn set_boolean_register(&mut self, register_index: usize, new_register: Register<bool>) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -160,10 +162,10 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_byte_register(&self, register_index: usize) -> u8 {
pub fn get_byte_register(&self, register_index: usize) -> &u8 {
let register = if cfg!(debug_assertions) {
self.call_stack
.last()
@ -184,13 +186,13 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_byte(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
}
pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> u8 {
pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> &u8 {
match pointer {
Pointer::Register(register_index) => self.get_byte_register(*register_index),
Pointer::Constant(constant_index) => {
@ -209,7 +211,7 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_byte(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
@ -217,8 +219,8 @@ impl Thread {
}
}
pub fn set_byte_register(&mut self, register_index: usize, value: u8) {
let register = if cfg!(debug_assertions) {
pub fn set_byte_register(&mut self, register_index: usize, new_register: Register<u8>) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -237,10 +239,10 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_character_register(&self, register_index: usize) -> char {
pub fn get_character_register(&self, register_index: usize) -> &char {
let register = if cfg!(debug_assertions) {
self.call_stack
.last()
@ -261,13 +263,13 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_character(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
}
pub fn get_pointer_to_character(&self, pointer: &Pointer) -> char {
pub fn get_pointer_to_character(&self, pointer: &Pointer) -> &char {
match pointer {
Pointer::Register(register_index) => self.get_character_register(*register_index),
Pointer::Constant(constant_index) => {
@ -295,7 +297,7 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_character(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
@ -303,8 +305,8 @@ impl Thread {
}
}
pub fn set_character_register(&mut self, register_index: usize, value: char) {
let register = if cfg!(debug_assertions) {
pub fn set_character_register(&mut self, register_index: usize, new_register: Register<char>) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -323,10 +325,10 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_float_register(&self, register_index: usize) -> f64 {
pub fn get_float_register(&self, register_index: usize) -> &f64 {
let register = if cfg!(debug_assertions) {
self.call_stack
.last()
@ -347,13 +349,13 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_float(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
}
pub fn get_pointer_to_float(&self, pointer: &Pointer) -> f64 {
pub fn get_pointer_to_float(&self, pointer: &Pointer) -> &f64 {
match pointer {
Pointer::Register(register_index) => self.get_float_register(*register_index),
Pointer::Constant(constant_index) => {
@ -372,7 +374,7 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_float(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
@ -380,8 +382,8 @@ impl Thread {
}
}
pub fn set_float_register(&mut self, register_index: usize, value: f64) {
let register = if cfg!(debug_assertions) {
pub fn set_float_register(&mut self, register_index: usize, new_register: Register<f64>) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -400,10 +402,10 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_integer_register(&self, register_index: usize) -> i64 {
pub fn get_integer_register(&self, register_index: usize) -> &i64 {
let register = if cfg!(debug_assertions) {
self.call_stack
.last()
@ -424,13 +426,13 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_integer(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
}
pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> i64 {
pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> &i64 {
match pointer {
Pointer::Register(register_index) => self.get_integer_register(*register_index),
Pointer::Constant(constant_index) => {
@ -449,7 +451,7 @@ impl Thread {
};
match register {
Register::Value(value) => *value,
Register::Value(value) => value,
Register::Pointer(pointer) => self.get_pointer_to_integer(pointer),
Register::Empty => panic!("Attempted to get value from empty register"),
}
@ -457,8 +459,8 @@ impl Thread {
}
}
pub fn set_integer_register(&mut self, register_index: usize, value: i64) {
let register = if cfg!(debug_assertions) {
pub fn set_integer_register(&mut self, register_index: usize, new_register: Register<i64>) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -477,7 +479,7 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_string_register(&self, register_index: usize) -> &DustString {
@ -534,8 +536,12 @@ impl Thread {
}
}
pub fn set_string_register(&mut self, register_index: usize, value: DustString) {
let register = if cfg!(debug_assertions) {
pub fn set_string_register(
&mut self,
register_index: usize,
new_register: Register<DustString>,
) {
let old_register = if cfg!(debug_assertions) {
self.call_stack
.last_mut()
.unwrap()
@ -554,7 +560,7 @@ impl Thread {
}
};
*register = Register::Value(value);
*old_register = new_register;
}
pub fn get_constant(&self, constant_index: usize) -> &ConcreteValue {