More refactoring of dvm; add DvmValue::String and related.
This commit is contained in:
parent
172e82025d
commit
26d87acff5
@ -16,7 +16,7 @@ pub enum DvmArray {
|
||||
Booleans(Vec<bool>),
|
||||
Objects(Vec<Rc<RefCell<DvmObject>>>),
|
||||
Arrays(Vec<Rc<RefCell<DvmArray>>>),
|
||||
ConstantPointers(Vec<DvmPointer>),
|
||||
Strings(Vec<Rc<String>>)
|
||||
}
|
||||
|
||||
impl DvmArray {
|
||||
@ -30,7 +30,7 @@ impl DvmArray {
|
||||
DvmArray::Booleans(vec) => DvmValue::Boolean(vec[index]),
|
||||
DvmArray::Objects(vec) => DvmValue::Object(vec[index].clone()),
|
||||
DvmArray::Arrays(vec) => DvmValue::Array(vec[index].clone()),
|
||||
DvmArray::ConstantPointers(vec) => DvmValue::ConstantPointer(vec[index].clone()),
|
||||
DvmArray::Strings(vec) => DvmValue::String(vec[index].clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,8 +60,8 @@ impl DvmArray {
|
||||
DvmArray::Arrays(vec) => {
|
||||
vec[index] = value.expect_array();
|
||||
}
|
||||
DvmArray::ConstantPointers(vec) => {
|
||||
vec[index] = value.expect_constant_pointer();
|
||||
DvmArray::Strings(vec) => {
|
||||
vec[index] = value.expect_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,7 +89,7 @@ pub enum DvmArrayIter<'a> {
|
||||
Booleans(Iter<'a, bool>),
|
||||
Objects(Iter<'a, Rc<RefCell<DvmObject>>>),
|
||||
Arrays(Iter<'a, Rc<RefCell<DvmArray>>>),
|
||||
ConstantPointers(Iter<'a, DvmPointer>),
|
||||
Strings(Iter<'a, Rc<String>>),
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DvmArrayIter<'a> {
|
||||
@ -104,9 +104,7 @@ impl<'a> Iterator for DvmArrayIter<'a> {
|
||||
DvmArrayIter::Booleans(iter) => iter.next().map(|b| DvmValue::Boolean(*b)),
|
||||
DvmArrayIter::Objects(iter) => iter.next().map(|o| DvmValue::Object(o.clone())),
|
||||
DvmArrayIter::Arrays(iter) => iter.next().map(|a| DvmValue::Array(a.clone())),
|
||||
DvmArrayIter::ConstantPointers(iter) => {
|
||||
iter.next().map(|p| DvmValue::ConstantPointer(p.clone()))
|
||||
}
|
||||
DvmArrayIter::Strings(iter) => iter.next().map(|s| DvmValue::String(s.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,7 +123,7 @@ impl<'a> IntoIterator for &'a DvmArray {
|
||||
DvmArray::Booleans(v) => DvmArrayIter::Booleans(v.iter()),
|
||||
DvmArray::Objects(v) => DvmArrayIter::Objects(v.iter()),
|
||||
DvmArray::Arrays(v) => DvmArrayIter::Arrays(v.iter()),
|
||||
DvmArray::ConstantPointers(v) => DvmArrayIter::ConstantPointers(v.iter()),
|
||||
DvmArray::Strings(v) => DvmArrayIter::Strings(v.iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
src/vm/constant.rs
Normal file
17
src/vm/constant.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DvmConstant {
|
||||
String(String),
|
||||
Array(DvmConstantArray)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DvmConstantArray {
|
||||
Bytes(Vec<u8>),
|
||||
Ints(Vec<i32>),
|
||||
Longs(Vec<i64>),
|
||||
Doubles(Vec<f64>),
|
||||
USizes(Vec<usize>),
|
||||
Booleans(Vec<bool>),
|
||||
Strings(Vec<String>),
|
||||
Arrays(Vec<DvmConstantArray>)
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
use std::rc::Rc;
|
||||
use crate::vm::constant::DvmConstant;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Instruction {
|
||||
@ -29,8 +30,13 @@ pub enum Instruction {
|
||||
function_name: Rc<String>,
|
||||
source_code_location: SourceCodeLocation,
|
||||
},
|
||||
PlatformCall {
|
||||
platform_function_name: Rc<String>,
|
||||
InvokeStaticPlatform {
|
||||
function_name: Rc<String>,
|
||||
source_code_location: SourceCodeLocation,
|
||||
},
|
||||
InvokeObjectPlatform {
|
||||
object_register: usize,
|
||||
function_name: Rc<String>,
|
||||
source_code_location: SourceCodeLocation,
|
||||
},
|
||||
Add {
|
||||
@ -107,10 +113,7 @@ pub enum Immediate {
|
||||
Double(f64),
|
||||
Usize(usize),
|
||||
Boolean(bool),
|
||||
ConstantPointer {
|
||||
raw_pointer: *const u8,
|
||||
length: usize
|
||||
},
|
||||
Constant(DvmConstant),
|
||||
Empty,
|
||||
}
|
||||
|
||||
|
313
src/vm/mod.rs
313
src/vm/mod.rs
@ -1,4 +1,5 @@
|
||||
mod array;
|
||||
mod constant;
|
||||
mod field;
|
||||
mod function;
|
||||
pub mod implementation;
|
||||
@ -15,10 +16,11 @@ pub mod util;
|
||||
pub mod value;
|
||||
mod virtual_method;
|
||||
|
||||
use crate::vm::array::DvmArray;
|
||||
use crate::vm::constant::{DvmConstant, DvmConstantArray};
|
||||
use crate::vm::implementation::DvmImplementation;
|
||||
use crate::vm::instruction::{Immediate, Instruction, Location, SourceCodeLocation};
|
||||
use crate::vm::object::DvmObject;
|
||||
use crate::vm::pointer::DvmPointer;
|
||||
use crate::vm::value::DvmValue;
|
||||
use function::DvmFunction;
|
||||
use std::cell::RefCell;
|
||||
@ -26,22 +28,22 @@ use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn dvm_panic(context: &DvmContext, message: &str) {
|
||||
fn dvm_panic(state: &DvmState, message: &str) {
|
||||
println!("----");
|
||||
println!("Deimos Virtual Machine: Panic!");
|
||||
println!("{}", message);
|
||||
println!("----");
|
||||
println!("Current Instruction: {:?}", context.current_instruction);
|
||||
println!("Current Instruction: {:?}", state.current_instruction);
|
||||
println!("Registers:");
|
||||
for (i, register) in context.registers.iter().enumerate() {
|
||||
for (i, register) in state.registers.iter().enumerate() {
|
||||
println!("\tr{}: {:?}", i, register);
|
||||
}
|
||||
println!("Call stack:");
|
||||
for call in context.call_stack.iter() {
|
||||
for call in state.call_stack.iter() {
|
||||
println!("\t{}", call);
|
||||
}
|
||||
println!("Stack:");
|
||||
for (i, value) in context.stack.iter().enumerate() {
|
||||
for (i, value) in state.stack.iter().enumerate() {
|
||||
println!("\t{}: {}", i, value);
|
||||
}
|
||||
println!("----");
|
||||
@ -54,13 +56,33 @@ macro_rules! dvm_panic {
|
||||
};
|
||||
}
|
||||
|
||||
pub type PlatformFunction = fn(context: &mut DvmContext);
|
||||
pub type PlatformFunction = fn(state: &mut DvmState, context: &DvmContext);
|
||||
|
||||
pub struct DvmContext {
|
||||
pub struct DvmState {
|
||||
call_stack: Vec<DvmCall>,
|
||||
current_instruction: Option<Instruction>,
|
||||
registers: Vec<DvmValue>,
|
||||
stack: Vec<DvmValue>,
|
||||
}
|
||||
|
||||
impl DvmState {
|
||||
pub fn new() -> Self {
|
||||
DvmState {
|
||||
call_stack: vec![],
|
||||
current_instruction: None,
|
||||
registers: vec![],
|
||||
stack: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_stack(&mut self) -> DvmValue {
|
||||
self.stack.pop().unwrap_or_else(|| {
|
||||
dvm_panic!(self, "Stack underflow!");
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DvmContext {
|
||||
implementations: HashMap<String, Rc<DvmImplementation>>,
|
||||
static_functions: HashMap<String, Rc<DvmFunction>>,
|
||||
platform_functions: HashMap<String, PlatformFunction>,
|
||||
@ -69,21 +91,11 @@ pub struct DvmContext {
|
||||
impl DvmContext {
|
||||
pub fn new() -> Self {
|
||||
DvmContext {
|
||||
call_stack: vec![],
|
||||
current_instruction: None,
|
||||
registers: vec![],
|
||||
stack: vec![],
|
||||
implementations: HashMap::new(),
|
||||
static_functions: HashMap::new(),
|
||||
platform_functions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_stack(&mut self) -> DvmValue {
|
||||
self.stack.pop().unwrap_or_else(|| {
|
||||
dvm_panic!(self, "Stack underflow!");
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DvmCall {
|
||||
@ -114,16 +126,16 @@ fn update_index(index: &mut usize, offset: isize) {
|
||||
fn push_call_frame(
|
||||
function_name: Rc<String>,
|
||||
source_code_location: SourceCodeLocation,
|
||||
context: &mut DvmContext,
|
||||
state: &mut DvmState,
|
||||
) {
|
||||
context.call_stack.push(DvmCall {
|
||||
state.call_stack.push(DvmCall {
|
||||
function_name,
|
||||
source_code_location,
|
||||
});
|
||||
}
|
||||
|
||||
fn pop_call_frame(context: &mut DvmContext) {
|
||||
context.call_stack.pop();
|
||||
fn pop_call_frame(state: &mut DvmState) {
|
||||
state.call_stack.pop();
|
||||
}
|
||||
|
||||
fn compute_index_with_offset(
|
||||
@ -146,17 +158,17 @@ fn compute_index_with_offset(
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_from_source(context: &DvmContext, source: &Location) -> DvmValue {
|
||||
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
||||
match source {
|
||||
Location::Register(register) => context.registers[*register].clone(),
|
||||
Location::Stack { offset } => context.stack[*offset].clone(),
|
||||
Location::Register(register) => state.registers[*register].clone(),
|
||||
Location::Stack { offset } => state.stack[*offset].clone(),
|
||||
Location::Field {
|
||||
object_register,
|
||||
field_name,
|
||||
} => context.registers[*object_register].map_object(
|
||||
} => state.registers[*object_register].map_object(
|
||||
|o| o.borrow().read_field(field_name).clone(),
|
||||
|v| {
|
||||
dvm_panic!(context, &format!("Expected an object, but found: {}", v));
|
||||
dvm_panic!(state, &format!("Expected an object, but found: {}", v));
|
||||
},
|
||||
),
|
||||
Location::Array {
|
||||
@ -164,30 +176,30 @@ fn copy_from_source(context: &DvmContext, source: &Location) -> DvmValue {
|
||||
index_register,
|
||||
offset,
|
||||
} => {
|
||||
let index = compute_index_with_offset(&context.registers, *index_register, offset);
|
||||
context.registers[*array_register].map_array(
|
||||
let index = compute_index_with_offset(&state.registers, *index_register, offset);
|
||||
state.registers[*array_register].map_array(
|
||||
|a| a.borrow().read_element(index),
|
||||
|v| {
|
||||
dvm_panic!(context, &format!("Expected an array, but found: {}", v));
|
||||
dvm_panic!(state, &format!("Expected an array, but found: {}", v));
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_destination(context: &mut DvmContext, destination: &Location, value: DvmValue) {
|
||||
fn write_to_destination(state: &mut DvmState, destination: &Location, value: DvmValue) {
|
||||
match destination {
|
||||
Location::Register(register) => {
|
||||
context.registers[*register] = value;
|
||||
state.registers[*register] = value;
|
||||
}
|
||||
Location::Stack { offset } => {
|
||||
context.stack[*offset] = value;
|
||||
state.stack[*offset] = value;
|
||||
}
|
||||
Location::Field {
|
||||
object_register,
|
||||
field_name,
|
||||
} => {
|
||||
context.registers[*object_register]
|
||||
state.registers[*object_register]
|
||||
.expect_object()
|
||||
.borrow_mut()
|
||||
.write_field(field_name, value);
|
||||
@ -197,8 +209,8 @@ fn write_to_destination(context: &mut DvmContext, destination: &Location, value:
|
||||
index_register,
|
||||
offset,
|
||||
} => {
|
||||
let index = compute_index_with_offset(&context.registers, *index_register, offset);
|
||||
context.registers[*array_register]
|
||||
let index = compute_index_with_offset(&state.registers, *index_register, offset);
|
||||
state.registers[*array_register]
|
||||
.expect_array()
|
||||
.borrow_mut()
|
||||
.write_element(index, value);
|
||||
@ -206,6 +218,32 @@ fn write_to_destination(context: &mut DvmContext, destination: &Location, value:
|
||||
}
|
||||
}
|
||||
|
||||
fn constant_array_to_array(constant_array: &DvmConstantArray) -> DvmArray {
|
||||
match constant_array {
|
||||
DvmConstantArray::Bytes(v) => DvmArray::Bytes(v.clone()),
|
||||
DvmConstantArray::Ints(v) => DvmArray::Ints(v.clone()),
|
||||
DvmConstantArray::Longs(v) => DvmArray::Longs(v.clone()),
|
||||
DvmConstantArray::Doubles(v) => DvmArray::Doubles(v.clone()),
|
||||
DvmConstantArray::USizes(v) => DvmArray::USizes(v.clone()),
|
||||
DvmConstantArray::Booleans(v) => DvmArray::Booleans(v.clone()),
|
||||
DvmConstantArray::Strings(vs) => {
|
||||
DvmArray::Strings(vs.iter().map(|s| Rc::new(s.clone())).collect())
|
||||
}
|
||||
DvmConstantArray::Arrays(va) => DvmArray::Arrays(
|
||||
va.iter()
|
||||
.map(|a| Rc::new(RefCell::new(constant_array_to_array(a))))
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn constant_to_value(constant: &DvmConstant) -> DvmValue {
|
||||
match constant {
|
||||
DvmConstant::String(s) => DvmValue::String(Rc::new(s.clone())),
|
||||
DvmConstant::Array(a) => DvmValue::Array(Rc::new(RefCell::new(constant_array_to_array(a)))),
|
||||
}
|
||||
}
|
||||
|
||||
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
||||
match immediate {
|
||||
Immediate::Byte(b) => DvmValue::Byte(*b),
|
||||
@ -214,135 +252,202 @@ fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
||||
Immediate::Double(d) => DvmValue::Double(*d),
|
||||
Immediate::Usize(s) => DvmValue::USize(*s),
|
||||
Immediate::Boolean(b) => DvmValue::Boolean(*b),
|
||||
Immediate::ConstantPointer {
|
||||
raw_pointer,
|
||||
length,
|
||||
} => DvmValue::ConstantPointer(DvmPointer {
|
||||
raw_pointer: *raw_pointer,
|
||||
length: *length,
|
||||
}),
|
||||
Immediate::Constant(c) => constant_to_value(c),
|
||||
Immediate::Empty => DvmValue::Empty,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: find all possible unwraps/expects and wrap with call to dvm_panic
|
||||
pub fn run(instructions: &[Instruction], context: &mut DvmContext) {
|
||||
pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmContext) {
|
||||
let mut index = 0;
|
||||
while index < instructions.len() {
|
||||
context.current_instruction = Some(instructions[index].clone());
|
||||
state.current_instruction = Some(instructions[index].clone());
|
||||
index += 1;
|
||||
use Instruction::*;
|
||||
match &instructions[index] {
|
||||
Instruction::MoveImmediate {
|
||||
MoveImmediate {
|
||||
destination,
|
||||
immediate,
|
||||
} => {
|
||||
write_to_destination(context, destination, immediate_to_value(immediate));
|
||||
write_to_destination(state, destination, immediate_to_value(immediate));
|
||||
}
|
||||
Instruction::Copy {
|
||||
Copy {
|
||||
source,
|
||||
destination,
|
||||
} => {
|
||||
let value = copy_from_source(context, source);
|
||||
write_to_destination(context, destination, value);
|
||||
let value = copy_from_source(state, source);
|
||||
write_to_destination(state, destination, value);
|
||||
}
|
||||
Instruction::Push { source_register } => {
|
||||
context
|
||||
.stack
|
||||
.push(context.registers[*source_register].clone());
|
||||
Push { source_register } => {
|
||||
state.stack.push(state.registers[*source_register].clone());
|
||||
}
|
||||
Instruction::Pop {
|
||||
Pop {
|
||||
destination_register,
|
||||
} => {
|
||||
let value = context.stack.pop().expect("Stack underflow");
|
||||
context.registers[*destination_register] = value;
|
||||
let value = state.stack.pop().unwrap_or_else(|| {
|
||||
dvm_panic!(state, "Stack underflow");
|
||||
});
|
||||
state.registers[*destination_register] = value;
|
||||
}
|
||||
Instruction::AllocateObject {
|
||||
AllocateObject {
|
||||
implementation_name,
|
||||
destination_register,
|
||||
} => {
|
||||
let implementation = context
|
||||
.implementations
|
||||
.get(implementation_name.as_str())
|
||||
.unwrap();
|
||||
let object = DvmObject::new(implementation.clone());
|
||||
context.registers[*destination_register] =
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!("Cannot find implementation {}", implementation_name)
|
||||
);
|
||||
})
|
||||
.clone();
|
||||
let object = DvmObject::new(implementation);
|
||||
state.registers[*destination_register] =
|
||||
DvmValue::Object(Rc::new(RefCell::new(object)));
|
||||
}
|
||||
Instruction::InvokeStatic {
|
||||
InvokeStatic {
|
||||
function_name,
|
||||
source_code_location,
|
||||
} => {
|
||||
// Find function
|
||||
let static_function = context
|
||||
.static_functions
|
||||
.get(function_name.as_str())
|
||||
.unwrap()
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!("Cannot find static function {}", function_name)
|
||||
);
|
||||
})
|
||||
.clone();
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), context);
|
||||
run(static_function.instructions(), context);
|
||||
pop_call_frame(context);
|
||||
|
||||
// Do call
|
||||
state.stack.push(DvmValue::Empty); // space for return value
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||
run(static_function.instructions(), state, context);
|
||||
pop_call_frame(state);
|
||||
}
|
||||
Instruction::InvokeObject {
|
||||
InvokeObject {
|
||||
object_register,
|
||||
function_name,
|
||||
source_code_location,
|
||||
} => {
|
||||
let object = context.registers[*object_register].expect_object();
|
||||
let object_ref = object.borrow();
|
||||
// Find method and get instructions
|
||||
let object_value = state.registers[*object_register].clone();
|
||||
let object_rc = object_value.expect_object_or_else(|v| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!("Expected DvmValue::Object, but found {}", object_value)
|
||||
);
|
||||
});
|
||||
let object_ref = object_rc.borrow();
|
||||
let method = object_ref
|
||||
.get_method(function_name.as_str())
|
||||
.expect(&format!(
|
||||
"Cannot find method {} for object {:?}",
|
||||
function_name, object
|
||||
));
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!(
|
||||
"Cannot find method {} for object {:?}",
|
||||
function_name, object_ref
|
||||
)
|
||||
);
|
||||
});
|
||||
let function = method.dm_fn();
|
||||
let instructions = function.instructions();
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), context);
|
||||
run(instructions, context);
|
||||
pop_call_frame(context);
|
||||
|
||||
// Do call
|
||||
state.stack.push(DvmValue::Empty); // space for return value
|
||||
state.stack.push(object_value); // self object
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||
run(instructions, state, context);
|
||||
pop_call_frame(state);
|
||||
state.stack.pop(); // self object
|
||||
}
|
||||
Instruction::PlatformCall {
|
||||
platform_function_name,
|
||||
InvokeStaticPlatform {
|
||||
function_name,
|
||||
source_code_location,
|
||||
} => {
|
||||
// Find function
|
||||
let platform_function = context
|
||||
.platform_functions
|
||||
.get(platform_function_name.as_str())
|
||||
.unwrap()
|
||||
.clone();
|
||||
push_call_frame(
|
||||
platform_function_name.clone(),
|
||||
source_code_location.clone(),
|
||||
context,
|
||||
);
|
||||
platform_function(context);
|
||||
pop_call_frame(context);
|
||||
.get(function_name.as_str())
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!("Cannot find static platform function {}", function_name)
|
||||
);
|
||||
});
|
||||
|
||||
// Do call
|
||||
state.stack.push(DvmValue::Empty); // space for return value
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||
platform_function(state, context);
|
||||
pop_call_frame(state);
|
||||
}
|
||||
Instruction::Add { .. } => {}
|
||||
Instruction::Subtract { .. } => {}
|
||||
Instruction::Multiply { .. } => {}
|
||||
Instruction::Divide { .. } => {}
|
||||
Instruction::Modulo { .. } => {}
|
||||
Instruction::Power { .. } => {}
|
||||
Instruction::Jump { offset } => {
|
||||
InvokeObjectPlatform {
|
||||
object_register,
|
||||
function_name,
|
||||
source_code_location,
|
||||
} => {
|
||||
// Find function
|
||||
let object_platform_function = context
|
||||
.platform_functions
|
||||
.get(function_name.as_str())
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!("Cannot find object platform function {}", function_name)
|
||||
);
|
||||
});
|
||||
|
||||
// Get self object
|
||||
let object_value = state.registers[*object_register].clone();
|
||||
if !object_value.is_object() {
|
||||
dvm_panic!(
|
||||
state,
|
||||
&format!(
|
||||
"Expected DvmValue::Object, but found DvmValue::{:?}",
|
||||
object_value
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Do call
|
||||
state.stack.push(DvmValue::Empty); // space for return value
|
||||
state.stack.push(object_value); // self object
|
||||
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||
object_platform_function(state, context);
|
||||
pop_call_frame(state);
|
||||
state.stack.pop(); // self object
|
||||
}
|
||||
Add { .. } => {}
|
||||
Subtract { .. } => {}
|
||||
Multiply { .. } => {}
|
||||
Divide { .. } => {}
|
||||
Modulo { .. } => {}
|
||||
Power { .. } => {}
|
||||
Jump { offset } => {
|
||||
update_index(&mut index, *offset);
|
||||
}
|
||||
Instruction::JumpEqual {
|
||||
JumpEqual {
|
||||
left_register,
|
||||
right_register,
|
||||
offset,
|
||||
} => {
|
||||
let left_value = &context.registers[*left_register];
|
||||
let right_value = &context.registers[*right_register];
|
||||
let left_value = &state.registers[*left_register];
|
||||
let right_value = &state.registers[*right_register];
|
||||
if left_value == right_value {
|
||||
update_index(&mut index, *offset);
|
||||
}
|
||||
}
|
||||
Instruction::JumpNotEqual { .. } => {}
|
||||
Instruction::JumpLessThan { .. } => {}
|
||||
Instruction::JumpGreaterThan { .. } => {}
|
||||
Instruction::JumpLessThanEqual { .. } => {}
|
||||
Instruction::JumpGreaterThanEqual { .. } => {}
|
||||
Instruction::Return => {
|
||||
JumpNotEqual { .. } => {}
|
||||
JumpLessThan { .. } => {}
|
||||
JumpGreaterThan { .. } => {}
|
||||
JumpLessThanEqual { .. } => {}
|
||||
JumpGreaterThanEqual { .. } => {}
|
||||
Return => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::vm::object::DvmObject;
|
||||
use crate::vm::value::DvmValue;
|
||||
use crate::vm::DvmContext;
|
||||
use crate::vm::{DvmContext, DvmState};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -8,12 +8,12 @@ use std::rc::Rc;
|
||||
/// // Signature
|
||||
/// print(m: &(Byte | Int | Long | Double | USize | Boolean | Object | Empty))
|
||||
/// ```
|
||||
pub fn dm_print(context: &mut DvmContext) {
|
||||
print!("{}", get_string(context.pop_stack()));
|
||||
pub fn dm_print(state: &mut DvmState, context: &DvmContext) {
|
||||
print!("{}", get_string(state.pop_stack()));
|
||||
}
|
||||
|
||||
pub fn dm_println(context: &mut DvmContext) {
|
||||
println!("{}", get_string(context.pop_stack()));
|
||||
pub fn dm_println(state: &mut DvmState, context: &DvmContext) {
|
||||
println!("{}", get_string(state.pop_stack()));
|
||||
}
|
||||
|
||||
fn get_string(dvm_value: DvmValue) -> String {
|
||||
@ -26,29 +26,11 @@ fn get_string(dvm_value: DvmValue) -> String {
|
||||
DvmValue::Object(object) => object_to_string(object.clone()),
|
||||
DvmValue::USize(u) => u.to_string(),
|
||||
DvmValue::Array(a) => a.borrow().to_string(),
|
||||
DvmValue::ConstantPointer(p) => p.to_string(),
|
||||
DvmValue::String(s) => s.to_string(),
|
||||
DvmValue::Empty => String::from("Empty"),
|
||||
}
|
||||
}
|
||||
|
||||
fn object_to_string(object: Rc<RefCell<DvmObject>>) -> String {
|
||||
if object.borrow().implementation().fqn() == "std::core::StringImpl" {
|
||||
extract_string_from_string(object.clone())
|
||||
} else {
|
||||
todo!("what happens if we don't have a String?")
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_string_from_string(string_object: Rc<RefCell<DvmObject>>) -> String {
|
||||
let object_ref = string_object.borrow();
|
||||
let bytes_field_value = object_ref.read_field("bytes");
|
||||
if let DvmValue::ConstantPointer(bytes_ptr) = bytes_field_value {
|
||||
let mut v = Vec::new();
|
||||
for i in 0..bytes_ptr.length {
|
||||
v.push(unsafe { bytes_ptr.raw_pointer.add(i).read() });
|
||||
}
|
||||
String::from_utf8(v).unwrap()
|
||||
} else {
|
||||
panic!("StringImpl.bytes field is not a DvmValue::ConstantPointer.");
|
||||
}
|
||||
todo!("Lookup to_string method!")
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ pub enum DvmValue {
|
||||
// Array
|
||||
Array(Rc<RefCell<DvmArray>>),
|
||||
|
||||
// Pointer to constant u8
|
||||
ConstantPointer(DvmPointer),
|
||||
// String
|
||||
String(Rc<String>),
|
||||
|
||||
// Null
|
||||
Empty,
|
||||
@ -45,7 +45,7 @@ impl Display for DvmValue {
|
||||
DvmValue::Boolean(b) => write!(f, "Boolean({})", b),
|
||||
DvmValue::Object(o) => write!(f, "Object({:p})", &o),
|
||||
DvmValue::Array(a) => write!(f, "Array({:p})", &a),
|
||||
DvmValue::ConstantPointer(p) => write!(f, "ConstantPointer({})", p),
|
||||
DvmValue::String(s) => write!(f, "String({})", s),
|
||||
DvmValue::Empty => write!(f, "Empty"),
|
||||
}
|
||||
}
|
||||
@ -103,6 +103,14 @@ impl DvmValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_object_or_else(&self, f: impl FnOnce(&Self) -> DvmObject) -> Rc<RefCell<DvmObject>> {
|
||||
if let DvmValue::Object(o) = self {
|
||||
o.clone()
|
||||
} else {
|
||||
Rc::new(RefCell::new(f(self)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_object<T>(
|
||||
&self,
|
||||
mapper: impl FnOnce(Rc<RefCell<DvmObject>>) -> T,
|
||||
@ -183,14 +191,19 @@ impl DvmValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_constant_pointer(&self) -> DvmPointer {
|
||||
if let DvmValue::ConstantPointer(ptr) = self {
|
||||
ptr.clone()
|
||||
pub fn expect_string(&self) -> Rc<String> {
|
||||
if let DvmValue::String(s) = self {
|
||||
s.clone()
|
||||
} else {
|
||||
panic!(
|
||||
"Expected DvmValue::ConstantPointer, but found DvmValue::{:?}",
|
||||
self
|
||||
);
|
||||
panic!("Expected DvmValue::String, but found DvmValue::{:?}", self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_string_or_else(&self, f: impl FnOnce(&Self) -> String) -> Rc<String> {
|
||||
if let DvmValue::String(s) = self {
|
||||
s.clone()
|
||||
} else {
|
||||
Rc::new(f(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user