Expand VM functionality; Slow the VM down quite a bit
This commit is contained in:
parent
7153cc16f2
commit
b0f7ca7992
@ -299,7 +299,7 @@ impl<'src> Compiler<'src> {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, r#type, _)| {
|
.find_map(|(instruction, r#type, _)| {
|
||||||
if (r#type == &Type::Byte)
|
if *r#type == Type::Byte
|
||||||
|| (instruction.operation() == Operation::LOAD_ENCODED
|
|| (instruction.operation() == Operation::LOAD_ENCODED
|
||||||
&& instruction.b_type() == TypeCode::BYTE)
|
&& instruction.b_type() == TypeCode::BYTE)
|
||||||
{
|
{
|
||||||
@ -332,8 +332,11 @@ impl<'src> Compiler<'src> {
|
|||||||
self.instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, _, _)| {
|
.find_map(|(instruction, r#type, _)| {
|
||||||
if instruction.b_type() == TypeCode::FLOAT && instruction.yields_value() {
|
if *r#type == Type::Float
|
||||||
|
|| (instruction.operation() == Operation::LOAD_CONSTANT
|
||||||
|
&& instruction.b_type() == TypeCode::FLOAT)
|
||||||
|
{
|
||||||
Some(instruction.a_field() + 1)
|
Some(instruction.a_field() + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -14,9 +14,9 @@ pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Th
|
|||||||
let right_index = instruction.c_field as usize;
|
let right_index = instruction.c_field as usize;
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_byte_from_register(left_index);
|
let left_value = current_frame.get_byte_from_register(left_index).clone();
|
||||||
let right_value = current_frame.get_byte_from_register(right_index);
|
let right_value = current_frame.get_byte_from_register(right_index).clone();
|
||||||
let sum = left_value.add(right_value);
|
let sum = left_value.add(&right_value);
|
||||||
|
|
||||||
current_frame
|
current_frame
|
||||||
.registers
|
.registers
|
||||||
@ -72,13 +72,15 @@ pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut T
|
|||||||
current_frame.get_float_constant(left)
|
current_frame.get_float_constant(left)
|
||||||
} else {
|
} else {
|
||||||
current_frame.get_float_from_register(left)
|
current_frame.get_float_from_register(left)
|
||||||
};
|
}
|
||||||
|
.clone();
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
current_frame.get_float_constant(right)
|
current_frame.get_float_constant(right)
|
||||||
} else {
|
} else {
|
||||||
current_frame.get_float_from_register(right)
|
current_frame.get_float_from_register(right)
|
||||||
};
|
}
|
||||||
let sum = left_value.add(right_value);
|
.clone();
|
||||||
|
let sum = left_value.add(&right_value);
|
||||||
|
|
||||||
current_frame
|
current_frame
|
||||||
.registers
|
.registers
|
||||||
@ -100,13 +102,15 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
current_frame.get_integer_constant(left)
|
current_frame.get_integer_constant(left)
|
||||||
} else {
|
} else {
|
||||||
current_frame.get_integer_from_register(left)
|
current_frame.get_integer_from_register(left)
|
||||||
};
|
}
|
||||||
|
.clone();
|
||||||
let right_value = if right_is_constant {
|
let right_value = if right_is_constant {
|
||||||
current_frame.get_integer_constant(right)
|
current_frame.get_integer_constant(right)
|
||||||
} else {
|
} else {
|
||||||
current_frame.get_integer_from_register(right)
|
current_frame.get_integer_from_register(right)
|
||||||
};
|
}
|
||||||
let sum = left_value.add(right_value);
|
.clone();
|
||||||
|
let sum = left_value.add(&right_value);
|
||||||
|
|
||||||
current_frame
|
current_frame
|
||||||
.registers
|
.registers
|
||||||
@ -201,12 +205,13 @@ pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thre
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn optimized_add_integer(
|
pub fn optimized_add_integer(
|
||||||
|
_: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &InstructionFields,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
||||||
) {
|
) {
|
||||||
if let Some([destination, left, right]) = cache {
|
if let Some([destination, left, right]) = cache {
|
||||||
trace!("ADD_INTEGERS_OPTIMIZED using cache");
|
trace!("OPTIMIZED_ADD using integer cache");
|
||||||
|
|
||||||
let sum = left.add(right);
|
let sum = left.add(right);
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ pub fn optimized_equal_integers(
|
|||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &InstructionFields,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 2]>,
|
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
||||||
) {
|
) {
|
||||||
if let Some([left, right]) = cache {
|
if let Some([_, left, right]) = cache {
|
||||||
trace!("equal_INTEGERS_OPTIMIZED using cache");
|
trace!("equal_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
let is_equal = left == right;
|
let is_equal = left == right;
|
||||||
@ -193,6 +193,6 @@ pub fn optimized_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([left_value, right_value]);
|
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,10 +139,10 @@ pub fn optimized_less_integers(
|
|||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &InstructionFields,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 2]>,
|
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
||||||
) {
|
) {
|
||||||
if let Some([left, right]) = cache {
|
if let Some([_, left, right]) = cache {
|
||||||
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
trace!("OPTIMIZED_LESS using integer cache");
|
||||||
|
|
||||||
let is_less_than = left < right;
|
let is_less_than = left < right;
|
||||||
|
|
||||||
@ -193,6 +193,6 @@ pub fn optimized_less_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([left_value, right_value]);
|
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,9 +139,9 @@ pub fn optimized_less_equal_integers(
|
|||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &InstructionFields,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 2]>,
|
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
||||||
) {
|
) {
|
||||||
if let Some([left, right]) = cache {
|
if let Some([_, left, right]) = cache {
|
||||||
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
let is_less_than_or_equal = left <= right;
|
let is_less_than_or_equal = left <= right;
|
||||||
@ -193,6 +193,6 @@ pub fn optimized_less_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([left_value, right_value]);
|
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,18 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::{InstructionFields, TypeCode},
|
instruction::{InstructionFields, TypeCode},
|
||||||
Operation, Value,
|
AbstractList, ConcreteValue, Operation, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{call_frame::RuntimeValue, thread::Thread};
|
use super::{call_frame::RuntimeValue, thread::Thread, Pointer};
|
||||||
|
|
||||||
|
pub type ActionLogic = fn(&mut usize, &InstructionFields, &mut Thread);
|
||||||
|
pub type OptimizedActionLogicIntegers =
|
||||||
|
fn(&mut usize, &InstructionFields, &mut Thread, &mut Option<[RuntimeValue<i64>; 3]>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ActionSequence {
|
pub struct ActionSequence {
|
||||||
actions: Vec<(Action, InstructionFields)>,
|
actions: Vec<Action>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActionSequence {
|
impl ActionSequence {
|
||||||
@ -49,13 +53,13 @@ impl ActionSequence {
|
|||||||
let mut loop_actions = Vec::with_capacity(backward_offset + 1);
|
let mut loop_actions = Vec::with_capacity(backward_offset + 1);
|
||||||
let jump_action = Action::optimized(&instruction);
|
let jump_action = Action::optimized(&instruction);
|
||||||
|
|
||||||
loop_actions.push((jump_action, instruction));
|
loop_actions.push(jump_action);
|
||||||
|
|
||||||
for _ in 0..backward_offset {
|
for _ in 0..backward_offset {
|
||||||
let instruction = instructions_reversed.next().unwrap();
|
let instruction = instructions_reversed.next().unwrap();
|
||||||
let action = Action::optimized(&instruction);
|
let action = Action::optimized(&instruction);
|
||||||
|
|
||||||
loop_actions.push((action, instruction));
|
loop_actions.push(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop_actions.reverse();
|
loop_actions.reverse();
|
||||||
@ -64,7 +68,7 @@ impl ActionSequence {
|
|||||||
actions: loop_actions,
|
actions: loop_actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.push((r#loop, instruction));
|
actions.push(r#loop);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -72,7 +76,7 @@ impl ActionSequence {
|
|||||||
|
|
||||||
let action = Action::unoptimized(instruction);
|
let action = Action::unoptimized(instruction);
|
||||||
|
|
||||||
actions.push((action, instruction));
|
actions.push(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.reverse();
|
actions.reverse();
|
||||||
@ -84,7 +88,11 @@ impl ActionSequence {
|
|||||||
let mut local_ip = 0;
|
let mut local_ip = 0;
|
||||||
|
|
||||||
while local_ip < self.actions.len() {
|
while local_ip < self.actions.len() {
|
||||||
let (action, instruction) = &mut self.actions[local_ip];
|
let action = if cfg!(debug_assertions) {
|
||||||
|
self.actions.get_mut(local_ip).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.actions.get_unchecked_mut(local_ip) }
|
||||||
|
};
|
||||||
local_ip += 1;
|
local_ip += 1;
|
||||||
|
|
||||||
info!("Run {action}");
|
info!("Run {action}");
|
||||||
@ -96,17 +104,12 @@ impl ActionSequence {
|
|||||||
Action::Loop { actions } => {
|
Action::Loop { actions } => {
|
||||||
actions.run(thread);
|
actions.run(thread);
|
||||||
}
|
}
|
||||||
Action::OptimizedAddIntegers(cache) => {
|
Action::OptimizedIntegers {
|
||||||
optimized_add_integer(instruction, thread, cache);
|
logic,
|
||||||
}
|
instruction,
|
||||||
Action::OptimizedEqualIntegers(cache) => {
|
cache,
|
||||||
optimized_equal_integers(&mut local_ip, instruction, thread, cache);
|
} => {
|
||||||
}
|
logic(&mut local_ip, &*instruction, thread, cache);
|
||||||
Action::OptimizedLessIntegers(cache) => {
|
|
||||||
optimized_less_integers(&mut local_ip, instruction, thread, cache);
|
|
||||||
}
|
|
||||||
Action::OptimizedLessEqualIntegers(cache) => {
|
|
||||||
optimized_less_equal_integers(&mut local_ip, instruction, thread, cache);
|
|
||||||
}
|
}
|
||||||
Action::OptimizedJumpForward { offset } => {
|
Action::OptimizedJumpForward { offset } => {
|
||||||
local_ip += *offset;
|
local_ip += *offset;
|
||||||
@ -123,7 +126,7 @@ impl Display for ActionSequence {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
|
||||||
for (index, (action, _)) in self.actions.iter().enumerate() {
|
for (index, action) in self.actions.iter().enumerate() {
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
@ -144,10 +147,11 @@ enum Action {
|
|||||||
Loop {
|
Loop {
|
||||||
actions: ActionSequence,
|
actions: ActionSequence,
|
||||||
},
|
},
|
||||||
OptimizedAddIntegers(Option<[RuntimeValue<i64>; 3]>),
|
OptimizedIntegers {
|
||||||
OptimizedEqualIntegers(Option<[RuntimeValue<i64>; 2]>),
|
logic: OptimizedActionLogicIntegers,
|
||||||
OptimizedLessIntegers(Option<[RuntimeValue<i64>; 2]>),
|
instruction: InstructionFields,
|
||||||
OptimizedLessEqualIntegers(Option<[RuntimeValue<i64>; 2]>),
|
cache: Option<[RuntimeValue<i64>; 3]>,
|
||||||
|
},
|
||||||
OptimizedJumpForward {
|
OptimizedJumpForward {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
},
|
},
|
||||||
@ -224,19 +228,35 @@ impl Action {
|
|||||||
pub fn optimized(instruction: &InstructionFields) -> Self {
|
pub fn optimized(instruction: &InstructionFields) -> Self {
|
||||||
match instruction.operation {
|
match instruction.operation {
|
||||||
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedAddIntegers(None),
|
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
||||||
|
logic: optimized_add_integer,
|
||||||
|
instruction: *instruction,
|
||||||
|
cache: None,
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::EQUAL => match (instruction.b_type, instruction.c_type) {
|
Operation::EQUAL => match (instruction.b_type, instruction.c_type) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedEqualIntegers(None),
|
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
||||||
|
logic: optimized_equal_integers,
|
||||||
|
instruction: *instruction,
|
||||||
|
cache: None,
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::LESS => match (instruction.b_type, instruction.c_type) {
|
Operation::LESS => match (instruction.b_type, instruction.c_type) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedLessIntegers(None),
|
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
||||||
|
logic: optimized_less_integers,
|
||||||
|
instruction: *instruction,
|
||||||
|
cache: None,
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::LESS_EQUAL => match (instruction.b_type, instruction.c_type) {
|
Operation::LESS_EQUAL => match (instruction.b_type, instruction.c_type) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedLessEqualIntegers(None),
|
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
||||||
|
logic: optimized_less_equal_integers,
|
||||||
|
instruction: *instruction,
|
||||||
|
cache: None,
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::JUMP => {
|
Operation::JUMP => {
|
||||||
@ -267,17 +287,8 @@ impl Display for Action {
|
|||||||
Action::Loop { actions } => {
|
Action::Loop { actions } => {
|
||||||
write!(f, "LOOP: {actions}")
|
write!(f, "LOOP: {actions}")
|
||||||
}
|
}
|
||||||
Action::OptimizedAddIntegers { .. } => {
|
Action::OptimizedIntegers { instruction, .. } => {
|
||||||
write!(f, "ADD_INTEGERS_OPTIMIZED")
|
write!(f, "OPTIMIZED_{}", instruction.operation)
|
||||||
}
|
|
||||||
Action::OptimizedEqualIntegers { .. } => {
|
|
||||||
write!(f, "EQUAL_INTEGERS_OPTIMIZED")
|
|
||||||
}
|
|
||||||
Action::OptimizedLessIntegers { .. } => {
|
|
||||||
write!(f, "LESS_INTEGERS_OPTIMIZED")
|
|
||||||
}
|
|
||||||
Action::OptimizedLessEqualIntegers { .. } => {
|
|
||||||
write!(f, "LESS_EQUAL_INTEGERS_OPTIMIZED")
|
|
||||||
}
|
}
|
||||||
Action::OptimizedJumpForward { offset } => {
|
Action::OptimizedJumpForward { offset } => {
|
||||||
write!(f, "JUMP +{offset}")
|
write!(f, "JUMP +{offset}")
|
||||||
@ -289,8 +300,6 @@ impl Display for Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ActionLogic = fn(&mut usize, &InstructionFields, &mut Thread);
|
|
||||||
|
|
||||||
fn point(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn point(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -388,7 +397,96 @@ fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut T
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_list(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn load_list(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
todo!()
|
let destination = instruction.a_field as usize;
|
||||||
|
let start_register = instruction.b_field as usize;
|
||||||
|
let item_type = instruction.b_type;
|
||||||
|
let end_register = instruction.c_field as usize;
|
||||||
|
let jump_next = instruction.d_field;
|
||||||
|
let current_frame = thread.current_frame_mut();
|
||||||
|
|
||||||
|
let mut item_pointers = Vec::with_capacity(end_register - start_register + 1);
|
||||||
|
|
||||||
|
match item_type {
|
||||||
|
TypeCode::BOOLEAN => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed = current_frame.registers.booleans.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::BYTE => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed = current_frame.registers.bytes.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::CHARACTER => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed =
|
||||||
|
current_frame.registers.characters.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::FLOAT => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed = current_frame.registers.floats.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::INTEGER => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed = current_frame.registers.integers.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::STRING => {
|
||||||
|
for register_index in start_register..=end_register {
|
||||||
|
let register_is_closed = current_frame.registers.strings.is_closed(register_index);
|
||||||
|
|
||||||
|
if register_is_closed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_pointers.push(Pointer::Register(register_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = RuntimeValue::Raw(AbstractList {
|
||||||
|
item_type,
|
||||||
|
item_pointers,
|
||||||
|
});
|
||||||
|
|
||||||
|
current_frame.registers.lists.get_mut(destination).set(list);
|
||||||
|
|
||||||
|
if jump_next {
|
||||||
|
*ip += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_function(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn load_function(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
||||||
@ -423,10 +521,6 @@ fn test_set(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn less_equal(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn negate(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn negate(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -488,7 +582,76 @@ fn r#return(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread)
|
|||||||
thread.return_value = Some(Value::string(return_value));
|
thread.return_value = Some(Value::string(return_value));
|
||||||
}
|
}
|
||||||
TypeCode::LIST => {
|
TypeCode::LIST => {
|
||||||
todo!()
|
let abstract_list = current_frame
|
||||||
|
.get_list_from_register(return_register)
|
||||||
|
.clone_inner();
|
||||||
|
let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len());
|
||||||
|
|
||||||
|
match abstract_list.item_type {
|
||||||
|
TypeCode::BOOLEAN => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let boolean = current_frame
|
||||||
|
.get_boolean_from_pointer(&pointer)
|
||||||
|
.clone_inner();
|
||||||
|
let value = ConcreteValue::Boolean(boolean);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::BYTE => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let byte = current_frame.get_byte_from_pointer(&pointer).clone_inner();
|
||||||
|
let value = ConcreteValue::Byte(byte);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::CHARACTER => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let character = current_frame
|
||||||
|
.get_character_from_pointer(&pointer)
|
||||||
|
.clone_inner();
|
||||||
|
let value = ConcreteValue::Character(character);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::FLOAT => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let float =
|
||||||
|
current_frame.get_float_from_pointer(&pointer).clone_inner();
|
||||||
|
let value = ConcreteValue::Float(float);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::INTEGER => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let integer = current_frame
|
||||||
|
.get_integer_from_pointer(&pointer)
|
||||||
|
.clone_inner();
|
||||||
|
let value = ConcreteValue::Integer(integer);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeCode::STRING => {
|
||||||
|
for pointer in abstract_list.item_pointers {
|
||||||
|
let string = current_frame
|
||||||
|
.get_string_from_pointer(&pointer)
|
||||||
|
.clone_inner();
|
||||||
|
let value = ConcreteValue::String(string);
|
||||||
|
|
||||||
|
concrete_list.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.return_value = Some(Value::Concrete(ConcreteValue::list(
|
||||||
|
concrete_list,
|
||||||
|
abstract_list.item_type,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,62 @@ impl CallFrame {
|
|||||||
unsafe { self.constants.strings.get_unchecked_mut(constant_index) }
|
unsafe { self.constants.strings.get_unchecked_mut(constant_index) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_list_from_register(&self, register_index: usize) -> &RuntimeValue<AbstractList> {
|
||||||
|
let register = self.registers.lists.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_list_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_list_from_register_mut(
|
||||||
|
&mut self,
|
||||||
|
register_index: usize,
|
||||||
|
) -> &mut RuntimeValue<AbstractList> {
|
||||||
|
let register = self.registers.lists.get_mut(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { .. } => panic!("Attempted to get mutable list from pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_list_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<AbstractList> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_list_from_register(*register_index),
|
||||||
|
Pointer::Constant(_) => panic!("Attempted to get list from constant pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_function_from_register(&self, register_index: usize) -> &RuntimeValue<Function> {
|
||||||
|
let register = self.registers.functions.get(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { pointer, .. } => self.get_function_from_pointer(pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_function_from_register_mut(
|
||||||
|
&mut self,
|
||||||
|
register_index: usize,
|
||||||
|
) -> &mut RuntimeValue<Function> {
|
||||||
|
let register = self.registers.functions.get_mut(register_index);
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::Value { value, .. } => value,
|
||||||
|
Register::Pointer { .. } => panic!("Attempted to get mutable function from pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_function_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue<Function> {
|
||||||
|
match pointer {
|
||||||
|
Pointer::Register(register_index) => self.get_function_from_register(*register_index),
|
||||||
|
Pointer::Constant(_) => panic!("Attempted to get function from constant pointer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CallFrame {
|
impl Display for CallFrame {
|
||||||
@ -460,42 +516,66 @@ impl<T: Clone> RuntimeValue<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Add<Output = T> + Copy> Add for &RuntimeValue<T> {
|
const BYTE_ADD: fn(u8, u8) -> u8 = u8::saturating_add;
|
||||||
type Output = T;
|
|
||||||
|
impl Add for &RuntimeValue<u8> {
|
||||||
|
type Output = u8;
|
||||||
|
|
||||||
fn add(self, other: Self) -> Self::Output {
|
fn add(self, other: Self) -> Self::Output {
|
||||||
match (self, other) {
|
let left = match self {
|
||||||
(RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => *left + *right,
|
RuntimeValue::Raw(value) => *value,
|
||||||
(RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => *left + **right,
|
RuntimeValue::Rc(value) => **value,
|
||||||
(RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => {
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
let right = right.borrow();
|
};
|
||||||
|
let right = match other {
|
||||||
|
RuntimeValue::Raw(value) => *value,
|
||||||
|
RuntimeValue::Rc(value) => **value,
|
||||||
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
|
};
|
||||||
|
|
||||||
*left + *right
|
BYTE_ADD(left, right)
|
||||||
}
|
}
|
||||||
(RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left + *right,
|
}
|
||||||
(RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left + **right,
|
|
||||||
(RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => {
|
|
||||||
let right = right.borrow();
|
|
||||||
|
|
||||||
**left + *right
|
const FLOAT_ADD: fn(f64, f64) -> f64 = f64::add;
|
||||||
}
|
|
||||||
(RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => {
|
|
||||||
let left = left.borrow();
|
|
||||||
let right = right.borrow();
|
|
||||||
|
|
||||||
*left + *right
|
impl Add for &RuntimeValue<f64> {
|
||||||
}
|
type Output = f64;
|
||||||
(RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => {
|
|
||||||
let left = left.borrow();
|
|
||||||
|
|
||||||
*left + *right
|
fn add(self, other: Self) -> Self::Output {
|
||||||
}
|
let left = match self {
|
||||||
(RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => {
|
RuntimeValue::Raw(value) => *value,
|
||||||
let left = left.borrow();
|
RuntimeValue::Rc(value) => **value,
|
||||||
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
|
};
|
||||||
|
let right = match other {
|
||||||
|
RuntimeValue::Raw(value) => *value,
|
||||||
|
RuntimeValue::Rc(value) => **value,
|
||||||
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
|
};
|
||||||
|
|
||||||
*left + **right
|
FLOAT_ADD(left, right)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const INTEGER_ADD: fn(i64, i64) -> i64 = i64::saturating_add;
|
||||||
|
|
||||||
|
impl Add for &RuntimeValue<i64> {
|
||||||
|
type Output = i64;
|
||||||
|
|
||||||
|
fn add(self, other: Self) -> Self::Output {
|
||||||
|
let left = match self {
|
||||||
|
RuntimeValue::Raw(value) => *value,
|
||||||
|
RuntimeValue::Rc(value) => **value,
|
||||||
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
|
};
|
||||||
|
let right = match other {
|
||||||
|
RuntimeValue::Raw(value) => *value,
|
||||||
|
RuntimeValue::Rc(value) => **value,
|
||||||
|
RuntimeValue::RefCell(value) => *value.borrow(),
|
||||||
|
};
|
||||||
|
|
||||||
|
INTEGER_ADD(left, right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
Chunk, ConcreteValue, DustString, FunctionType, Instruction, Span, Type, Value, compile,
|
compile, instruction::TypeCode, run, Chunk, ConcreteValue, DustString, FunctionType,
|
||||||
instruction::TypeCode, run,
|
Instruction, Span, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -67,7 +67,7 @@ fn load_character() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::CHARACTER),
|
Instruction::r#return(true, 0, TypeCode::CHARACTER),
|
||||||
],
|
],
|
||||||
positions: vec![Span(0, 3), Span(3, 3)],
|
positions: vec![Span(0, 3), Span(3, 3)],
|
||||||
constants: vec![ConcreteValue::Character('a')],
|
character_constants: vec!['a'],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::character('a'));
|
let return_value = Some(Value::character('a'));
|
||||||
@ -86,7 +86,7 @@ fn load_float() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::FLOAT),
|
Instruction::r#return(true, 0, TypeCode::FLOAT),
|
||||||
],
|
],
|
||||||
positions: vec![Span(0, 5), Span(5, 5)],
|
positions: vec![Span(0, 5), Span(5, 5)],
|
||||||
constants: vec![ConcreteValue::Float(42.42)],
|
float_constants: vec![42.42],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::float(42.42));
|
let return_value = Some(Value::float(42.42));
|
||||||
@ -105,7 +105,7 @@ fn load_integer() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::INTEGER),
|
Instruction::r#return(true, 0, TypeCode::INTEGER),
|
||||||
],
|
],
|
||||||
positions: vec![Span(0, 2), Span(2, 2)],
|
positions: vec![Span(0, 2), Span(2, 2)],
|
||||||
constants: vec![ConcreteValue::Integer(42)],
|
integer_constants: vec![42],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::integer(42));
|
let return_value = Some(Value::integer(42));
|
||||||
@ -124,7 +124,7 @@ fn load_string() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::STRING),
|
Instruction::r#return(true, 0, TypeCode::STRING),
|
||||||
],
|
],
|
||||||
positions: vec![Span(0, 15), Span(15, 15)],
|
positions: vec![Span(0, 15), Span(15, 15)],
|
||||||
constants: vec![ConcreteValue::String(DustString::from("Hello, World!"))],
|
string_constants: vec![DustString::from("Hello, World!")],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::string("Hello, World!"));
|
let return_value = Some(Value::string("Hello, World!"));
|
||||||
@ -191,7 +191,7 @@ fn load_character_list() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::LIST),
|
Instruction::r#return(true, 0, TypeCode::LIST),
|
||||||
],
|
],
|
||||||
positions: vec![Span(1, 4), Span(6, 9), Span(0, 10), Span(10, 10)],
|
positions: vec![Span(1, 4), Span(6, 9), Span(0, 10), Span(10, 10)],
|
||||||
constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')],
|
character_constants: vec!['a', 'b'],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
@ -215,7 +215,7 @@ fn load_float_list() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::LIST),
|
Instruction::r#return(true, 0, TypeCode::LIST),
|
||||||
],
|
],
|
||||||
positions: vec![Span(1, 6), Span(8, 13), Span(0, 14), Span(14, 14)],
|
positions: vec![Span(1, 6), Span(8, 13), Span(0, 14), Span(14, 14)],
|
||||||
constants: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)],
|
float_constants: vec![42.42, 24.24],
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
@ -240,11 +240,7 @@ fn load_integer_list() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::LIST),
|
Instruction::r#return(true, 0, TypeCode::LIST),
|
||||||
],
|
],
|
||||||
positions: vec![Span(1, 2), Span(4, 5), Span(7, 8), Span(0, 9), Span(9, 9)],
|
positions: vec![Span(1, 2), Span(4, 5), Span(7, 8), Span(0, 9), Span(9, 9)],
|
||||||
constants: vec![
|
integer_constants: vec![1, 2, 3],
|
||||||
ConcreteValue::Integer(1),
|
|
||||||
ConcreteValue::Integer(2),
|
|
||||||
ConcreteValue::Integer(3),
|
|
||||||
],
|
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
@ -272,10 +268,7 @@ fn load_string_list() {
|
|||||||
Instruction::r#return(true, 0, TypeCode::LIST),
|
Instruction::r#return(true, 0, TypeCode::LIST),
|
||||||
],
|
],
|
||||||
positions: vec![Span(1, 8), Span(10, 17), Span(0, 18), Span(18, 18)],
|
positions: vec![Span(1, 8), Span(10, 17), Span(0, 18), Span(18, 18)],
|
||||||
constants: vec![
|
string_constants: vec![DustString::from("Hello"), DustString::from("World")],
|
||||||
ConcreteValue::String(DustString::from("Hello")),
|
|
||||||
ConcreteValue::String(DustString::from("World")),
|
|
||||||
],
|
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
@ -315,12 +308,7 @@ fn load_nested_list() {
|
|||||||
Span(0, 16),
|
Span(0, 16),
|
||||||
Span(16, 16),
|
Span(16, 16),
|
||||||
],
|
],
|
||||||
constants: vec![
|
integer_constants: vec![1, 2, 3, 4],
|
||||||
ConcreteValue::Integer(1),
|
|
||||||
ConcreteValue::Integer(2),
|
|
||||||
ConcreteValue::Integer(3),
|
|
||||||
ConcreteValue::Integer(4),
|
|
||||||
],
|
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
@ -386,16 +374,7 @@ fn load_deeply_nested_list() {
|
|||||||
Span(0, 36),
|
Span(0, 36),
|
||||||
Span(36, 36),
|
Span(36, 36),
|
||||||
],
|
],
|
||||||
constants: vec![
|
integer_constants: vec![1, 2, 3, 4, 5, 6, 7, 8],
|
||||||
ConcreteValue::Integer(1),
|
|
||||||
ConcreteValue::Integer(2),
|
|
||||||
ConcreteValue::Integer(3),
|
|
||||||
ConcreteValue::Integer(4),
|
|
||||||
ConcreteValue::Integer(5),
|
|
||||||
ConcreteValue::Integer(6),
|
|
||||||
ConcreteValue::Integer(7),
|
|
||||||
ConcreteValue::Integer(8),
|
|
||||||
],
|
|
||||||
..Chunk::default()
|
..Chunk::default()
|
||||||
};
|
};
|
||||||
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
let return_value = Some(Value::Concrete(ConcreteValue::List {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user