From 71ee49761eae6c9334fe2acfafe8cd52aca066d4 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sun, 13 Apr 2025 10:20:29 -0500 Subject: [PATCH] Updated dvm/main.rs to use new refactored dvm. --- src/bin/dvm/main.rs | 206 +++++++++----------------------- src/vm/array.rs | 3 +- src/vm/function.rs | 13 +- src/vm/instruction.rs | 12 +- src/vm/mod.rs | 67 ++++++++--- src/vm/platform/mod.rs | 2 +- src/vm/platform/std_lib/core.rs | 4 +- src/vm/pointer.rs | 13 -- src/vm/source_code_location.rs | 6 + src/vm/value.rs | 22 +++- 10 files changed, 150 insertions(+), 198 deletions(-) delete mode 100644 src/vm/pointer.rs create mode 100644 src/vm/source_code_location.rs diff --git a/src/bin/dvm/main.rs b/src/bin/dvm/main.rs index cfc62ab..7d88870 100644 --- a/src/bin/dvm/main.rs +++ b/src/bin/dvm/main.rs @@ -1,163 +1,69 @@ -use deimos::vm::field::DvmField; +use deimos::vm::constant::DvmConstant; use deimos::vm::function::DvmFunction; -use deimos::vm::implementation::DvmImplementation; -use deimos::vm::interface::DmInterface; -use deimos::vm::lib::{DmConstant, DmLib}; -use deimos::vm::method::DvmMethod; -use deimos::vm::op_codes::{ - add_alloc, add_dealloc, add_invoke_fn, add_mov_const, add_platform_call, add_store, -}; -use deimos::vm::platform::init_platform_functions; -use deimos::vm::r#type::DvmType; -use deimos::vm::{call_fn, DvmContext, DvmState}; +use deimos::vm::instruction::{Immediate, Instruction, Location}; +use deimos::vm::platform::get_std_lib_platform_functions; +use deimos::vm::source_code_location::SourceCodeLocation; +use deimos::vm::{dump_state, run_main_function, DvmContext, DvmState}; use std::rc::Rc; fn main() { // Goal: // - write a single lib with a main() // - call the main fn - // fn main() { println "Hello, World!" } + // + // ns greeter + // + // fn main() { + // println "Hello, World!" + // } + let main_instructions = vec![ + Instruction::MoveImmediate { + destination: Location::Register(0), + immediate: Immediate::Constant(DvmConstant::String(String::from("Hello, World!"))), + }, + Instruction::Push { source_register: 0 }, + Instruction::InvokeStaticPlatform { + function_name: Rc::new(String::from("std::core::println")), + source_code_location: SourceCodeLocation { + source_file_name: String::from("greeter.dm"), + line: 4, + char: 5, + }, + }, + Instruction::Pop { + // println return value + destination_register: None, + }, + Instruction::Pop { + // arg0 to println + destination_register: None, + }, + Instruction::MoveImmediate { + destination: Location::Register(1), + immediate: Immediate::Int(0), + }, + Instruction::Push { source_register: 1 }, + Instruction::Return, + ]; - // std/core/array lib - let mut array_lib = DmLib::new("std/core/array"); - - // std::core::Array - let array_int = DmInterface::new("std::core::Array"); - 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 = DvmImplementation::new("std::core::ArrayImpl", Some(array_int_rc.clone())); - - let array_impl_ptr_address_fld = DvmField::new("ptr_address", DvmType::USize); - let array_impl_ptr_size_fld = DvmField::new("ptr_size", DvmType::USize); - let array_impl_length_fld = DvmField::new("length", DvmType::Long); - - array_impl.add_field(array_impl_ptr_address_fld); - array_impl.add_field(array_impl_ptr_size_fld); - array_impl.add_field(array_impl_length_fld); - - // std::core::ArrayImpl::_ctor_0( - // r0: self - // r1: USize ptr_address - // r2: USize ptr_size - // r3: Long length - // ) - let mut array_impl_ctor_0_bytecode: Vec = Vec::new(); - - add_store(&mut array_impl_ctor_0_bytecode, 0, 0, 1); - add_store(&mut array_impl_ctor_0_bytecode, 0, 1, 2); - add_store(&mut array_impl_ctor_0_bytecode, 0, 2, 3); - - let array_impl_ctor_0_fn = DvmFunction::new( - "std::core::ArrayImpl::_ctor_0", - "_ctor_0", - array_impl_ctor_0_bytecode, - 4, - None, + let main_function = DvmFunction::new( + "greeter::main", + &main_instructions, + SourceCodeLocation { + source_file_name: String::from("greeter.dm"), + line: 3, + char: 1, + }, ); - let array_impl_ctor_0_method = DvmMethod::new(array_impl_ctor_0_fn, None); - array_impl.add_method(array_impl_ctor_0_method); - - 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_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 = - DvmImplementation::new("std::core::StringImpl", Some(string_int_rc.clone())); - - let bytes_field = DvmField::new("bytes", DvmType::Object); - string_impl.add_field(bytes_field); - - // std::core::String::_ctor_0( - // r0: self - // r1: Array bytes - // ) - let mut string_ctor_0_bytecode: Vec = Vec::new(); - add_store(&mut string_ctor_0_bytecode, 0, 0, 1); - - let string_ctor_0_fn = DvmFunction::new( - "std::core::StringImpl::_ctor_0", - "_ctor_0", - string_ctor_0_bytecode, - 2, - None, - ); - - let string_ctor_0_method = DvmMethod::new(string_ctor_0_fn, None); - - string_impl.add_method(string_ctor_0_method); - - string_lib.add_implementation(string_impl); - - // greeting lib - let mut greeting_lib = DmLib::new("greeting"); - greeting_lib.add_constant(DmConstant::String("Hello, World!".to_string())); - - let mut main_byte_code = Vec::new(); - - // Move greeting - // r0: greeting address - // r1: greeting size - add_mov_const(&mut main_byte_code, 0, 1, "greeting", 0); - - // Alloc Array greeting bytes - add_alloc(&mut main_byte_code, 2, "std::core::ArrayImpl"); - - // Call ArrayImpl(ptr_address, ptr_size, length) - add_invoke_fn( - &mut main_byte_code, - "std::core::ArrayImpl::_ctor_0", - 3, - &[2, 0, 1, 1], - ); - - // Alloc StringImpl greeting - add_alloc(&mut main_byte_code, 4, "std::core::StringImpl"); - - // Call StringImpl(greeting_bytes) - add_invoke_fn( - &mut main_byte_code, - "std::core::StringImpl::_ctor_0", - 5, - &[4, 2], - ); - - // Call println(greeting) - add_platform_call(&mut main_byte_code, "std::core::println", 6, &[4]); - - // Dealloc StringImpl - add_dealloc(&mut main_byte_code, 4); - - // Dealloc ArrayImpl - add_dealloc(&mut main_byte_code, 2); - - let main_dm_fn = DvmFunction::new("main", "main", main_byte_code, 7, None); - - greeting_lib.add_function(main_dm_fn); let mut state = DvmState::new(); - let mut context = DvmContext::new(); - context.load_libs(vec![ - Rc::new(greeting_lib), - Rc::new(string_lib), - Rc::new(array_lib), - ]); - context.load_platform_fns(init_platform_functions()); + let mut context = DvmContext::new(Rc::new(main_function)); + context.add_platform_functions(get_std_lib_platform_functions()); + let exit_code = run_main_function(&mut state, &context); - let main_fn = context.fn_by_fqn("main").unwrap(); - call_fn(&mut state, &context, &main_fn, vec![]); + dump_state(&state, "After main!"); + + if exit_code != 0 { + std::process::exit(exit_code); + } } diff --git a/src/vm/array.rs b/src/vm/array.rs index 22c0428..eb7464e 100644 --- a/src/vm/array.rs +++ b/src/vm/array.rs @@ -1,5 +1,4 @@ use crate::vm::object::DvmObject; -use crate::vm::pointer::DvmPointer; use crate::vm::value::DvmValue; use std::cell::RefCell; use std::fmt::{Display, Write}; @@ -16,7 +15,7 @@ pub enum DvmArray { Booleans(Vec), Objects(Vec>>), Arrays(Vec>>), - Strings(Vec>) + Strings(Vec>), } impl DvmArray { diff --git a/src/vm/function.rs b/src/vm/function.rs index ad9e43c..d6cece1 100644 --- a/src/vm/function.rs +++ b/src/vm/function.rs @@ -1,16 +1,23 @@ use crate::vm::instruction::Instruction; +use crate::vm::source_code_location::SourceCodeLocation; #[derive(Debug)] pub struct DvmFunction { fqn: String, instructions: Vec, + source_code_location: SourceCodeLocation, } impl DvmFunction { - pub fn new(fqn: &str, instructions: &[Instruction]) -> Self { + pub fn new( + fqn: &str, + instructions: &[Instruction], + source_code_location: SourceCodeLocation, + ) -> Self { DvmFunction { fqn: fqn.to_string(), instructions: Vec::from(instructions), + source_code_location, } } @@ -21,6 +28,10 @@ impl DvmFunction { pub fn instructions(&self) -> &Vec { &self.instructions } + + pub fn source_code_location(&self) -> &SourceCodeLocation { + &self.source_code_location + } } impl PartialEq for DvmFunction { diff --git a/src/vm/instruction.rs b/src/vm/instruction.rs index d9c18f6..9aece0b 100644 --- a/src/vm/instruction.rs +++ b/src/vm/instruction.rs @@ -1,5 +1,6 @@ -use std::rc::Rc; use crate::vm::constant::DvmConstant; +use crate::vm::source_code_location::SourceCodeLocation; +use std::rc::Rc; #[derive(Debug, Clone)] pub enum Instruction { @@ -15,7 +16,7 @@ pub enum Instruction { source_register: usize, }, Pop { - destination_register: usize, + destination_register: Option, }, AllocateObject { implementation_name: Rc, @@ -133,10 +134,3 @@ pub enum Location { offset: Option, }, } - -#[derive(Debug, Clone)] -pub struct SourceCodeLocation { - pub source_file_name: String, - pub line: i64, - pub char: i64, -} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index cbba5f5..da368a2 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -1,16 +1,16 @@ mod array; -mod constant; +pub mod constant; mod field; -mod function; +pub mod function; pub mod implementation; -mod instruction; +pub mod instruction; mod interface; pub mod lib; mod method; pub mod object; pub mod op_codes; pub mod platform; -mod pointer; +pub mod source_code_location; pub mod r#type; pub mod util; pub mod value; @@ -19,24 +19,27 @@ 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::instruction::{Immediate, Instruction, Location}; use crate::vm::object::DvmObject; use crate::vm::value::DvmValue; use function::DvmFunction; +use source_code_location::SourceCodeLocation; use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Display; use std::rc::Rc; -fn dvm_panic(state: &DvmState, message: &str) { +pub fn dump_state(state: &DvmState, message: &str) { println!("----"); - println!("Deimos Virtual Machine: Panic!"); println!("{}", message); println!("----"); - println!("Current Instruction: {:?}", state.current_instruction); + println!( + "Current Instruction: {:?}", + state.current_instruction.clone().unwrap() + ); println!("Registers:"); for (i, register) in state.registers.iter().enumerate() { - println!("\tr{}: {:?}", i, register); + println!("\tr{:x}: {:?}", i, register); } println!("Call stack:"); for call in state.call_stack.iter() { @@ -51,7 +54,7 @@ fn dvm_panic(state: &DvmState, message: &str) { macro_rules! dvm_panic { ($context: expr, $message: expr) => { - dvm_panic($context, $message); + dump_state($context, $message); panic!() }; } @@ -70,7 +73,7 @@ impl DvmState { DvmState { call_stack: vec![], current_instruction: None, - registers: vec![], + registers: vec![DvmValue::Empty; 16], stack: vec![], } } @@ -80,22 +83,42 @@ impl DvmState { dvm_panic!(self, "Stack underflow!"); }) } + + pub fn get_stack_argument(&self, index: usize) -> DvmValue { + self.stack + .get(self.stack.len() - 2 - index) + .unwrap_or_else(|| { + dvm_panic!(self, "Stack underflow!"); + }) + .clone() + } } pub struct DvmContext { + main_function: Rc, implementations: HashMap>, static_functions: HashMap>, platform_functions: HashMap, } impl DvmContext { - pub fn new() -> Self { + pub fn new(main_function: Rc) -> Self { DvmContext { + main_function, implementations: HashMap::new(), static_functions: HashMap::new(), platform_functions: HashMap::new(), } } + + pub fn add_platform_functions( + &mut self, + platform_functions: HashMap, + ) { + for (fqn, platform_function) in platform_functions { + self.platform_functions.insert(fqn, platform_function); + } + } } pub struct DvmCall { @@ -257,12 +280,25 @@ fn immediate_to_value(immediate: &Immediate) -> DvmValue { } } +pub fn run_main_function(state: &mut DvmState, context: &DvmContext) -> i32 { + let main_function = context.main_function.clone(); + push_call_frame( + Rc::new(main_function.fqn().to_string()), + main_function.source_code_location().clone(), + state, + ); + run(main_function.instructions(), state, context); + pop_call_frame(state); + state.pop_stack().expect_int_or_else(|v| { + dvm_panic!(state, &format!("Expected DvmValue::Int, but found {}", v)); + }) +} + // TODO: find all possible unwraps/expects and wrap with call to dvm_panic pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmContext) { let mut index = 0; while index < instructions.len() { state.current_instruction = Some(instructions[index].clone()); - index += 1; use Instruction::*; match &instructions[index] { MoveImmediate { @@ -287,7 +323,9 @@ pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmCont let value = state.stack.pop().unwrap_or_else(|| { dvm_panic!(state, "Stack underflow"); }); - state.registers[*destination_register] = value; + if let Some(register_index) = destination_register { + state.registers[*register_index] = value; + } } AllocateObject { implementation_name, @@ -451,5 +489,6 @@ pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmCont break; } } + index += 1; } } diff --git a/src/vm/platform/mod.rs b/src/vm/platform/mod.rs index 656117a..12ec598 100644 --- a/src/vm/platform/mod.rs +++ b/src/vm/platform/mod.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; mod std_lib; -pub fn init_platform_functions() -> HashMap { +pub fn get_std_lib_platform_functions() -> HashMap { let mut fns: HashMap = HashMap::new(); fns.insert(String::from("std::core::print"), dm_print); fns.insert(String::from("std::core::println"), dm_println); diff --git a/src/vm/platform/std_lib/core.rs b/src/vm/platform/std_lib/core.rs index 60f7339..d64e796 100644 --- a/src/vm/platform/std_lib/core.rs +++ b/src/vm/platform/std_lib/core.rs @@ -9,11 +9,11 @@ use std::rc::Rc; /// print(m: &(Byte | Int | Long | Double | USize | Boolean | Object | Empty)) /// ``` pub fn dm_print(state: &mut DvmState, context: &DvmContext) { - print!("{}", get_string(state.pop_stack())); + print!("{}", get_string(state.get_stack_argument(0))); } pub fn dm_println(state: &mut DvmState, context: &DvmContext) { - println!("{}", get_string(state.pop_stack())); + println!("{}", get_string(state.get_stack_argument(0))); } fn get_string(dvm_value: DvmValue) -> String { diff --git a/src/vm/pointer.rs b/src/vm/pointer.rs deleted file mode 100644 index 70c905d..0000000 --- a/src/vm/pointer.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::fmt::Display; - -#[derive(Debug, Clone, PartialEq)] -pub struct DvmPointer { - pub raw_pointer: *const u8, - pub length: usize, -} - -impl Display for DvmPointer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "DvmPointer({:p}, {})", self.raw_pointer, self.length) - } -} \ No newline at end of file diff --git a/src/vm/source_code_location.rs b/src/vm/source_code_location.rs new file mode 100644 index 0000000..8b84819 --- /dev/null +++ b/src/vm/source_code_location.rs @@ -0,0 +1,6 @@ +#[derive(Debug, Clone)] +pub struct SourceCodeLocation { + pub source_file_name: String, + pub line: i64, + pub char: i64, +} diff --git a/src/vm/value.rs b/src/vm/value.rs index 223e0f8..449e8fa 100644 --- a/src/vm/value.rs +++ b/src/vm/value.rs @@ -1,6 +1,5 @@ use crate::vm::array::DvmArray; use crate::vm::object::DvmObject; -use crate::vm::pointer::DvmPointer; use std::cell::RefCell; use std::fmt::{Display, Formatter}; use std::rc::Rc; @@ -71,6 +70,14 @@ impl DvmValue { panic!("Expected DvmValue::Int, but found DvmValue::{:?}", self); } } + + pub fn expect_int_or_else(&self, f: impl FnOnce(&Self) -> i32) -> i32 { + if let DvmValue::Int(i) = self { + *i + } else { + f(self) + } + } pub fn expect_long(&self) -> i64 { if let DvmValue::Long(l) = self { @@ -102,8 +109,11 @@ impl DvmValue { panic!("Expected DvmValue::Object, but found DvmValue::{:?}", self); } } - - pub fn expect_object_or_else(&self, f: impl FnOnce(&Self) -> DvmObject) -> Rc> { + + pub fn expect_object_or_else( + &self, + f: impl FnOnce(&Self) -> DvmObject, + ) -> Rc> { if let DvmValue::Object(o) = self { o.clone() } else { @@ -144,7 +154,7 @@ impl DvmValue { _ => false, } } - + pub fn map_array( &self, mapper: impl FnOnce(Rc>) -> T, @@ -190,7 +200,7 @@ impl DvmValue { panic!("Expected DvmValue::Boolean, but found DvmValue::{:?}", self); } } - + pub fn expect_string(&self) -> Rc { if let DvmValue::String(s) = self { s.clone() @@ -198,7 +208,7 @@ impl DvmValue { panic!("Expected DvmValue::String, but found DvmValue::{:?}", self); } } - + pub fn expect_string_or_else(&self, f: impl FnOnce(&Self) -> String) -> Rc { if let DvmValue::String(s) = self { s.clone()