Attempt to implement runtime types.
This commit is contained in:
parent
9bc27b841b
commit
7903c1cfb3
@ -5,7 +5,7 @@ fn main() {
|
|||||||
let mut code: Vec<u8> = Vec::new();
|
let mut code: Vec<u8> = Vec::new();
|
||||||
add_mov_int(&mut code, 0, 42);
|
add_mov_int(&mut code, 0, 42);
|
||||||
add_platform_call_to(&mut code, &String::from("std::core::print"), 0, 1, &vec![0u8]);
|
add_platform_call_to(&mut code, &String::from("std::core::print"), 0, 1, &vec![0u8]);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&mut code);
|
vm.run(&mut code);
|
||||||
println!()
|
println!()
|
||||||
}
|
}
|
78
src/vm/mem.rs
Normal file
78
src/vm/mem.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use crate::vm::types::{DmImplementation, DmProperty, DmType};
|
||||||
|
use crate::vm::values::DmValue;
|
||||||
|
use std::alloc::Layout;
|
||||||
|
|
||||||
|
pub struct DmAllocObject<'a> {
|
||||||
|
pub data: *mut u8,
|
||||||
|
pub size: usize,
|
||||||
|
pub layout: Layout,
|
||||||
|
pub object_type: &'a DmImplementation<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_property_value(dm_property: &DmProperty, dm_property_object: &DmAllocObject) -> DmValue {
|
||||||
|
let mut data: Vec<u8> = Vec::with_capacity(dm_property.dm_type.size_in_bytes());
|
||||||
|
for i in dm_property.data_offset..(dm_property.data_offset + dm_property.dm_type.size_in_bytes()) {
|
||||||
|
data.push(dm_property_object.data.offset(i as isize).read());
|
||||||
|
}
|
||||||
|
match dm_property.dm_type {
|
||||||
|
DmType::Byte => {
|
||||||
|
DmValue::DmByte(data[0])
|
||||||
|
}
|
||||||
|
DmType::Int => {
|
||||||
|
DmValue::DmInt(i32::from_ne_bytes(data[0..4].try_into().unwrap()))
|
||||||
|
}
|
||||||
|
DmType::Long => {
|
||||||
|
DmValue::DmLong(i64::from_ne_bytes(data[0..8].try_into().unwrap()))
|
||||||
|
}
|
||||||
|
DmType::Double => {
|
||||||
|
DmValue::DmDouble(f64::from_ne_bytes(data[0..8].try_into().unwrap()))
|
||||||
|
}
|
||||||
|
DmType::Boolean => {
|
||||||
|
DmValue::DmBoolean(i32::from_ne_bytes(data[0..4].try_into().unwrap()) != 0)
|
||||||
|
}
|
||||||
|
DmType::ObjectPointer(_) => {
|
||||||
|
DmValue::DmPointer(usize::from_ne_bytes(data[0..8].try_into().unwrap()) as *mut DmAllocObject)
|
||||||
|
}
|
||||||
|
DmType::ByteArray(_) => {
|
||||||
|
DmValue::DmByteArray(data)
|
||||||
|
}
|
||||||
|
DmType::IntArray(length) => {
|
||||||
|
let mut result = Vec::with_capacity(length);
|
||||||
|
for i in 0..length {
|
||||||
|
result.push(i32::from_ne_bytes(data[(i * 4)..(i * 4 + 4)].try_into().unwrap()));
|
||||||
|
}
|
||||||
|
DmValue::DmIntArray(result)
|
||||||
|
}
|
||||||
|
DmType::LongArray(length) => {
|
||||||
|
let mut result = Vec::with_capacity(length);
|
||||||
|
for i in 0..length {
|
||||||
|
result.push(i64::from_ne_bytes(data[i * 8..(i * 8 + 8)].try_into().unwrap()));
|
||||||
|
}
|
||||||
|
DmValue::DmLongArray(result)
|
||||||
|
}
|
||||||
|
DmType::DoubleArray(length) => {
|
||||||
|
let mut result = Vec::with_capacity(length);
|
||||||
|
for i in 0..length {
|
||||||
|
result.push(f64::from_ne_bytes(data[i * 8..(i * 8 + 8)].try_into().unwrap()));
|
||||||
|
}
|
||||||
|
DmValue::DmDoubleArray(result)
|
||||||
|
}
|
||||||
|
DmType::BooleanArray(length) => {
|
||||||
|
let mut result = Vec::with_capacity(length);
|
||||||
|
for i in 0..length {
|
||||||
|
result.push(i32::from_ne_bytes(data[(i * 4)..(i * 4 + 4)].try_into().unwrap()) != 0);
|
||||||
|
}
|
||||||
|
DmValue::DmBooleanArray(result)
|
||||||
|
}
|
||||||
|
DmType::ObjectPointerArray(length, _) => {
|
||||||
|
let mut result = Vec::with_capacity(length);
|
||||||
|
for i in 0..length {
|
||||||
|
result.push(usize::from_ne_bytes(data[(i * 8)..(i * 8 + 8)].try_into().unwrap()) as *mut DmAllocObject);
|
||||||
|
}
|
||||||
|
DmValue::DmPointerArray(result)
|
||||||
|
}
|
||||||
|
DmType::Unit => {
|
||||||
|
DmValue::DmUnit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,13 +4,15 @@ pub mod platform;
|
|||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod values;
|
pub mod values;
|
||||||
|
mod mem;
|
||||||
|
|
||||||
use crate::vm::module::DmFunction;
|
use crate::vm::mem::DmAllocObject;
|
||||||
|
use crate::vm::module::DmModule;
|
||||||
use crate::vm::platform::init_platform_functions;
|
use crate::vm::platform::init_platform_functions;
|
||||||
|
use crate::vm::types::{DmFn, DmImplementation};
|
||||||
use op_codes::*;
|
use op_codes::*;
|
||||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Index;
|
|
||||||
use types::DmType;
|
use types::DmType;
|
||||||
use util::{get_32_le, get_64_le};
|
use util::{get_32_le, get_64_le};
|
||||||
use values::DmValue;
|
use values::DmValue;
|
||||||
@ -25,15 +27,15 @@ enum CallFrame {
|
|||||||
|
|
||||||
pub struct PlatformCallFrame {
|
pub struct PlatformCallFrame {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub args: Vec<u64>,
|
pub args: Vec<DmValue>,
|
||||||
pub arg_types: Vec<DmType>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DeimosCallFrame {
|
struct DeimosCallFrame {
|
||||||
return_address: usize,
|
return_address: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DmVirtualMachine {
|
pub struct DmVirtualMachine<'a> {
|
||||||
|
modules: Vec<DmModule<'a>>,
|
||||||
platform_functions: HashMap<String, PlatformFunction>,
|
platform_functions: HashMap<String, PlatformFunction>,
|
||||||
ip: usize,
|
ip: usize,
|
||||||
call_stack: Vec<CallFrame>,
|
call_stack: Vec<CallFrame>,
|
||||||
@ -41,9 +43,10 @@ pub struct DmVirtualMachine {
|
|||||||
register_state_stack: Vec<Vec<DmValue>>,
|
register_state_stack: Vec<Vec<DmValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmVirtualMachine {
|
impl DmVirtualMachine<'_> {
|
||||||
pub fn new() -> DmVirtualMachine {
|
pub fn new(modules: Vec<DmModule>) -> DmVirtualMachine {
|
||||||
DmVirtualMachine {
|
DmVirtualMachine {
|
||||||
|
modules,
|
||||||
ip: 0,
|
ip: 0,
|
||||||
registers: Vec::new(),
|
registers: Vec::new(),
|
||||||
platform_functions: init_platform_functions(),
|
platform_functions: init_platform_functions(),
|
||||||
@ -54,7 +57,7 @@ impl DmVirtualMachine {
|
|||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
dm_function: &DmFunction,
|
dm_function: &DmFn,
|
||||||
args: Vec<DmValue>,
|
args: Vec<DmValue>,
|
||||||
) -> DmValue {
|
) -> DmValue {
|
||||||
// save current state
|
// save current state
|
||||||
@ -110,15 +113,36 @@ impl DmVirtualMachine {
|
|||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
ALLOC => {
|
ALLOC => {
|
||||||
let target_register = code[i + 1] as usize;
|
i += 1;
|
||||||
let size = get_32_le!(code, i, 2, usize);
|
let target_register = code[i] as usize;
|
||||||
|
i += 1;
|
||||||
|
let symbol_name_length = get_32_le!(code, i, 0, usize);
|
||||||
|
i += 4;
|
||||||
|
let raw_symbol_name = code[i..(i + symbol_name_length)].to_vec();
|
||||||
|
i += symbol_name_length;
|
||||||
|
let symbol_name = String::from_utf8(raw_symbol_name).unwrap();
|
||||||
|
|
||||||
|
// find implementation
|
||||||
|
let mut implementation_result: Option<&DmImplementation> = None;
|
||||||
|
'module_find: for module in self.modules.iter() {
|
||||||
|
if let Some(dm_implementation) = module.implementations.get(&symbol_name) {
|
||||||
|
implementation_result = Some(dm_implementation);
|
||||||
|
break 'module_find;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if implementation_result == None {
|
||||||
|
panic!("Implementation {} not found", symbol_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dm_implementation = implementation_result.unwrap();
|
||||||
|
let size = dm_implementation.size_in_bytes;
|
||||||
let layout = Layout::from_size_align(size, 4).unwrap();
|
let layout = Layout::from_size_align(size, 4).unwrap();
|
||||||
let pointer = unsafe { alloc_zeroed(layout) };
|
let pointer = unsafe { alloc_zeroed(layout) };
|
||||||
let dm_object = Box::new(DmObject {
|
let dm_object = Box::new(DmAllocObject {
|
||||||
|
object_type: dm_implementation,
|
||||||
data: pointer,
|
data: pointer,
|
||||||
size,
|
size,
|
||||||
layout,
|
layout,
|
||||||
object_type: todo!(),
|
|
||||||
});
|
});
|
||||||
let dm_object_pointer = Box::into_raw(dm_object);
|
let dm_object_pointer = Box::into_raw(dm_object);
|
||||||
self.registers.insert(target_register, DmPointer(dm_object_pointer));
|
self.registers.insert(target_register, DmPointer(dm_object_pointer));
|
||||||
@ -201,30 +225,6 @@ impl DmVirtualMachine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DmObjectType {
|
|
||||||
name: String,
|
|
||||||
properties: HashMap<String, DmObjectProperty>,
|
|
||||||
fields: HashMap<String, DmObjectField>,
|
|
||||||
methods: HashMap<String, DmFunction>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DmObject {
|
|
||||||
object_type: Box<DmObjectType>,
|
|
||||||
data: *mut u8,
|
|
||||||
size: usize,
|
|
||||||
layout: Layout,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DmObjectProperty {
|
|
||||||
name: String,
|
|
||||||
property_type: DmType,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DmObjectField {
|
|
||||||
name: String,
|
|
||||||
field_type: DmType,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod dvm_run_tests {
|
mod dvm_run_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -240,7 +240,7 @@ mod dvm_run_tests {
|
|||||||
fn mov_1_as_int() {
|
fn mov_1_as_int() {
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_mov_int(&mut code, 0, 1);
|
add_mov_int(&mut code, 0, 1);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
assert_register!(DmInt(1), vm.registers.get(0));
|
assert_register!(DmInt(1), vm.registers.get(0));
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ mod dvm_run_tests {
|
|||||||
fn move_65535_as_int() {
|
fn move_65535_as_int() {
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_mov_int(&mut code, 0, 0xffff);
|
add_mov_int(&mut code, 0, 0xffff);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
assert_register!(DmInt(0xffff), vm.registers.get(0));
|
assert_register!(DmInt(0xffff), vm.registers.get(0));
|
||||||
}
|
}
|
||||||
@ -258,7 +258,7 @@ mod dvm_run_tests {
|
|||||||
fn move_int_max_as_int() {
|
fn move_int_max_as_int() {
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_mov_int(&mut code, 0, 0x0fff_ffff);
|
add_mov_int(&mut code, 0, 0x0fff_ffff);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
assert_register!(DmInt(0x0fff_ffff), vm.registers.get(0));
|
assert_register!(DmInt(0x0fff_ffff), vm.registers.get(0));
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ mod dvm_run_tests {
|
|||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_mov_int(&mut code, 1, 1);
|
add_mov_int(&mut code, 1, 1);
|
||||||
add_mov_register(&mut code, 0, 1);
|
add_mov_register(&mut code, 0, 1);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.registers.resize(2, DmUnit);
|
vm.registers.resize(2, DmUnit);
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
assert_register!(DmInt(1), vm.registers.get(0));
|
assert_register!(DmInt(1), vm.registers.get(0));
|
||||||
@ -280,7 +280,7 @@ mod dvm_run_tests {
|
|||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_alloc(&mut code, 0, 4);
|
add_alloc(&mut code, 0, 4);
|
||||||
add_mov_int_to(&mut code, 0, 0, 0xff);
|
add_mov_int_to(&mut code, 0, 0, 0xff);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
let box_address = vm.registers.get(0).unwrap().clone();
|
let box_address = vm.registers.get(0).unwrap().clone();
|
||||||
match box_address {
|
match box_address {
|
||||||
@ -299,7 +299,7 @@ mod dvm_run_tests {
|
|||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
add_alloc(&mut code, 0, 4);
|
add_alloc(&mut code, 0, 4);
|
||||||
add_dealloc(&mut code, 0);
|
add_dealloc(&mut code, 0);
|
||||||
let mut vm = DmVirtualMachine::new();
|
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||||
vm.run(&code);
|
vm.run(&code);
|
||||||
assert_register!(DmUnit, vm.registers.get(0));
|
assert_register!(DmUnit, vm.registers.get(0));
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
use crate::get_32_le;
|
use crate::get_32_le;
|
||||||
|
use crate::vm::types::{DmFn, DmImplementation, DmInterface};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
pub const DEIMOS_MAGIC_NUMBER: u64 = 0x00_00_64_65_69_6d_6f_73; // ascii 'deimos'
|
pub const DEIMOS_MAGIC_NUMBER: u64 = 0x00_00_64_65_69_6d_6f_73; // ascii 'deimos'
|
||||||
const DEIMOS_MAGIC_STRING: [u8; 6] = [0x64, 0x65, 0x69, 0x6d, 0x6f, 0x73]; // ascii 'deimos'
|
pub const DEIMOS_MAGIC_STRING: [u8; 6] = [0x64, 0x65, 0x69, 0x6d, 0x6f, 0x73]; // ascii 'deimos'
|
||||||
|
|
||||||
pub const VERSION_STRING: &str = "0.1.0";
|
pub const COMPILER_VERSION_STRING: &str = "0.1.0";
|
||||||
|
|
||||||
pub struct DmModule {
|
pub struct DmModule<'a> {
|
||||||
name: String,
|
pub compiler_version: String,
|
||||||
version: String,
|
pub fqn: String,
|
||||||
constants: HashMap<String, DmConstant>,
|
pub short_name: String,
|
||||||
functions: HashMap<String, DmFunction>,
|
pub constants: HashMap<String, DmConstant>,
|
||||||
|
pub interfaces: HashMap<String, DmInterface<'a>>,
|
||||||
|
pub implementations: HashMap<String, DmImplementation<'a>>,
|
||||||
|
pub functions: HashMap<String, DmFn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DmConstant {
|
pub enum DmConstant {
|
||||||
@ -21,12 +24,6 @@ pub enum DmConstant {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DmFunction {
|
|
||||||
pub name: String,
|
|
||||||
pub byte_code: Vec<u8>,
|
|
||||||
pub num_registers: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
const CONST_SYMBOL: u8 = 0x01;
|
const CONST_SYMBOL: u8 = 0x01;
|
||||||
const FUNCTION_SYMBOL: u8 = 0x02;
|
const FUNCTION_SYMBOL: u8 = 0x02;
|
||||||
|
|
||||||
@ -74,10 +71,10 @@ pub fn write_module(module: DmModule) -> Vec<u8> {
|
|||||||
push_byte_array!(result, DEIMOS_MAGIC_STRING);
|
push_byte_array!(result, DEIMOS_MAGIC_STRING);
|
||||||
|
|
||||||
// Push version string
|
// Push version string
|
||||||
push_string!(result, module.version);
|
push_string!(result, module.compiler_version);
|
||||||
|
|
||||||
// Push module name length, little endian
|
// Push module name length, little endian
|
||||||
push_string!(result, module.name);
|
push_string!(result, module.fqn);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,5 @@
|
|||||||
use crate::vm::module::DmFunction;
|
|
||||||
use crate::vm::DmValue::*;
|
use crate::vm::DmValue::*;
|
||||||
use crate::vm::{DmObject, DmValue, DmVirtualMachine};
|
use crate::vm::{mem, DmValue, DmVirtualMachine};
|
||||||
|
|
||||||
fn get_method<'a>(ptr: *mut DmObject, name: String) -> Option<&'a DmFunction> {
|
|
||||||
unsafe {
|
|
||||||
(*ptr).object_type.methods.get(&name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rust_string_from_dm_object(ptr: &*mut DmObject) -> String {
|
|
||||||
unsafe {
|
|
||||||
let dm_object = Box::from_raw(*ptr);
|
|
||||||
format!("{}@{:?}", dm_object.object_type.name, dm_object.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rust_string_from_dm_string(ptr: *mut DmObject) -> String {
|
|
||||||
unsafe {
|
|
||||||
let dm_string = Box::from_raw(ptr);
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dm_print(args: Vec<DmValue>, vm: &mut DmVirtualMachine) -> DmValue {
|
pub fn dm_print(args: Vec<DmValue>, vm: &mut DmVirtualMachine) -> DmValue {
|
||||||
if args.len() != 1 {
|
if args.len() != 1 {
|
||||||
@ -42,20 +21,26 @@ pub fn dm_print(args: Vec<DmValue>, vm: &mut DmVirtualMachine) -> DmValue {
|
|||||||
DmBoolean(b) => {
|
DmBoolean(b) => {
|
||||||
print!("{}", *b);
|
print!("{}", *b);
|
||||||
}
|
}
|
||||||
DmPointer(ptr) => {
|
DmPointer(ptr) => unsafe {
|
||||||
if let Some(to_string) = get_method(*ptr, String::from("to_string")) {
|
let dm_alloc_object = Box::from_raw(*ptr);
|
||||||
let call_result = vm.call(&to_string, vec![args[0].clone()]);
|
let dm_object_type = &dm_alloc_object.object_type;
|
||||||
match call_result {
|
if let Some(to_string_method) = dm_object_type.get_method(String::from("std::core::Object::to_string"), &dm_alloc_object) {
|
||||||
DmPointer(dm_string_ptr) => {
|
let call_result = vm.call(to_string_method, vec![args[0].clone()]);
|
||||||
let string = get_rust_string_from_dm_string(dm_string_ptr);
|
if let DmPointer(dm_string_pointer) = call_result {
|
||||||
print!("{}", string);
|
let dm_string_object = Box::from_raw(dm_string_pointer);
|
||||||
}
|
let bytes_property = dm_string_object.object_type.get_property(String::from("bytes"), &dm_string_object).unwrap();
|
||||||
_ => {
|
let string_bytes_value = mem::get_property_value(bytes_property, &dm_string_object);
|
||||||
// TODO: vm throw or return exception?
|
if let DmByteArray(raw_string_bytes) = string_bytes_value {
|
||||||
}
|
// TODO: other encodings
|
||||||
|
print!("{}", String::from_utf8(raw_string_bytes).unwrap());
|
||||||
|
} else {
|
||||||
|
panic!("Expected std::core::String.bytes to be a ByteArray.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print!("{}", get_rust_string_from_dm_object(ptr));
|
panic!("Expected {} to return a string.", to_string_method.fqn)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{}@{:?}", dm_object_type.get_fqn(), dm_alloc_object.data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DmByteArray(bs) => {
|
DmByteArray(bs) => {
|
||||||
|
164
src/vm/types.rs
164
src/vm/types.rs
@ -1,14 +1,162 @@
|
|||||||
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
|
use crate::vm::mem::DmAllocObject;
|
||||||
pub enum DmType {
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum DmType<'a> {
|
||||||
|
Byte,
|
||||||
Int,
|
Int,
|
||||||
Long,
|
Long,
|
||||||
Double,
|
Double,
|
||||||
Boolean,
|
Boolean,
|
||||||
Pointer,
|
ObjectPointer(&'a dyn DmObjectType),
|
||||||
IntArray,
|
ByteArray(usize),
|
||||||
LongArray,
|
IntArray(usize),
|
||||||
DoubleArray,
|
LongArray(usize),
|
||||||
BooleanArray,
|
DoubleArray(usize),
|
||||||
PointerArray,
|
BooleanArray(usize),
|
||||||
|
ObjectPointerArray(usize, &'a dyn DmObjectType),
|
||||||
Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DmType<'_> {
|
||||||
|
pub fn size_in_bytes(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
DmType::Byte => 1,
|
||||||
|
DmType::Int => 4,
|
||||||
|
DmType::Long => 8,
|
||||||
|
DmType::Double => 8,
|
||||||
|
DmType::Boolean => 4,
|
||||||
|
DmType::ObjectPointer(_) => 8,
|
||||||
|
DmType::ByteArray(length) => *length,
|
||||||
|
DmType::IntArray(length) => *length * 4,
|
||||||
|
DmType::LongArray(length) => *length * 8,
|
||||||
|
DmType::DoubleArray(length) => *length * 8,
|
||||||
|
DmType::BooleanArray(length) => *length * 4,
|
||||||
|
DmType::ObjectPointerArray(length, _) => length * 8,
|
||||||
|
DmType::Unit => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DmObjectType {
|
||||||
|
fn get_fqn(&self) -> &String;
|
||||||
|
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn>;
|
||||||
|
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmFn {
|
||||||
|
pub fqn: String,
|
||||||
|
pub short_name: String,
|
||||||
|
pub byte_code: Vec<u8>,
|
||||||
|
pub num_registers: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmFn {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.fqn == other.fqn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmInterface<'a> {
|
||||||
|
fqn: String,
|
||||||
|
short_name: String,
|
||||||
|
properties: HashMap<String, DmProperty<'a>>,
|
||||||
|
virtual_methods: HashMap<String, DmVirtualMethod>,
|
||||||
|
impl_methods: HashMap<String, DmFn>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmInterface<'_> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.fqn == other.fqn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DmObjectType for DmInterface<'_> {
|
||||||
|
fn get_fqn(&self) -> &String {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn> {
|
||||||
|
if self.impl_methods.contains_key(&name) {
|
||||||
|
self.impl_methods.get(&name)
|
||||||
|
} else if self.virtual_methods.contains_key(&name) {
|
||||||
|
self_object.object_type.get_method(name, &self_object)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||||
|
self.properties.get(&name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmVirtualMethod {
|
||||||
|
pub fqn: String,
|
||||||
|
pub short_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmVirtualMethod {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.fqn == other.fqn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmImplementation<'a> {
|
||||||
|
pub fqn: String,
|
||||||
|
pub short_name: String,
|
||||||
|
pub interface: &'a DmInterface<'a>,
|
||||||
|
pub properties: HashMap<String, DmProperty<'a>>,
|
||||||
|
pub fields: HashMap<String, DmField<'a>>,
|
||||||
|
pub size_in_bytes: usize,
|
||||||
|
pub methods: HashMap<String, DmFn>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmImplementation<'_> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.fqn == other.fqn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DmObjectType for DmImplementation<'_> {
|
||||||
|
fn get_fqn(&self) -> &String {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn> {
|
||||||
|
self.methods.get(&name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||||
|
self.properties.get(&name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmProperty<'a> {
|
||||||
|
pub name: String,
|
||||||
|
pub data_offset: usize,
|
||||||
|
pub dm_type: DmType<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmProperty<'_> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.name == other.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq)]
|
||||||
|
pub struct DmField<'a> {
|
||||||
|
name: String,
|
||||||
|
dm_type: DmType<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DmField<'_> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.name == other.name
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use crate::vm::DmObject;
|
use crate::vm::mem::DmAllocObject;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum DmValue {
|
pub enum DmValue {
|
||||||
@ -7,12 +7,12 @@ pub enum DmValue {
|
|||||||
DmLong(i64),
|
DmLong(i64),
|
||||||
DmDouble(f64),
|
DmDouble(f64),
|
||||||
DmBoolean(bool),
|
DmBoolean(bool),
|
||||||
DmPointer(*mut DmObject),
|
DmPointer(*mut DmAllocObject),
|
||||||
DmByteArray(Vec<u8>),
|
DmByteArray(Vec<u8>),
|
||||||
DmIntArray(Vec<i32>),
|
DmIntArray(Vec<i32>),
|
||||||
DmLongArray(Vec<i64>),
|
DmLongArray(Vec<i64>),
|
||||||
DmDoubleArray(Vec<f64>),
|
DmDoubleArray(Vec<f64>),
|
||||||
DmBooleanArray(Vec<bool>),
|
DmBooleanArray(Vec<bool>),
|
||||||
DmPointerArray(Vec<*mut DmObject>),
|
DmPointerArray(Vec<*mut DmAllocObject>),
|
||||||
DmUnit,
|
DmUnit,
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user