Compare commits

..

No commits in common. "fc9cfcdf7c322f37f821039b2530409783172aab" and "258fe824bd11bb40051c7f6f00ab37cfc92038ec" have entirely different histories.

11 changed files with 195 additions and 216 deletions

View File

@ -59,7 +59,7 @@ mov_usize(
) )
---- ----
Unlike the other numerical operand types, this operand remains unsigned at runtime. Unlike most other operand types, this operand remains unsigned at runtime.
=== Move Double === Move Double
@ -91,7 +91,7 @@ The operand is converted to a `bool` at runtime by the virtual machine.
=== Move Register === Move Register
Copies the value in one register to another. Moves or copies (see below) the value in one register to another.
[source] [source]
---- ----
@ -101,6 +101,9 @@ mov_register(
) )
---- ----
For `Byte`, `Int`, `Long`, `USize`, `Double`, and `Boolean`, the value is **copied** to the register. For `Object`
values, the value is **moved**, meaning that register takes ownership of the referenced object.
=== Load === Load
Loads the target register with the `DvmValue` inner value stored in the field at `field_index` in the object in the Loads the target register with the `DvmValue` inner value stored in the field at `field_index` in the object in the

View File

@ -19,12 +19,7 @@ fn main() {
// std::core::Array // std::core::Array
let array_int = DmInterface::new("std::core::Array", "Array"); let array_int = DmInterface::new("std::core::Array", "Array");
array_lib.add_interface(array_int); let array_int_rc = Rc::new(array_int);
let array_int_rc = array_lib
.interfaces()
.iter()
.find(|interface| interface.fqn() == "std::core::Array")
.unwrap();
// std::core::ArrayImpl // std::core::ArrayImpl
let mut array_impl = DmImplementation::new( let mut array_impl = DmImplementation::new(
@ -37,9 +32,9 @@ fn main() {
let array_impl_ptr_size_fld = DmField::new("ptr_size", DmType::USize); let array_impl_ptr_size_fld = DmField::new("ptr_size", DmType::USize);
let array_impl_length_fld = DmField::new("length", DmType::Long); let array_impl_length_fld = DmField::new("length", DmType::Long);
array_impl.add_field(array_impl_ptr_address_fld); array_impl.fields.push(array_impl_ptr_address_fld);
array_impl.add_field(array_impl_ptr_size_fld); array_impl.fields.push(array_impl_ptr_size_fld);
array_impl.add_field(array_impl_length_fld); array_impl.fields.push(array_impl_length_fld);
// std::core::ArrayImpl::_ctor_0( // std::core::ArrayImpl::_ctor_0(
// r0: self // r0: self
@ -61,29 +56,22 @@ fn main() {
None, None,
); );
let array_impl_ctor_0_method = DmMethod::new(array_impl_ctor_0_fn, None); let array_impl_ctor_0_method = DmMethod::new(array_impl_ctor_0_fn, None);
array_impl.add_method(array_impl_ctor_0_method); array_impl.methods.push(Rc::new(array_impl_ctor_0_method));
array_lib.add_implementation(array_impl); // Add Array and ArrayImpl to array lib
array_lib.interfaces.push(array_int_rc.clone());
let array_impl_rc = Rc::new(array_impl);
array_lib.implementations.push(array_impl_rc.clone());
// std::core::String // std::core::String
let mut string_lib = DmLib::new("std/core/string"); let mut string_lib = DmLib::new("std/core/string");
let string_int = DmInterface::new("std::core::String", "String"); let string_int = DmInterface::new("std::core::String", "String");
string_lib.add_interface(string_int);
let string_int_rc = string_lib
.interfaces()
.iter()
.find(|interface| interface.fqn() == "std::core::String")
.unwrap();
let mut string_impl = DmImplementation::new( let mut string_impl = DmImplementation::new("std::core::StringImpl", "StringImpl", None);
"std::core::StringImpl",
"StringImpl",
Some(string_int_rc.clone()),
);
let bytes_field = DmField::new("bytes", DmType::Object); let bytes_field = DmField::new("bytes", DmType::Object);
string_impl.add_field(bytes_field); string_impl.fields.push(bytes_field);
// std::core::String::_ctor_0( // std::core::String::_ctor_0(
// r0: self // r0: self
@ -102,13 +90,16 @@ fn main() {
let string_ctor_0_method = DmMethod::new(string_ctor_0_fn, None); let string_ctor_0_method = DmMethod::new(string_ctor_0_fn, None);
string_impl.add_method(string_ctor_0_method); string_impl.methods.push(Rc::new(string_ctor_0_method));
string_lib.add_implementation(string_impl); string_lib.interfaces.push(Rc::new(string_int));
string_lib.implementations.push(Rc::new(string_impl));
// greeting lib // greeting lib
let mut greeting_lib = DmLib::new("greeting"); let mut greeting_lib = DmLib::new("greeting");
greeting_lib.add_constant(DmConstant::String("Hello, World!".to_string())); greeting_lib
.constants
.push(DmConstant::String("Hello, Jeanna!".to_string()));
let mut main_byte_code = Vec::new(); let mut main_byte_code = Vec::new();
@ -150,7 +141,7 @@ fn main() {
let main_dm_fn = DmFn::new("main", "main", main_byte_code, 7, None); let main_dm_fn = DmFn::new("main", "main", main_byte_code, 7, None);
greeting_lib.add_function(main_dm_fn); greeting_lib.functions.push(Rc::new(main_dm_fn));
let mut state = DvmState::new(); let mut state = DvmState::new();
let mut context = DvmContext::new(); let mut context = DvmContext::new();
@ -159,7 +150,7 @@ fn main() {
Rc::new(string_lib), Rc::new(string_lib),
Rc::new(array_lib), Rc::new(array_lib),
]); ]);
context.load_platform_fns(init_platform_functions()); context.load_platform_fns(&init_platform_functions());
let main_fn = context.fn_by_fqn("main").unwrap(); let main_fn = context.fn_by_fqn("main").unwrap();
call_fn(&mut state, &context, &main_fn, vec![]); call_fn(&mut state, &context, &main_fn, vec![]);

View File

@ -8,3 +8,17 @@ pub enum DmType {
Object, Object,
USize, USize,
} }
impl DmType {
pub fn size_in_bytes(&self) -> usize {
match self {
DmType::Byte => size_of::<u8>(),
DmType::Int => size_of::<i32>(),
DmType::Long => size_of::<i64>(),
DmType::Double => size_of::<f64>(),
DmType::Boolean => size_of::<bool>(),
DmType::Object => size_of::<usize>(),
DmType::USize => size_of::<usize>(),
}
}
}

View File

@ -1,7 +1,7 @@
use crate::vm::object::DvmObject; use crate::vm::object::DvmObject;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, Clone, PartialEq)]
pub enum DvmValue { pub enum DvmValue {
Byte(u8), Byte(u8),
Int(i32), Int(i32),
@ -15,10 +15,6 @@ pub enum DvmValue {
} }
impl DvmValue { impl DvmValue {
pub fn from_object(object: DvmObject) -> Self {
DvmValue::Object(Rc::new(object))
}
pub fn expect_long(&self) -> i64 { pub fn expect_long(&self) -> i64 {
if let DvmValue::Long(l) = self { if let DvmValue::Long(l) = self {
*l *l
@ -27,13 +23,6 @@ impl DvmValue {
} }
} }
pub fn is_long(&self) -> bool {
match self {
DvmValue::Long(_) => true,
_ => false,
}
}
pub fn expect_object(&self) -> Rc<DvmObject> { pub fn expect_object(&self) -> Rc<DvmObject> {
if let DvmValue::Object(o) = self { if let DvmValue::Object(o) = self {
o.clone() o.clone()
@ -56,11 +45,4 @@ impl DvmValue {
panic!("Expected DvmValue::USize, but found DvmValue::{:?}", self); panic!("Expected DvmValue::USize, but found DvmValue::{:?}", self);
} }
} }
pub fn is_usize(&self) -> bool {
match self {
DvmValue::USize(_) => true,
_ => false,
}
}
} }

View File

@ -7,11 +7,11 @@ use crate::vm::object_type::{DmFn, DmImplementation, DmInterface};
use std::rc::Rc; use std::rc::Rc;
pub struct DmLib { pub struct DmLib {
name: String, pub name: String,
constants: Vec<DmConstant>, pub constants: Vec<DmConstant>,
interfaces: Vec<Rc<DmInterface>>, pub interfaces: Vec<Rc<DmInterface>>,
implementations: Vec<Rc<DmImplementation>>, pub implementations: Vec<Rc<DmImplementation>>,
functions: Vec<Rc<DmFn>>, pub functions: Vec<Rc<DmFn>>,
} }
impl DmLib { impl DmLib {
@ -24,42 +24,6 @@ impl DmLib {
functions: Vec::new(), functions: Vec::new(),
} }
} }
pub fn name(&self) -> &str {
&self.name
}
pub fn constants(&self) -> &Vec<DmConstant> {
&self.constants
}
pub fn add_constant(&mut self, constant: DmConstant) {
self.constants.push(constant);
}
pub fn interfaces(&self) -> &Vec<Rc<DmInterface>> {
&self.interfaces
}
pub fn add_interface(&mut self, interface: DmInterface) {
self.interfaces.push(Rc::new(interface));
}
pub fn implementations(&self) -> &Vec<Rc<DmImplementation>> {
&self.implementations
}
pub fn add_implementation(&mut self, implementation: DmImplementation) {
self.implementations.push(Rc::new(implementation));
}
pub fn functions(&self) -> &Vec<Rc<DmFn>> {
&self.functions
}
pub fn add_function(&mut self, function: DmFn) {
self.functions.push(Rc::new(function));
}
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -18,21 +18,21 @@ unsafe fn read_field(data_pointer: *const u8, dm_type: &DmType) -> DvmValue {
pub fn read_field_by_name(field_name: &str, self_object: &DvmObject) -> DvmValue { pub fn read_field_by_name(field_name: &str, self_object: &DvmObject) -> DvmValue {
let (field_index, field) = self_object let (field_index, field) = self_object
.implementation() .implementation()
.fields() .fields
.iter() .iter()
.enumerate() .enumerate()
.find(|(_index, field)| field.name() == field_name) .find(|(_index, field)| field.name() == field_name)
.expect(&format!( .expect(&format!(
"Cannot find field {} in {}", "Cannot find field {} in {}",
field_name, field_name,
self_object.implementation().fqn() self_object.implementation().fqn
)); ));
let data_pointer = self_object.data()[field_index]; let data_pointer = self_object.data()[field_index];
unsafe { read_field(data_pointer, field.dm_type()) } unsafe { read_field(data_pointer, field.dm_type()) }
} }
pub fn read_field_by_index(index: usize, self_object: &DvmObject) -> DvmValue { pub fn read_field_by_index(index: usize, self_object: &DvmObject) -> DvmValue {
let field = &self_object.implementation().fields()[index]; let field = &self_object.implementation().fields[index];
let data_pointer = self_object.data()[index]; let data_pointer = self_object.data()[index];
unsafe { read_field(data_pointer, field.dm_type()) } unsafe { read_field(data_pointer, field.dm_type()) }
} }
@ -68,13 +68,13 @@ unsafe fn write_field(data_pointer: *mut u8, value: DvmValue) {
pub fn write_field_by_name(field_name: &str, self_object: &DvmObject, value: DvmValue) { pub fn write_field_by_name(field_name: &str, self_object: &DvmObject, value: DvmValue) {
let field_index = self_object let field_index = self_object
.implementation() .implementation()
.fields() .fields
.iter() .iter()
.position(|field| field.name() == field_name) .position(|field| field.name() == field_name)
.expect(&format!( .expect(&format!(
"Cannot find field {} in {}", "Cannot find field {} in {}",
field_name, field_name,
self_object.implementation().fqn() self_object.implementation().fqn
)); ));
let data_pointer = self_object.data()[field_index]; let data_pointer = self_object.data()[field_index];
unsafe { write_field(data_pointer, value) }; unsafe { write_field(data_pointer, value) };

View File

@ -2,10 +2,11 @@ pub mod dm_type;
pub mod dvm_value; pub mod dvm_value;
pub mod lib; pub mod lib;
pub mod mem; pub mod mem;
pub mod object; mod object;
pub mod object_type; pub mod object_type;
pub mod op_codes; pub mod op_codes;
pub mod platform; pub mod platform;
mod pointer;
pub mod util; pub mod util;
use crate::vm::dvm_value::DvmValue; use crate::vm::dvm_value::DvmValue;
@ -34,66 +35,70 @@ struct CallFrameInfo {
pub struct DvmContext { pub struct DvmContext {
libs: Vec<Rc<DmLib>>, libs: Vec<Rc<DmLib>>,
function_cache: HashMap<String, Rc<DmFn>>, functions: HashMap<String, Rc<DmFn>>,
platform_functions: HashMap<String, PlatformFunction>, platform_functions: HashMap<String, Rc<PlatformFunction>>,
} }
impl DvmContext { impl DvmContext {
pub fn new() -> Self { pub fn new() -> Self {
DvmContext { DvmContext {
libs: Vec::new(), libs: Vec::new(),
function_cache: HashMap::new(), functions: HashMap::new(),
platform_functions: HashMap::new(), platform_functions: HashMap::new(),
} }
} }
pub fn load_libs(&mut self, libs: Vec<Rc<DmLib>>) { pub fn load_libs(&mut self, libs: Vec<Rc<DmLib>>) {
for lib in libs { for lib in libs {
for lib_fn in lib.functions() { self.libs.push(lib.clone());
self.function_cache for lib_fn in &lib.functions {
self.functions
.insert(lib_fn.fqn().to_string(), lib_fn.clone()); .insert(lib_fn.fqn().to_string(), lib_fn.clone());
} }
for interface_function in lib for interface_function in lib
.interfaces() .interfaces
.iter() .iter()
.flat_map(|interface| interface.functions()) .flat_map(|interface| interface.get_functions())
{ {
self.function_cache.insert( self.functions.insert(
interface_function.fqn().to_string(), interface_function.fqn().to_string(),
interface_function.clone(), interface_function.clone(),
); );
} }
for implementation_function in lib for implementation_function in lib
.implementations() .implementations
.iter() .iter()
.flat_map(|implementation| implementation.functions()) .flat_map(|implementation| &implementation.functions)
{ {
self.function_cache.insert( self.functions.insert(
implementation_function.fqn().to_string(), implementation_function.fqn().to_string(),
implementation_function.clone(), implementation_function.clone(),
); );
} }
for method in lib for method in lib
.implementations() .implementations
.iter() .iter()
.flat_map(|implementation| implementation.methods()) .flat_map(|implementation| &implementation.methods)
{ {
self.function_cache self.functions
.insert(method.dm_fn().fqn().to_string(), method.dm_fn()); .insert(method.dm_fn().fqn().to_string(), method.dm_fn().clone());
} }
self.libs.push(lib);
} }
} }
pub fn load_platform_fns(&mut self, platform_fns: HashMap<String, PlatformFunction>) { pub fn load_platform_fns(&mut self, platform_fns: &HashMap<String, PlatformFunction>) {
platform_fns.iter().for_each(|(fqn, platform_function)| { for (fqn, platform_fn) in platform_fns {
self.platform_functions self.platform_functions
.insert(fqn.to_string(), *platform_function); .insert(fqn.to_string(), Rc::new(*platform_fn));
}); }
} }
pub fn fn_by_fqn(&self, fqn: &str) -> Option<Rc<DmFn>> { pub fn fn_by_fqn(&self, fqn: &str) -> Option<Rc<DmFn>> {
self.function_cache.get(fqn).cloned() self.functions.get(fqn).cloned()
}
pub fn platform_fn_by_fqn(&self, fqn: &str) -> Option<Rc<PlatformFunction>> {
self.platform_functions.get(fqn).cloned()
} }
} }
@ -277,9 +282,8 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
MOV_REGISTER => { MOV_REGISTER => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let source_register = next_8!(iter, usize); let source_register = next_8!(iter, usize);
let source_value = let source_value = state.registers.get(source_register).unwrap();
std::mem::replace(&mut state.registers[source_register], DvmValue::Uninit); state.registers[target_register] = source_value.clone();
state.registers[target_register] = source_value;
} }
LOAD => { LOAD => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
@ -318,24 +322,25 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
.libs .libs
.iter() .iter()
.find_map(|lib| { .find_map(|lib| {
lib.implementations() lib.implementations
.iter() .iter()
.find(|implementation| implementation.fqn() == impl_name) .find(|implementation| implementation.fqn == impl_name)
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
dvm_panic!(&format!("Implementation not found: {}", impl_name), state) dvm_panic!(&format!("Implementation not found: {}", impl_name), state)
}) });
.clone();
let dm_alloc_object = DvmObject::new(implementation); let dm_alloc_object = DvmObject::new(implementation.clone());
state.registers[target_register] = DvmValue::from_object(dm_alloc_object); state.registers[target_register] = DvmValue::Object(Rc::new(dm_alloc_object));
} }
DEALLOC => { DEALLOC => {
let target_register = next_8!(iter, usize); let target_register = next_8!(iter, usize);
let target_object = let dvm_object = state
std::mem::replace(&mut state.registers[target_register], DvmValue::Uninit) .registers
.expect_object(); .get(target_register)
drop(target_object); // explicit .unwrap()
.expect_object();
drop(dvm_object); // explicit
state.registers[target_register] = DvmValue::Uninit; state.registers[target_register] = DvmValue::Uninit;
} }
MOV_CONST => { MOV_CONST => {
@ -346,13 +351,13 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let const_id = next_32_le!(iter, usize); let const_id = next_32_le!(iter, usize);
// Get constant // Get constant
let Some(lib) = context.libs.iter().find(|lib| lib.name() == lib_name) else { let Some(lib) = context.libs.iter().find(|lib| lib.name == lib_name) else {
dvm_panic!( dvm_panic!(
&format!("Could not find lib with name: {}", lib_name), &format!("Could not find lib with name: {}", lib_name),
state state
); );
}; };
let constant = lib.constants().get(const_id).unwrap(); let constant = lib.constants.get(const_id).unwrap();
let DmConstant::String(s) = constant; let DmConstant::String(s) = constant;
let pointer = s.as_ptr(); let pointer = s.as_ptr();
@ -400,7 +405,11 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
args.push(value.clone()); args.push(value.clone());
} }
let platform_function = context.platform_functions.get(&symbol_name).unwrap(); let platform_function = context
.platform_functions
.get(&symbol_name)
.unwrap()
.clone();
state state
.call_stack .call_stack
.push(CallFrame::PlatformCall(CallFrameInfo { fqn: symbol_name })); .push(CallFrame::PlatformCall(CallFrameInfo { fqn: symbol_name }));
@ -419,7 +428,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
args.push(value.clone()); args.push(value.clone());
} }
let dm_fn = context.function_cache.get(&symbol_name).unwrap(); let dm_fn = context.functions.get(&symbol_name).unwrap();
let call_result = call_fn(state, context, dm_fn, args); let call_result = call_fn(state, context, dm_fn, args);
state.registers[return_register] = call_result; state.registers[return_register] = call_result;
} }
@ -437,7 +446,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
let self_obj = args.get(0).unwrap().expect_object(); let self_obj = args.get(0).unwrap().expect_object();
let method = self_obj let method = self_obj
.implementation() .implementation()
.find_method(&symbol_name, &self_obj) .get_method(&symbol_name, &self_obj)
.unwrap_or_else(|| { .unwrap_or_else(|| {
dvm_panic!( dvm_panic!(
&format!("Could not find method with name: {}", symbol_name), &format!("Could not find method with name: {}", symbol_name),
@ -473,11 +482,14 @@ mod run_code_tests {
macro_rules! assert_register { macro_rules! assert_register {
( $expected: expr, $state: expr, $register_number: expr ) => { ( $expected: expr, $state: expr, $register_number: expr ) => {
assert_eq!($expected, $state.registers.remove($register_number)); assert_eq!(
$expected,
$state.registers.get($register_number).unwrap().clone()
);
}; };
} }
fn setup<'a>(number_of_registers: usize) -> (DvmState, DvmContext) { fn setup(number_of_registers: usize) -> (DvmState, DvmContext) {
let mut state = DvmState::new(); let mut state = DvmState::new();
state state
.registers .registers
@ -488,7 +500,7 @@ mod run_code_tests {
fn impl_with_object_field() -> DmImplementation { fn impl_with_object_field() -> DmImplementation {
let mut dm_impl = DmImplementation::new("ImplWithObjectField", "ImplWithObjectField", None); let mut dm_impl = DmImplementation::new("ImplWithObjectField", "ImplWithObjectField", None);
let object_field = DmField::new("object_field", DmType::Object); let object_field = DmField::new("object_field", DmType::Object);
dm_impl.add_field(object_field); dm_impl.fields.push(object_field);
dm_impl dm_impl
} }
@ -532,17 +544,13 @@ mod run_code_tests {
#[test] #[test]
fn load_object() { fn load_object() {
let dummy_impl = impl_with_object_field(); let dummy_impl = impl_with_object_field();
let dummy_impl_rc = Rc::new(dummy_impl);
let mut dummy_lib = DmLib::new("dummy"); let mut dummy_lib = DmLib::new("dummy");
dummy_lib.add_implementation(dummy_impl); dummy_lib.implementations.push(dummy_impl_rc.clone());
let dummy_impl_ref = dummy_lib
.implementations()
.iter()
.find(|implementation| implementation.fqn() == "dummy")
.unwrap();
let mut code = Vec::new(); let mut code = Vec::new();
add_alloc(&mut code, 0, dummy_impl_ref.fqn()); add_alloc(&mut code, 0, &dummy_impl_rc.fqn);
add_alloc(&mut code, 1, dummy_impl_ref.fqn()); add_alloc(&mut code, 1, &dummy_impl_rc.fqn);
add_store(&mut code, 0, 0, 1); add_store(&mut code, 0, 0, 1);
add_load(&mut code, 2, 0, 0); add_load(&mut code, 2, 0, 0);

View File

@ -24,8 +24,8 @@ fn layout_for(dm_type: &DmType) -> Layout {
impl DvmObject { impl DvmObject {
pub fn new(implementation: Rc<DmImplementation>) -> Self { pub fn new(implementation: Rc<DmImplementation>) -> Self {
let mut data = vec![ptr::null_mut(); implementation.fields().len()]; let mut data = vec![ptr::null_mut(); implementation.fields.len()];
for (index, field) in implementation.fields().iter().enumerate() { for (index, field) in implementation.fields.iter().enumerate() {
data[index] = unsafe { alloc(layout_for(field.dm_type())) } data[index] = unsafe { alloc(layout_for(field.dm_type())) }
} }
DvmObject { DvmObject {
@ -45,7 +45,7 @@ impl DvmObject {
impl Drop for DvmObject { impl Drop for DvmObject {
fn drop(&mut self) { fn drop(&mut self) {
for (index, field) in self.implementation.fields().iter().enumerate() { for (index, field) in self.implementation.fields.iter().enumerate() {
unsafe { dealloc(self.data[index], layout_for(field.dm_type())) } unsafe { dealloc(self.data[index], layout_for(field.dm_type())) }
} }
} }

View File

@ -3,6 +3,12 @@ use crate::vm::object::DvmObject;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]
pub enum DmObjectType {
Interface(DmInterface),
Implementation(DmImplementation),
}
#[derive(Debug, Eq)] #[derive(Debug, Eq)]
pub struct DmFn { pub struct DmFn {
fqn: String, fqn: String,
@ -86,7 +92,7 @@ pub struct DmInterface {
fqn: String, fqn: String,
short_name: String, short_name: String,
functions: Vec<Rc<DmFn>>, functions: Vec<Rc<DmFn>>,
virtual_methods: Vec<DmVirtualMethod>, virtual_methods: Vec<Rc<DmVirtualMethod>>,
} }
impl PartialEq for DmInterface { impl PartialEq for DmInterface {
@ -117,23 +123,39 @@ impl DmInterface {
self.functions.push(Rc::new(dm_fn)); self.functions.push(Rc::new(dm_fn));
} }
pub fn functions(&self) -> &Vec<Rc<DmFn>> { pub fn get_functions(&self) -> Vec<Rc<DmFn>> {
&self.functions self.functions.clone()
} }
pub fn add_method(&mut self, dm_virtual_method: DmVirtualMethod) { pub fn add_method(&mut self, dm_virtual_method: DmVirtualMethod) {
self.virtual_methods.push(dm_virtual_method); self.virtual_methods.push(Rc::new(dm_virtual_method));
} }
pub fn virtual_methods(&self) -> &Vec<DmVirtualMethod> { pub fn get_method(&self, name: &str, self_object: &DvmObject) -> Option<Rc<DmMethod>> {
&self.virtual_methods if self
.virtual_methods
.iter()
.find(|&dm_fn| dm_fn.fqn == name)
.is_some()
{
return self_object.implementation().get_method(name, self_object);
}
None
}
pub fn get_virtual_methods(&self) -> Vec<Rc<DmVirtualMethod>> {
self.virtual_methods.clone()
}
pub fn get_property(&self, name: &str, self_object: &DvmObject) -> Option<&DmProperty> {
todo!()
} }
} }
#[derive(Debug, Eq)] #[derive(Debug, Eq)]
pub struct DmVirtualMethod { pub struct DmVirtualMethod {
fqn: String, pub fqn: String,
short_name: String, pub short_name: String,
} }
impl PartialEq for DmVirtualMethod { impl PartialEq for DmVirtualMethod {
@ -142,31 +164,14 @@ impl PartialEq for DmVirtualMethod {
} }
} }
impl DmVirtualMethod {
pub fn new(fqn: &str, short_name: &str) -> Self {
DmVirtualMethod {
fqn: fqn.to_string(),
short_name: short_name.to_string(),
}
}
pub fn fqn(&self) -> &str {
self.fqn.as_str()
}
pub fn short_name(&self) -> &str {
self.short_name.as_str()
}
}
#[derive(Debug, Eq)] #[derive(Debug, Eq)]
pub struct DmImplementation { pub struct DmImplementation {
fqn: String, pub fqn: String,
short_name: String, pub short_name: String,
interface: Option<Rc<DmInterface>>, pub interface: Option<Rc<DmInterface>>,
functions: Vec<Rc<DmFn>>, pub functions: Vec<Rc<DmFn>>,
methods: Vec<Rc<DmMethod>>, pub methods: Vec<Rc<DmMethod>>,
fields: Vec<DmField>, pub fields: Vec<DmField>,
} }
impl PartialEq for DmImplementation { impl PartialEq for DmImplementation {
@ -187,60 +192,45 @@ impl DmImplementation {
} }
} }
pub fn fqn(&self) -> &str {
self.fqn.as_str()
}
pub fn short_name(&self) -> &str {
self.short_name.as_str()
}
pub fn interface(&self) -> Option<Rc<DmInterface>> { pub fn interface(&self) -> Option<Rc<DmInterface>> {
self.interface.clone() self.interface.clone()
} }
pub fn functions(&self) -> &Vec<Rc<DmFn>> { pub fn get_method(&self, name: &str, self_object: &DvmObject) -> Option<Rc<DmMethod>> {
&self.functions
}
pub fn add_function(&mut self, dm_fn: DmFn) {
self.functions.push(Rc::new(dm_fn));
}
pub fn methods(&self) -> &Vec<Rc<DmMethod>> {
&self.methods
}
pub fn add_method(&mut self, dm_method: DmMethod) {
self.methods.push(Rc::new(dm_method));
}
pub fn find_method(&self, name: &str, self_object: &DvmObject) -> Option<&DmMethod> {
for method in &self.methods { for method in &self.methods {
if method.dm_fn.fqn == name { if method.dm_fn.fqn == name {
return Some(method); return Some(method.clone());
} else if let Some(implements) = &method.implements { } else if let Some(implements) = &method.implements {
if implements.fqn == name { if implements.fqn == name {
return Some(method); return Some(method.clone());
} }
} }
} }
None None
} }
pub fn fields(&self) -> &Vec<DmField> { pub fn get_property(&self, name: &str, self_object: &DvmObject) -> Option<Rc<DmProperty>> {
&self.fields todo!()
} }
pub fn add_field(&mut self, dm_field: DmField) { pub fn get_field(&self, name: &str, self_object: &DvmObject) -> Option<&DmField> {
self.fields.push(dm_field);
}
pub fn find_field(&self, name: &str, self_object: &DvmObject) -> Option<&DmField> {
self.fields.iter().find(|field| field.name == name) self.fields.iter().find(|field| field.name == name)
} }
} }
#[derive(Debug, Eq)]
pub struct DmProperty {
pub name: String,
pub data_offset: usize,
pub primitive_type: Rc<DmType>,
}
impl PartialEq for DmProperty {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
#[derive(Debug, Eq)] #[derive(Debug, Eq)]
pub struct DmField { pub struct DmField {
name: String, name: String,

View File

@ -35,7 +35,7 @@ fn get_string(dvm_value: &DvmValue) -> String {
} }
fn object_to_string(alloc_object_rc: Rc<DvmObject>) -> String { fn object_to_string(alloc_object_rc: Rc<DvmObject>) -> String {
if alloc_object_rc.implementation().fqn() == "std::core::StringImpl" { if alloc_object_rc.implementation().fqn == "std::core::StringImpl" {
extract_string_from_string(alloc_object_rc.clone()) extract_string_from_string(alloc_object_rc.clone())
} else { } else {
todo!("what happens if we don't have a String?") todo!("what happens if we don't have a String?")
@ -44,7 +44,7 @@ fn object_to_string(alloc_object_rc: Rc<DvmObject>) -> String {
fn extract_string_from_string(string_object: Rc<DvmObject>) -> String { fn extract_string_from_string(string_object: Rc<DvmObject>) -> String {
let bytes_object = read_field_by_name("bytes", &string_object).expect_object(); let bytes_object = read_field_by_name("bytes", &string_object).expect_object();
if bytes_object.implementation().fqn() != "std::core::ArrayImpl" { if bytes_object.implementation().fqn != "std::core::ArrayImpl" {
panic!("String.bytes field is not a std::core::ArrayImpl"); panic!("String.bytes field is not a std::core::ArrayImpl");
} }

27
src/vm/pointer.rs Normal file
View File

@ -0,0 +1,27 @@
use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Eq)]
pub struct DvmPointer {
address: *mut u8,
size: usize,
}
impl DvmPointer {
pub fn new(address: *mut u8, size: usize) -> DvmPointer {
DvmPointer { address, size }
}
pub fn address(&self) -> *mut u8 {
self.address
}
pub fn size(&self) -> usize {
self.size
}
}
impl Display for DvmPointer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("0x{:x}", self.address as usize))
}
}