Clean up of references and Rcs; better information hiding.
This commit is contained in:
parent
68553a756b
commit
fc9cfcdf7c
@ -59,7 +59,7 @@ mov_usize(
|
||||
)
|
||||
----
|
||||
|
||||
Unlike most other operand types, this operand remains unsigned at runtime.
|
||||
Unlike the other numerical operand types, this operand remains unsigned at runtime.
|
||||
|
||||
=== Move Double
|
||||
|
||||
@ -91,7 +91,7 @@ The operand is converted to a `bool` at runtime by the virtual machine.
|
||||
|
||||
=== Move Register
|
||||
|
||||
Moves or copies (see below) the value in one register to another.
|
||||
Copies the value in one register to another.
|
||||
|
||||
[source]
|
||||
----
|
||||
@ -101,9 +101,6 @@ 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
|
||||
|
||||
Loads the target register with the `DvmValue` inner value stored in the field at `field_index` in the object in the
|
||||
|
@ -19,7 +19,12 @@ fn main() {
|
||||
|
||||
// std::core::Array
|
||||
let array_int = DmInterface::new("std::core::Array", "Array");
|
||||
let array_int_rc = Rc::new(array_int);
|
||||
array_lib.add_interface(array_int);
|
||||
let array_int_rc = array_lib
|
||||
.interfaces()
|
||||
.iter()
|
||||
.find(|interface| interface.fqn() == "std::core::Array")
|
||||
.unwrap();
|
||||
|
||||
// std::core::ArrayImpl
|
||||
let mut array_impl = DmImplementation::new(
|
||||
@ -58,17 +63,24 @@ fn main() {
|
||||
let array_impl_ctor_0_method = DmMethod::new(array_impl_ctor_0_fn, None);
|
||||
array_impl.add_method(array_impl_ctor_0_method);
|
||||
|
||||
// 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());
|
||||
array_lib.add_implementation(array_impl);
|
||||
|
||||
// std::core::String
|
||||
let mut string_lib = DmLib::new("std/core/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("std::core::StringImpl", "StringImpl", None);
|
||||
let mut string_impl = DmImplementation::new(
|
||||
"std::core::StringImpl",
|
||||
"StringImpl",
|
||||
Some(string_int_rc.clone()),
|
||||
);
|
||||
|
||||
let bytes_field = DmField::new("bytes", DmType::Object);
|
||||
string_impl.add_field(bytes_field);
|
||||
@ -92,14 +104,11 @@ fn main() {
|
||||
|
||||
string_impl.add_method(string_ctor_0_method);
|
||||
|
||||
string_lib.interfaces.push(Rc::new(string_int));
|
||||
string_lib.implementations.push(Rc::new(string_impl));
|
||||
string_lib.add_implementation(string_impl);
|
||||
|
||||
// greeting lib
|
||||
let mut greeting_lib = DmLib::new("greeting");
|
||||
greeting_lib
|
||||
.constants
|
||||
.push(DmConstant::String("Hello, Jeanna!".to_string()));
|
||||
greeting_lib.add_constant(DmConstant::String("Hello, World!".to_string()));
|
||||
|
||||
let mut main_byte_code = Vec::new();
|
||||
|
||||
@ -141,7 +150,7 @@ fn main() {
|
||||
|
||||
let main_dm_fn = DmFn::new("main", "main", main_byte_code, 7, None);
|
||||
|
||||
greeting_lib.functions.push(Rc::new(main_dm_fn));
|
||||
greeting_lib.add_function(main_dm_fn);
|
||||
|
||||
let mut state = DvmState::new();
|
||||
let mut context = DvmContext::new();
|
||||
@ -150,7 +159,7 @@ fn main() {
|
||||
Rc::new(string_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();
|
||||
call_fn(&mut state, &context, &main_fn, vec![]);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::vm::object::DvmObject;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum DvmValue {
|
||||
Byte(u8),
|
||||
Int(i32),
|
||||
@ -15,6 +15,10 @@ pub enum DvmValue {
|
||||
}
|
||||
|
||||
impl DvmValue {
|
||||
pub fn from_object(object: DvmObject) -> Self {
|
||||
DvmValue::Object(Rc::new(object))
|
||||
}
|
||||
|
||||
pub fn expect_long(&self) -> i64 {
|
||||
if let DvmValue::Long(l) = self {
|
||||
*l
|
||||
|
@ -7,11 +7,11 @@ use crate::vm::object_type::{DmFn, DmImplementation, DmInterface};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct DmLib {
|
||||
pub name: String,
|
||||
pub constants: Vec<DmConstant>,
|
||||
pub interfaces: Vec<Rc<DmInterface>>,
|
||||
pub implementations: Vec<Rc<DmImplementation>>,
|
||||
pub functions: Vec<Rc<DmFn>>,
|
||||
name: String,
|
||||
constants: Vec<DmConstant>,
|
||||
interfaces: Vec<Rc<DmInterface>>,
|
||||
implementations: Vec<Rc<DmImplementation>>,
|
||||
functions: Vec<Rc<DmFn>>,
|
||||
}
|
||||
|
||||
impl DmLib {
|
||||
@ -24,6 +24,42 @@ impl DmLib {
|
||||
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)]
|
||||
|
@ -34,70 +34,66 @@ struct CallFrameInfo {
|
||||
|
||||
pub struct DvmContext {
|
||||
libs: Vec<Rc<DmLib>>,
|
||||
functions: HashMap<String, Rc<DmFn>>,
|
||||
platform_functions: HashMap<String, Rc<PlatformFunction>>,
|
||||
function_cache: HashMap<String, Rc<DmFn>>,
|
||||
platform_functions: HashMap<String, PlatformFunction>,
|
||||
}
|
||||
|
||||
impl DvmContext {
|
||||
pub fn new() -> Self {
|
||||
DvmContext {
|
||||
libs: Vec::new(),
|
||||
functions: HashMap::new(),
|
||||
function_cache: HashMap::new(),
|
||||
platform_functions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_libs(&mut self, libs: Vec<Rc<DmLib>>) {
|
||||
for lib in libs {
|
||||
self.libs.push(lib.clone());
|
||||
for lib_fn in &lib.functions {
|
||||
self.functions
|
||||
for lib_fn in lib.functions() {
|
||||
self.function_cache
|
||||
.insert(lib_fn.fqn().to_string(), lib_fn.clone());
|
||||
}
|
||||
for interface_function in lib
|
||||
.interfaces
|
||||
.interfaces()
|
||||
.iter()
|
||||
.flat_map(|interface| interface.get_functions())
|
||||
.flat_map(|interface| interface.functions())
|
||||
{
|
||||
self.functions.insert(
|
||||
self.function_cache.insert(
|
||||
interface_function.fqn().to_string(),
|
||||
interface_function.clone(),
|
||||
);
|
||||
}
|
||||
for implementation_function in lib
|
||||
.implementations
|
||||
.implementations()
|
||||
.iter()
|
||||
.flat_map(|implementation| implementation.functions())
|
||||
{
|
||||
self.functions.insert(
|
||||
self.function_cache.insert(
|
||||
implementation_function.fqn().to_string(),
|
||||
implementation_function.clone(),
|
||||
);
|
||||
}
|
||||
for method in lib
|
||||
.implementations
|
||||
.implementations()
|
||||
.iter()
|
||||
.flat_map(|implementation| implementation.methods())
|
||||
{
|
||||
self.functions
|
||||
.insert(method.dm_fn().fqn().to_string(), method.dm_fn().clone());
|
||||
self.function_cache
|
||||
.insert(method.dm_fn().fqn().to_string(), method.dm_fn());
|
||||
}
|
||||
self.libs.push(lib);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_platform_fns(&mut self, platform_fns: &HashMap<String, PlatformFunction>) {
|
||||
for (fqn, platform_fn) in platform_fns {
|
||||
pub fn load_platform_fns(&mut self, platform_fns: HashMap<String, PlatformFunction>) {
|
||||
platform_fns.iter().for_each(|(fqn, platform_function)| {
|
||||
self.platform_functions
|
||||
.insert(fqn.to_string(), Rc::new(*platform_fn));
|
||||
}
|
||||
.insert(fqn.to_string(), *platform_function);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn fn_by_fqn(&self, fqn: &str) -> Option<Rc<DmFn>> {
|
||||
self.functions.get(fqn).cloned()
|
||||
}
|
||||
|
||||
pub fn platform_fn_by_fqn(&self, fqn: &str) -> Option<Rc<PlatformFunction>> {
|
||||
self.platform_functions.get(fqn).cloned()
|
||||
self.function_cache.get(fqn).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,8 +277,9 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
MOV_REGISTER => {
|
||||
let target_register = next_8!(iter, usize);
|
||||
let source_register = next_8!(iter, usize);
|
||||
let source_value = state.registers.get(source_register).unwrap();
|
||||
state.registers[target_register] = source_value.clone();
|
||||
let source_value =
|
||||
std::mem::replace(&mut state.registers[source_register], DvmValue::Uninit);
|
||||
state.registers[target_register] = source_value;
|
||||
}
|
||||
LOAD => {
|
||||
let target_register = next_8!(iter, usize);
|
||||
@ -321,25 +318,24 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
.libs
|
||||
.iter()
|
||||
.find_map(|lib| {
|
||||
lib.implementations
|
||||
lib.implementations()
|
||||
.iter()
|
||||
.find(|implementation| implementation.fqn() == impl_name)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
dvm_panic!(&format!("Implementation not found: {}", impl_name), state)
|
||||
});
|
||||
})
|
||||
.clone();
|
||||
|
||||
let dm_alloc_object = DvmObject::new(implementation.clone());
|
||||
state.registers[target_register] = DvmValue::Object(Rc::new(dm_alloc_object));
|
||||
let dm_alloc_object = DvmObject::new(implementation);
|
||||
state.registers[target_register] = DvmValue::from_object(dm_alloc_object);
|
||||
}
|
||||
DEALLOC => {
|
||||
let target_register = next_8!(iter, usize);
|
||||
let dvm_object = state
|
||||
.registers
|
||||
.get(target_register)
|
||||
.unwrap()
|
||||
.expect_object();
|
||||
drop(dvm_object); // explicit
|
||||
let target_object =
|
||||
std::mem::replace(&mut state.registers[target_register], DvmValue::Uninit)
|
||||
.expect_object();
|
||||
drop(target_object); // explicit
|
||||
state.registers[target_register] = DvmValue::Uninit;
|
||||
}
|
||||
MOV_CONST => {
|
||||
@ -350,13 +346,13 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
let const_id = next_32_le!(iter, usize);
|
||||
|
||||
// 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!(
|
||||
&format!("Could not find lib with name: {}", lib_name),
|
||||
state
|
||||
);
|
||||
};
|
||||
let constant = lib.constants.get(const_id).unwrap();
|
||||
let constant = lib.constants().get(const_id).unwrap();
|
||||
let DmConstant::String(s) = constant;
|
||||
let pointer = s.as_ptr();
|
||||
|
||||
@ -404,11 +400,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
args.push(value.clone());
|
||||
}
|
||||
|
||||
let platform_function = context
|
||||
.platform_functions
|
||||
.get(&symbol_name)
|
||||
.unwrap()
|
||||
.clone();
|
||||
let platform_function = context.platform_functions.get(&symbol_name).unwrap();
|
||||
state
|
||||
.call_stack
|
||||
.push(CallFrame::PlatformCall(CallFrameInfo { fqn: symbol_name }));
|
||||
@ -427,7 +419,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
||||
args.push(value.clone());
|
||||
}
|
||||
|
||||
let dm_fn = context.functions.get(&symbol_name).unwrap();
|
||||
let dm_fn = context.function_cache.get(&symbol_name).unwrap();
|
||||
let call_result = call_fn(state, context, dm_fn, args);
|
||||
state.registers[return_register] = call_result;
|
||||
}
|
||||
@ -481,14 +473,11 @@ mod run_code_tests {
|
||||
|
||||
macro_rules! assert_register {
|
||||
( $expected: expr, $state: expr, $register_number: expr ) => {
|
||||
assert_eq!(
|
||||
$expected,
|
||||
$state.registers.get($register_number).unwrap().clone()
|
||||
);
|
||||
assert_eq!($expected, $state.registers.remove($register_number));
|
||||
};
|
||||
}
|
||||
|
||||
fn setup(number_of_registers: usize) -> (DvmState, DvmContext) {
|
||||
fn setup<'a>(number_of_registers: usize) -> (DvmState, DvmContext) {
|
||||
let mut state = DvmState::new();
|
||||
state
|
||||
.registers
|
||||
@ -543,13 +532,17 @@ mod run_code_tests {
|
||||
#[test]
|
||||
fn load_object() {
|
||||
let dummy_impl = impl_with_object_field();
|
||||
let dummy_impl_rc = Rc::new(dummy_impl);
|
||||
let mut dummy_lib = DmLib::new("dummy");
|
||||
dummy_lib.implementations.push(dummy_impl_rc.clone());
|
||||
dummy_lib.add_implementation(dummy_impl);
|
||||
let dummy_impl_ref = dummy_lib
|
||||
.implementations()
|
||||
.iter()
|
||||
.find(|implementation| implementation.fqn() == "dummy")
|
||||
.unwrap();
|
||||
|
||||
let mut code = Vec::new();
|
||||
add_alloc(&mut code, 0, &dummy_impl_rc.fqn());
|
||||
add_alloc(&mut code, 1, &dummy_impl_rc.fqn());
|
||||
add_alloc(&mut code, 0, dummy_impl_ref.fqn());
|
||||
add_alloc(&mut code, 1, dummy_impl_ref.fqn());
|
||||
add_store(&mut code, 0, 0, 1);
|
||||
add_load(&mut code, 2, 0, 0);
|
||||
|
||||
|
@ -3,12 +3,6 @@ use crate::vm::object::DvmObject;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmObjectType {
|
||||
Interface(DmInterface),
|
||||
Implementation(DmImplementation),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmFn {
|
||||
fqn: String,
|
||||
@ -92,7 +86,7 @@ pub struct DmInterface {
|
||||
fqn: String,
|
||||
short_name: String,
|
||||
functions: Vec<Rc<DmFn>>,
|
||||
virtual_methods: Vec<Rc<DmVirtualMethod>>,
|
||||
virtual_methods: Vec<DmVirtualMethod>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmInterface {
|
||||
@ -123,28 +117,16 @@ impl DmInterface {
|
||||
self.functions.push(Rc::new(dm_fn));
|
||||
}
|
||||
|
||||
pub fn get_functions(&self) -> Vec<Rc<DmFn>> {
|
||||
self.functions.clone()
|
||||
pub fn functions(&self) -> &Vec<Rc<DmFn>> {
|
||||
&self.functions
|
||||
}
|
||||
|
||||
pub fn add_method(&mut self, dm_virtual_method: DmVirtualMethod) {
|
||||
self.virtual_methods.push(Rc::new(dm_virtual_method));
|
||||
self.virtual_methods.push(dm_virtual_method);
|
||||
}
|
||||
|
||||
pub fn get_method(&self, name: &str, self_object: &DvmObject) -> Option<Rc<DmMethod>> {
|
||||
if self
|
||||
.virtual_methods
|
||||
.iter()
|
||||
.find(|&dm_fn| dm_fn.fqn == name)
|
||||
.is_some()
|
||||
{
|
||||
return self_object.implementation().find_method(name, self_object);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_virtual_methods(&self) -> Vec<Rc<DmVirtualMethod>> {
|
||||
self.virtual_methods.clone()
|
||||
pub fn virtual_methods(&self) -> &Vec<DmVirtualMethod> {
|
||||
&self.virtual_methods
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,25 +199,29 @@ impl DmImplementation {
|
||||
self.interface.clone()
|
||||
}
|
||||
|
||||
pub fn functions(&self) -> Vec<Rc<DmFn>> {
|
||||
self.functions.clone()
|
||||
pub fn functions(&self) -> &Vec<Rc<DmFn>> {
|
||||
&self.functions
|
||||
}
|
||||
|
||||
pub fn methods(&self) -> Vec<Rc<DmMethod>> {
|
||||
self.methods.clone()
|
||||
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<Rc<DmMethod>> {
|
||||
pub fn find_method(&self, name: &str, self_object: &DvmObject) -> Option<&DmMethod> {
|
||||
for method in &self.methods {
|
||||
if method.dm_fn.fqn == name {
|
||||
return Some(method.clone());
|
||||
return Some(method);
|
||||
} else if let Some(implements) = &method.implements {
|
||||
if implements.fqn == name {
|
||||
return Some(method.clone());
|
||||
return Some(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user