Clean up of references and Rcs; better information hiding.

This commit is contained in:
Jesse Brault 2024-12-30 16:27:13 -06:00
parent 68553a756b
commit fc9cfcdf7c
6 changed files with 132 additions and 107 deletions

View File

@ -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

View File

@ -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![]);

View File

@ -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

View File

@ -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)]

View File

@ -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);

View File

@ -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);
}
}
}