Compare commits
2 Commits
172e82025d
...
71ee49761e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
71ee49761e | ||
![]() |
26d87acff5 |
@ -1,163 +1,69 @@
|
|||||||
use deimos::vm::field::DvmField;
|
use deimos::vm::constant::DvmConstant;
|
||||||
use deimos::vm::function::DvmFunction;
|
use deimos::vm::function::DvmFunction;
|
||||||
use deimos::vm::implementation::DvmImplementation;
|
use deimos::vm::instruction::{Immediate, Instruction, Location};
|
||||||
use deimos::vm::interface::DmInterface;
|
use deimos::vm::platform::get_std_lib_platform_functions;
|
||||||
use deimos::vm::lib::{DmConstant, DmLib};
|
use deimos::vm::source_code_location::SourceCodeLocation;
|
||||||
use deimos::vm::method::DvmMethod;
|
use deimos::vm::{dump_state, run_main_function, DvmContext, DvmState};
|
||||||
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 std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Goal:
|
// Goal:
|
||||||
// - write a single lib with a main()
|
// - write a single lib with a main()
|
||||||
// - call the main fn
|
// - 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 main_function = DvmFunction::new(
|
||||||
let mut array_lib = DmLib::new("std/core/array");
|
"greeter::main",
|
||||||
|
&main_instructions,
|
||||||
// std::core::Array
|
SourceCodeLocation {
|
||||||
let array_int = DmInterface::new("std::core::Array");
|
source_file_name: String::from("greeter.dm"),
|
||||||
array_lib.add_interface(array_int);
|
line: 3,
|
||||||
let array_int_rc = array_lib
|
char: 1,
|
||||||
.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<u8> = 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 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<Byte> bytes
|
|
||||||
// )
|
|
||||||
let mut string_ctor_0_bytecode: Vec<u8> = 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<Byte> 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 state = DvmState::new();
|
||||||
let mut context = DvmContext::new();
|
let mut context = DvmContext::new(Rc::new(main_function));
|
||||||
context.load_libs(vec![
|
context.add_platform_functions(get_std_lib_platform_functions());
|
||||||
Rc::new(greeting_lib),
|
let exit_code = run_main_function(&mut state, &context);
|
||||||
Rc::new(string_lib),
|
|
||||||
Rc::new(array_lib),
|
|
||||||
]);
|
|
||||||
context.load_platform_fns(init_platform_functions());
|
|
||||||
|
|
||||||
let main_fn = context.fn_by_fqn("main").unwrap();
|
dump_state(&state, "After main!");
|
||||||
call_fn(&mut state, &context, &main_fn, vec![]);
|
|
||||||
|
if exit_code != 0 {
|
||||||
|
std::process::exit(exit_code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::vm::object::DvmObject;
|
use crate::vm::object::DvmObject;
|
||||||
use crate::vm::pointer::DvmPointer;
|
|
||||||
use crate::vm::value::DvmValue;
|
use crate::vm::value::DvmValue;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::{Display, Write};
|
use std::fmt::{Display, Write};
|
||||||
@ -16,7 +15,7 @@ pub enum DvmArray {
|
|||||||
Booleans(Vec<bool>),
|
Booleans(Vec<bool>),
|
||||||
Objects(Vec<Rc<RefCell<DvmObject>>>),
|
Objects(Vec<Rc<RefCell<DvmObject>>>),
|
||||||
Arrays(Vec<Rc<RefCell<DvmArray>>>),
|
Arrays(Vec<Rc<RefCell<DvmArray>>>),
|
||||||
ConstantPointers(Vec<DvmPointer>),
|
Strings(Vec<Rc<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DvmArray {
|
impl DvmArray {
|
||||||
@ -30,7 +29,7 @@ impl DvmArray {
|
|||||||
DvmArray::Booleans(vec) => DvmValue::Boolean(vec[index]),
|
DvmArray::Booleans(vec) => DvmValue::Boolean(vec[index]),
|
||||||
DvmArray::Objects(vec) => DvmValue::Object(vec[index].clone()),
|
DvmArray::Objects(vec) => DvmValue::Object(vec[index].clone()),
|
||||||
DvmArray::Arrays(vec) => DvmValue::Array(vec[index].clone()),
|
DvmArray::Arrays(vec) => DvmValue::Array(vec[index].clone()),
|
||||||
DvmArray::ConstantPointers(vec) => DvmValue::ConstantPointer(vec[index].clone()),
|
DvmArray::Strings(vec) => DvmValue::String(vec[index].clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +59,8 @@ impl DvmArray {
|
|||||||
DvmArray::Arrays(vec) => {
|
DvmArray::Arrays(vec) => {
|
||||||
vec[index] = value.expect_array();
|
vec[index] = value.expect_array();
|
||||||
}
|
}
|
||||||
DvmArray::ConstantPointers(vec) => {
|
DvmArray::Strings(vec) => {
|
||||||
vec[index] = value.expect_constant_pointer();
|
vec[index] = value.expect_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +88,7 @@ pub enum DvmArrayIter<'a> {
|
|||||||
Booleans(Iter<'a, bool>),
|
Booleans(Iter<'a, bool>),
|
||||||
Objects(Iter<'a, Rc<RefCell<DvmObject>>>),
|
Objects(Iter<'a, Rc<RefCell<DvmObject>>>),
|
||||||
Arrays(Iter<'a, Rc<RefCell<DvmArray>>>),
|
Arrays(Iter<'a, Rc<RefCell<DvmArray>>>),
|
||||||
ConstantPointers(Iter<'a, DvmPointer>),
|
Strings(Iter<'a, Rc<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for DvmArrayIter<'a> {
|
impl<'a> Iterator for DvmArrayIter<'a> {
|
||||||
@ -104,9 +103,7 @@ impl<'a> Iterator for DvmArrayIter<'a> {
|
|||||||
DvmArrayIter::Booleans(iter) => iter.next().map(|b| DvmValue::Boolean(*b)),
|
DvmArrayIter::Booleans(iter) => iter.next().map(|b| DvmValue::Boolean(*b)),
|
||||||
DvmArrayIter::Objects(iter) => iter.next().map(|o| DvmValue::Object(o.clone())),
|
DvmArrayIter::Objects(iter) => iter.next().map(|o| DvmValue::Object(o.clone())),
|
||||||
DvmArrayIter::Arrays(iter) => iter.next().map(|a| DvmValue::Array(a.clone())),
|
DvmArrayIter::Arrays(iter) => iter.next().map(|a| DvmValue::Array(a.clone())),
|
||||||
DvmArrayIter::ConstantPointers(iter) => {
|
DvmArrayIter::Strings(iter) => iter.next().map(|s| DvmValue::String(s.clone())),
|
||||||
iter.next().map(|p| DvmValue::ConstantPointer(p.clone()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +122,7 @@ impl<'a> IntoIterator for &'a DvmArray {
|
|||||||
DvmArray::Booleans(v) => DvmArrayIter::Booleans(v.iter()),
|
DvmArray::Booleans(v) => DvmArrayIter::Booleans(v.iter()),
|
||||||
DvmArray::Objects(v) => DvmArrayIter::Objects(v.iter()),
|
DvmArray::Objects(v) => DvmArrayIter::Objects(v.iter()),
|
||||||
DvmArray::Arrays(v) => DvmArrayIter::Arrays(v.iter()),
|
DvmArray::Arrays(v) => DvmArrayIter::Arrays(v.iter()),
|
||||||
DvmArray::ConstantPointers(v) => DvmArrayIter::ConstantPointers(v.iter()),
|
DvmArray::Strings(v) => DvmArrayIter::Strings(v.iter()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
src/vm/constant.rs
Normal file
17
src/vm/constant.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DvmConstant {
|
||||||
|
String(String),
|
||||||
|
Array(DvmConstantArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DvmConstantArray {
|
||||||
|
Bytes(Vec<u8>),
|
||||||
|
Ints(Vec<i32>),
|
||||||
|
Longs(Vec<i64>),
|
||||||
|
Doubles(Vec<f64>),
|
||||||
|
USizes(Vec<usize>),
|
||||||
|
Booleans(Vec<bool>),
|
||||||
|
Strings(Vec<String>),
|
||||||
|
Arrays(Vec<DvmConstantArray>)
|
||||||
|
}
|
@ -1,16 +1,23 @@
|
|||||||
use crate::vm::instruction::Instruction;
|
use crate::vm::instruction::Instruction;
|
||||||
|
use crate::vm::source_code_location::SourceCodeLocation;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DvmFunction {
|
pub struct DvmFunction {
|
||||||
fqn: String,
|
fqn: String,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
|
source_code_location: SourceCodeLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DvmFunction {
|
impl DvmFunction {
|
||||||
pub fn new(fqn: &str, instructions: &[Instruction]) -> Self {
|
pub fn new(
|
||||||
|
fqn: &str,
|
||||||
|
instructions: &[Instruction],
|
||||||
|
source_code_location: SourceCodeLocation,
|
||||||
|
) -> Self {
|
||||||
DvmFunction {
|
DvmFunction {
|
||||||
fqn: fqn.to_string(),
|
fqn: fqn.to_string(),
|
||||||
instructions: Vec::from(instructions),
|
instructions: Vec::from(instructions),
|
||||||
|
source_code_location,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +28,10 @@ impl DvmFunction {
|
|||||||
pub fn instructions(&self) -> &Vec<Instruction> {
|
pub fn instructions(&self) -> &Vec<Instruction> {
|
||||||
&self.instructions
|
&self.instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn source_code_location(&self) -> &SourceCodeLocation {
|
||||||
|
&self.source_code_location
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for DvmFunction {
|
impl PartialEq for DvmFunction {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::vm::constant::DvmConstant;
|
||||||
|
use crate::vm::source_code_location::SourceCodeLocation;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -14,7 +16,7 @@ pub enum Instruction {
|
|||||||
source_register: usize,
|
source_register: usize,
|
||||||
},
|
},
|
||||||
Pop {
|
Pop {
|
||||||
destination_register: usize,
|
destination_register: Option<usize>,
|
||||||
},
|
},
|
||||||
AllocateObject {
|
AllocateObject {
|
||||||
implementation_name: Rc<String>,
|
implementation_name: Rc<String>,
|
||||||
@ -29,8 +31,13 @@ pub enum Instruction {
|
|||||||
function_name: Rc<String>,
|
function_name: Rc<String>,
|
||||||
source_code_location: SourceCodeLocation,
|
source_code_location: SourceCodeLocation,
|
||||||
},
|
},
|
||||||
PlatformCall {
|
InvokeStaticPlatform {
|
||||||
platform_function_name: Rc<String>,
|
function_name: Rc<String>,
|
||||||
|
source_code_location: SourceCodeLocation,
|
||||||
|
},
|
||||||
|
InvokeObjectPlatform {
|
||||||
|
object_register: usize,
|
||||||
|
function_name: Rc<String>,
|
||||||
source_code_location: SourceCodeLocation,
|
source_code_location: SourceCodeLocation,
|
||||||
},
|
},
|
||||||
Add {
|
Add {
|
||||||
@ -107,10 +114,7 @@ pub enum Immediate {
|
|||||||
Double(f64),
|
Double(f64),
|
||||||
Usize(usize),
|
Usize(usize),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
ConstantPointer {
|
Constant(DvmConstant),
|
||||||
raw_pointer: *const u8,
|
|
||||||
length: usize
|
|
||||||
},
|
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,10 +134,3 @@ pub enum Location {
|
|||||||
offset: Option<isize>,
|
offset: Option<isize>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct SourceCodeLocation {
|
|
||||||
pub source_file_name: String,
|
|
||||||
pub line: i64,
|
|
||||||
pub char: i64,
|
|
||||||
}
|
|
||||||
|
366
src/vm/mod.rs
366
src/vm/mod.rs
@ -1,47 +1,52 @@
|
|||||||
mod array;
|
mod array;
|
||||||
|
pub mod constant;
|
||||||
mod field;
|
mod field;
|
||||||
mod function;
|
pub mod function;
|
||||||
pub mod implementation;
|
pub mod implementation;
|
||||||
mod instruction;
|
pub mod instruction;
|
||||||
mod interface;
|
mod interface;
|
||||||
pub mod lib;
|
pub mod lib;
|
||||||
mod method;
|
mod method;
|
||||||
pub mod object;
|
pub mod object;
|
||||||
pub mod op_codes;
|
pub mod op_codes;
|
||||||
pub mod platform;
|
pub mod platform;
|
||||||
mod pointer;
|
pub mod source_code_location;
|
||||||
pub mod r#type;
|
pub mod r#type;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
mod virtual_method;
|
mod virtual_method;
|
||||||
|
|
||||||
|
use crate::vm::array::DvmArray;
|
||||||
|
use crate::vm::constant::{DvmConstant, DvmConstantArray};
|
||||||
use crate::vm::implementation::DvmImplementation;
|
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::object::DvmObject;
|
||||||
use crate::vm::pointer::DvmPointer;
|
|
||||||
use crate::vm::value::DvmValue;
|
use crate::vm::value::DvmValue;
|
||||||
use function::DvmFunction;
|
use function::DvmFunction;
|
||||||
|
use source_code_location::SourceCodeLocation;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn dvm_panic(context: &DvmContext, message: &str) {
|
pub fn dump_state(state: &DvmState, message: &str) {
|
||||||
println!("----");
|
println!("----");
|
||||||
println!("Deimos Virtual Machine: Panic!");
|
|
||||||
println!("{}", message);
|
println!("{}", message);
|
||||||
println!("----");
|
println!("----");
|
||||||
println!("Current Instruction: {:?}", context.current_instruction);
|
println!(
|
||||||
|
"Current Instruction: {:?}",
|
||||||
|
state.current_instruction.clone().unwrap()
|
||||||
|
);
|
||||||
println!("Registers:");
|
println!("Registers:");
|
||||||
for (i, register) in context.registers.iter().enumerate() {
|
for (i, register) in state.registers.iter().enumerate() {
|
||||||
println!("\tr{}: {:?}", i, register);
|
println!("\tr{:x}: {:?}", i, register);
|
||||||
}
|
}
|
||||||
println!("Call stack:");
|
println!("Call stack:");
|
||||||
for call in context.call_stack.iter() {
|
for call in state.call_stack.iter() {
|
||||||
println!("\t{}", call);
|
println!("\t{}", call);
|
||||||
}
|
}
|
||||||
println!("Stack:");
|
println!("Stack:");
|
||||||
for (i, value) in context.stack.iter().enumerate() {
|
for (i, value) in state.stack.iter().enumerate() {
|
||||||
println!("\t{}: {}", i, value);
|
println!("\t{}: {}", i, value);
|
||||||
}
|
}
|
||||||
println!("----");
|
println!("----");
|
||||||
@ -49,33 +54,27 @@ fn dvm_panic(context: &DvmContext, message: &str) {
|
|||||||
|
|
||||||
macro_rules! dvm_panic {
|
macro_rules! dvm_panic {
|
||||||
($context: expr, $message: expr) => {
|
($context: expr, $message: expr) => {
|
||||||
dvm_panic($context, $message);
|
dump_state($context, $message);
|
||||||
panic!()
|
panic!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PlatformFunction = fn(context: &mut DvmContext);
|
pub type PlatformFunction = fn(state: &mut DvmState, context: &DvmContext);
|
||||||
|
|
||||||
pub struct DvmContext {
|
pub struct DvmState {
|
||||||
call_stack: Vec<DvmCall>,
|
call_stack: Vec<DvmCall>,
|
||||||
current_instruction: Option<Instruction>,
|
current_instruction: Option<Instruction>,
|
||||||
registers: Vec<DvmValue>,
|
registers: Vec<DvmValue>,
|
||||||
stack: Vec<DvmValue>,
|
stack: Vec<DvmValue>,
|
||||||
implementations: HashMap<String, Rc<DvmImplementation>>,
|
|
||||||
static_functions: HashMap<String, Rc<DvmFunction>>,
|
|
||||||
platform_functions: HashMap<String, PlatformFunction>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DvmContext {
|
impl DvmState {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DvmContext {
|
DvmState {
|
||||||
call_stack: vec![],
|
call_stack: vec![],
|
||||||
current_instruction: None,
|
current_instruction: None,
|
||||||
registers: vec![],
|
registers: vec![DvmValue::Empty; 16],
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
implementations: HashMap::new(),
|
|
||||||
static_functions: HashMap::new(),
|
|
||||||
platform_functions: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +83,42 @@ impl DvmContext {
|
|||||||
dvm_panic!(self, "Stack underflow!");
|
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<DvmFunction>,
|
||||||
|
implementations: HashMap<String, Rc<DvmImplementation>>,
|
||||||
|
static_functions: HashMap<String, Rc<DvmFunction>>,
|
||||||
|
platform_functions: HashMap<String, PlatformFunction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DvmContext {
|
||||||
|
pub fn new(main_function: Rc<DvmFunction>) -> 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<String, PlatformFunction>,
|
||||||
|
) {
|
||||||
|
for (fqn, platform_function) in platform_functions {
|
||||||
|
self.platform_functions.insert(fqn, platform_function);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmCall {
|
pub struct DvmCall {
|
||||||
@ -114,16 +149,16 @@ fn update_index(index: &mut usize, offset: isize) {
|
|||||||
fn push_call_frame(
|
fn push_call_frame(
|
||||||
function_name: Rc<String>,
|
function_name: Rc<String>,
|
||||||
source_code_location: SourceCodeLocation,
|
source_code_location: SourceCodeLocation,
|
||||||
context: &mut DvmContext,
|
state: &mut DvmState,
|
||||||
) {
|
) {
|
||||||
context.call_stack.push(DvmCall {
|
state.call_stack.push(DvmCall {
|
||||||
function_name,
|
function_name,
|
||||||
source_code_location,
|
source_code_location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_call_frame(context: &mut DvmContext) {
|
fn pop_call_frame(state: &mut DvmState) {
|
||||||
context.call_stack.pop();
|
state.call_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_index_with_offset(
|
fn compute_index_with_offset(
|
||||||
@ -146,17 +181,17 @@ fn compute_index_with_offset(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_from_source(context: &DvmContext, source: &Location) -> DvmValue {
|
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
||||||
match source {
|
match source {
|
||||||
Location::Register(register) => context.registers[*register].clone(),
|
Location::Register(register) => state.registers[*register].clone(),
|
||||||
Location::Stack { offset } => context.stack[*offset].clone(),
|
Location::Stack { offset } => state.stack[*offset].clone(),
|
||||||
Location::Field {
|
Location::Field {
|
||||||
object_register,
|
object_register,
|
||||||
field_name,
|
field_name,
|
||||||
} => context.registers[*object_register].map_object(
|
} => state.registers[*object_register].map_object(
|
||||||
|o| o.borrow().read_field(field_name).clone(),
|
|o| o.borrow().read_field(field_name).clone(),
|
||||||
|v| {
|
|v| {
|
||||||
dvm_panic!(context, &format!("Expected an object, but found: {}", v));
|
dvm_panic!(state, &format!("Expected an object, but found: {}", v));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Location::Array {
|
Location::Array {
|
||||||
@ -164,30 +199,30 @@ fn copy_from_source(context: &DvmContext, source: &Location) -> DvmValue {
|
|||||||
index_register,
|
index_register,
|
||||||
offset,
|
offset,
|
||||||
} => {
|
} => {
|
||||||
let index = compute_index_with_offset(&context.registers, *index_register, offset);
|
let index = compute_index_with_offset(&state.registers, *index_register, offset);
|
||||||
context.registers[*array_register].map_array(
|
state.registers[*array_register].map_array(
|
||||||
|a| a.borrow().read_element(index),
|
|a| a.borrow().read_element(index),
|
||||||
|v| {
|
|v| {
|
||||||
dvm_panic!(context, &format!("Expected an array, but found: {}", v));
|
dvm_panic!(state, &format!("Expected an array, but found: {}", v));
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_destination(context: &mut DvmContext, destination: &Location, value: DvmValue) {
|
fn write_to_destination(state: &mut DvmState, destination: &Location, value: DvmValue) {
|
||||||
match destination {
|
match destination {
|
||||||
Location::Register(register) => {
|
Location::Register(register) => {
|
||||||
context.registers[*register] = value;
|
state.registers[*register] = value;
|
||||||
}
|
}
|
||||||
Location::Stack { offset } => {
|
Location::Stack { offset } => {
|
||||||
context.stack[*offset] = value;
|
state.stack[*offset] = value;
|
||||||
}
|
}
|
||||||
Location::Field {
|
Location::Field {
|
||||||
object_register,
|
object_register,
|
||||||
field_name,
|
field_name,
|
||||||
} => {
|
} => {
|
||||||
context.registers[*object_register]
|
state.registers[*object_register]
|
||||||
.expect_object()
|
.expect_object()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_field(field_name, value);
|
.write_field(field_name, value);
|
||||||
@ -197,8 +232,8 @@ fn write_to_destination(context: &mut DvmContext, destination: &Location, value:
|
|||||||
index_register,
|
index_register,
|
||||||
offset,
|
offset,
|
||||||
} => {
|
} => {
|
||||||
let index = compute_index_with_offset(&context.registers, *index_register, offset);
|
let index = compute_index_with_offset(&state.registers, *index_register, offset);
|
||||||
context.registers[*array_register]
|
state.registers[*array_register]
|
||||||
.expect_array()
|
.expect_array()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_element(index, value);
|
.write_element(index, value);
|
||||||
@ -206,6 +241,32 @@ fn write_to_destination(context: &mut DvmContext, destination: &Location, value:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn constant_array_to_array(constant_array: &DvmConstantArray) -> DvmArray {
|
||||||
|
match constant_array {
|
||||||
|
DvmConstantArray::Bytes(v) => DvmArray::Bytes(v.clone()),
|
||||||
|
DvmConstantArray::Ints(v) => DvmArray::Ints(v.clone()),
|
||||||
|
DvmConstantArray::Longs(v) => DvmArray::Longs(v.clone()),
|
||||||
|
DvmConstantArray::Doubles(v) => DvmArray::Doubles(v.clone()),
|
||||||
|
DvmConstantArray::USizes(v) => DvmArray::USizes(v.clone()),
|
||||||
|
DvmConstantArray::Booleans(v) => DvmArray::Booleans(v.clone()),
|
||||||
|
DvmConstantArray::Strings(vs) => {
|
||||||
|
DvmArray::Strings(vs.iter().map(|s| Rc::new(s.clone())).collect())
|
||||||
|
}
|
||||||
|
DvmConstantArray::Arrays(va) => DvmArray::Arrays(
|
||||||
|
va.iter()
|
||||||
|
.map(|a| Rc::new(RefCell::new(constant_array_to_array(a))))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn constant_to_value(constant: &DvmConstant) -> DvmValue {
|
||||||
|
match constant {
|
||||||
|
DvmConstant::String(s) => DvmValue::String(Rc::new(s.clone())),
|
||||||
|
DvmConstant::Array(a) => DvmValue::Array(Rc::new(RefCell::new(constant_array_to_array(a)))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
||||||
match immediate {
|
match immediate {
|
||||||
Immediate::Byte(b) => DvmValue::Byte(*b),
|
Immediate::Byte(b) => DvmValue::Byte(*b),
|
||||||
@ -214,137 +275,220 @@ fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
|||||||
Immediate::Double(d) => DvmValue::Double(*d),
|
Immediate::Double(d) => DvmValue::Double(*d),
|
||||||
Immediate::Usize(s) => DvmValue::USize(*s),
|
Immediate::Usize(s) => DvmValue::USize(*s),
|
||||||
Immediate::Boolean(b) => DvmValue::Boolean(*b),
|
Immediate::Boolean(b) => DvmValue::Boolean(*b),
|
||||||
Immediate::ConstantPointer {
|
Immediate::Constant(c) => constant_to_value(c),
|
||||||
raw_pointer,
|
|
||||||
length,
|
|
||||||
} => DvmValue::ConstantPointer(DvmPointer {
|
|
||||||
raw_pointer: *raw_pointer,
|
|
||||||
length: *length,
|
|
||||||
}),
|
|
||||||
Immediate::Empty => DvmValue::Empty,
|
Immediate::Empty => DvmValue::Empty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// TODO: find all possible unwraps/expects and wrap with call to dvm_panic
|
||||||
pub fn run(instructions: &[Instruction], context: &mut DvmContext) {
|
pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmContext) {
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
while index < instructions.len() {
|
while index < instructions.len() {
|
||||||
context.current_instruction = Some(instructions[index].clone());
|
state.current_instruction = Some(instructions[index].clone());
|
||||||
index += 1;
|
use Instruction::*;
|
||||||
match &instructions[index] {
|
match &instructions[index] {
|
||||||
Instruction::MoveImmediate {
|
MoveImmediate {
|
||||||
destination,
|
destination,
|
||||||
immediate,
|
immediate,
|
||||||
} => {
|
} => {
|
||||||
write_to_destination(context, destination, immediate_to_value(immediate));
|
write_to_destination(state, destination, immediate_to_value(immediate));
|
||||||
}
|
}
|
||||||
Instruction::Copy {
|
Copy {
|
||||||
source,
|
source,
|
||||||
destination,
|
destination,
|
||||||
} => {
|
} => {
|
||||||
let value = copy_from_source(context, source);
|
let value = copy_from_source(state, source);
|
||||||
write_to_destination(context, destination, value);
|
write_to_destination(state, destination, value);
|
||||||
}
|
}
|
||||||
Instruction::Push { source_register } => {
|
Push { source_register } => {
|
||||||
context
|
state.stack.push(state.registers[*source_register].clone());
|
||||||
.stack
|
|
||||||
.push(context.registers[*source_register].clone());
|
|
||||||
}
|
}
|
||||||
Instruction::Pop {
|
Pop {
|
||||||
destination_register,
|
destination_register,
|
||||||
} => {
|
} => {
|
||||||
let value = context.stack.pop().expect("Stack underflow");
|
let value = state.stack.pop().unwrap_or_else(|| {
|
||||||
context.registers[*destination_register] = value;
|
dvm_panic!(state, "Stack underflow");
|
||||||
|
});
|
||||||
|
if let Some(register_index) = destination_register {
|
||||||
|
state.registers[*register_index] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Instruction::AllocateObject {
|
AllocateObject {
|
||||||
implementation_name,
|
implementation_name,
|
||||||
destination_register,
|
destination_register,
|
||||||
} => {
|
} => {
|
||||||
let implementation = context
|
let implementation = context
|
||||||
.implementations
|
.implementations
|
||||||
.get(implementation_name.as_str())
|
.get(implementation_name.as_str())
|
||||||
.unwrap();
|
.unwrap_or_else(|| {
|
||||||
let object = DvmObject::new(implementation.clone());
|
dvm_panic!(
|
||||||
context.registers[*destination_register] =
|
state,
|
||||||
|
&format!("Cannot find implementation {}", implementation_name)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
let object = DvmObject::new(implementation);
|
||||||
|
state.registers[*destination_register] =
|
||||||
DvmValue::Object(Rc::new(RefCell::new(object)));
|
DvmValue::Object(Rc::new(RefCell::new(object)));
|
||||||
}
|
}
|
||||||
Instruction::InvokeStatic {
|
InvokeStatic {
|
||||||
function_name,
|
function_name,
|
||||||
source_code_location,
|
source_code_location,
|
||||||
} => {
|
} => {
|
||||||
|
// Find function
|
||||||
let static_function = context
|
let static_function = context
|
||||||
.static_functions
|
.static_functions
|
||||||
.get(function_name.as_str())
|
.get(function_name.as_str())
|
||||||
.unwrap()
|
.unwrap_or_else(|| {
|
||||||
|
dvm_panic!(
|
||||||
|
state,
|
||||||
|
&format!("Cannot find static function {}", function_name)
|
||||||
|
);
|
||||||
|
})
|
||||||
.clone();
|
.clone();
|
||||||
push_call_frame(function_name.clone(), source_code_location.clone(), context);
|
|
||||||
run(static_function.instructions(), context);
|
// Do call
|
||||||
pop_call_frame(context);
|
state.stack.push(DvmValue::Empty); // space for return value
|
||||||
|
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||||
|
run(static_function.instructions(), state, context);
|
||||||
|
pop_call_frame(state);
|
||||||
}
|
}
|
||||||
Instruction::InvokeObject {
|
InvokeObject {
|
||||||
object_register,
|
object_register,
|
||||||
function_name,
|
function_name,
|
||||||
source_code_location,
|
source_code_location,
|
||||||
} => {
|
} => {
|
||||||
let object = context.registers[*object_register].expect_object();
|
// Find method and get instructions
|
||||||
let object_ref = object.borrow();
|
let object_value = state.registers[*object_register].clone();
|
||||||
|
let object_rc = object_value.expect_object_or_else(|v| {
|
||||||
|
dvm_panic!(
|
||||||
|
state,
|
||||||
|
&format!("Expected DvmValue::Object, but found {}", object_value)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let object_ref = object_rc.borrow();
|
||||||
let method = object_ref
|
let method = object_ref
|
||||||
.get_method(function_name.as_str())
|
.get_method(function_name.as_str())
|
||||||
.expect(&format!(
|
.unwrap_or_else(|| {
|
||||||
"Cannot find method {} for object {:?}",
|
dvm_panic!(
|
||||||
function_name, object
|
state,
|
||||||
));
|
&format!(
|
||||||
|
"Cannot find method {} for object {:?}",
|
||||||
|
function_name, object_ref
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
let function = method.dm_fn();
|
let function = method.dm_fn();
|
||||||
let instructions = function.instructions();
|
let instructions = function.instructions();
|
||||||
push_call_frame(function_name.clone(), source_code_location.clone(), context);
|
|
||||||
run(instructions, context);
|
// Do call
|
||||||
pop_call_frame(context);
|
state.stack.push(DvmValue::Empty); // space for return value
|
||||||
|
state.stack.push(object_value); // self object
|
||||||
|
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||||
|
run(instructions, state, context);
|
||||||
|
pop_call_frame(state);
|
||||||
|
state.stack.pop(); // self object
|
||||||
}
|
}
|
||||||
Instruction::PlatformCall {
|
InvokeStaticPlatform {
|
||||||
platform_function_name,
|
function_name,
|
||||||
source_code_location,
|
source_code_location,
|
||||||
} => {
|
} => {
|
||||||
|
// Find function
|
||||||
let platform_function = context
|
let platform_function = context
|
||||||
.platform_functions
|
.platform_functions
|
||||||
.get(platform_function_name.as_str())
|
.get(function_name.as_str())
|
||||||
.unwrap()
|
.unwrap_or_else(|| {
|
||||||
.clone();
|
dvm_panic!(
|
||||||
push_call_frame(
|
state,
|
||||||
platform_function_name.clone(),
|
&format!("Cannot find static platform function {}", function_name)
|
||||||
source_code_location.clone(),
|
);
|
||||||
context,
|
});
|
||||||
);
|
|
||||||
platform_function(context);
|
// Do call
|
||||||
pop_call_frame(context);
|
state.stack.push(DvmValue::Empty); // space for return value
|
||||||
|
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||||
|
platform_function(state, context);
|
||||||
|
pop_call_frame(state);
|
||||||
}
|
}
|
||||||
Instruction::Add { .. } => {}
|
InvokeObjectPlatform {
|
||||||
Instruction::Subtract { .. } => {}
|
object_register,
|
||||||
Instruction::Multiply { .. } => {}
|
function_name,
|
||||||
Instruction::Divide { .. } => {}
|
source_code_location,
|
||||||
Instruction::Modulo { .. } => {}
|
} => {
|
||||||
Instruction::Power { .. } => {}
|
// Find function
|
||||||
Instruction::Jump { offset } => {
|
let object_platform_function = context
|
||||||
|
.platform_functions
|
||||||
|
.get(function_name.as_str())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
dvm_panic!(
|
||||||
|
state,
|
||||||
|
&format!("Cannot find object platform function {}", function_name)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get self object
|
||||||
|
let object_value = state.registers[*object_register].clone();
|
||||||
|
if !object_value.is_object() {
|
||||||
|
dvm_panic!(
|
||||||
|
state,
|
||||||
|
&format!(
|
||||||
|
"Expected DvmValue::Object, but found DvmValue::{:?}",
|
||||||
|
object_value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do call
|
||||||
|
state.stack.push(DvmValue::Empty); // space for return value
|
||||||
|
state.stack.push(object_value); // self object
|
||||||
|
push_call_frame(function_name.clone(), source_code_location.clone(), state);
|
||||||
|
object_platform_function(state, context);
|
||||||
|
pop_call_frame(state);
|
||||||
|
state.stack.pop(); // self object
|
||||||
|
}
|
||||||
|
Add { .. } => {}
|
||||||
|
Subtract { .. } => {}
|
||||||
|
Multiply { .. } => {}
|
||||||
|
Divide { .. } => {}
|
||||||
|
Modulo { .. } => {}
|
||||||
|
Power { .. } => {}
|
||||||
|
Jump { offset } => {
|
||||||
update_index(&mut index, *offset);
|
update_index(&mut index, *offset);
|
||||||
}
|
}
|
||||||
Instruction::JumpEqual {
|
JumpEqual {
|
||||||
left_register,
|
left_register,
|
||||||
right_register,
|
right_register,
|
||||||
offset,
|
offset,
|
||||||
} => {
|
} => {
|
||||||
let left_value = &context.registers[*left_register];
|
let left_value = &state.registers[*left_register];
|
||||||
let right_value = &context.registers[*right_register];
|
let right_value = &state.registers[*right_register];
|
||||||
if left_value == right_value {
|
if left_value == right_value {
|
||||||
update_index(&mut index, *offset);
|
update_index(&mut index, *offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instruction::JumpNotEqual { .. } => {}
|
JumpNotEqual { .. } => {}
|
||||||
Instruction::JumpLessThan { .. } => {}
|
JumpLessThan { .. } => {}
|
||||||
Instruction::JumpGreaterThan { .. } => {}
|
JumpGreaterThan { .. } => {}
|
||||||
Instruction::JumpLessThanEqual { .. } => {}
|
JumpLessThanEqual { .. } => {}
|
||||||
Instruction::JumpGreaterThanEqual { .. } => {}
|
JumpGreaterThanEqual { .. } => {}
|
||||||
Instruction::Return => {
|
Return => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
mod std_lib;
|
mod std_lib;
|
||||||
|
|
||||||
pub fn init_platform_functions() -> HashMap<String, PlatformFunction> {
|
pub fn get_std_lib_platform_functions() -> HashMap<String, PlatformFunction> {
|
||||||
let mut fns: HashMap<String, PlatformFunction> = HashMap::new();
|
let mut fns: HashMap<String, PlatformFunction> = HashMap::new();
|
||||||
fns.insert(String::from("std::core::print"), dm_print);
|
fns.insert(String::from("std::core::print"), dm_print);
|
||||||
fns.insert(String::from("std::core::println"), dm_println);
|
fns.insert(String::from("std::core::println"), dm_println);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::vm::object::DvmObject;
|
use crate::vm::object::DvmObject;
|
||||||
use crate::vm::value::DvmValue;
|
use crate::vm::value::DvmValue;
|
||||||
use crate::vm::DvmContext;
|
use crate::vm::{DvmContext, DvmState};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -8,12 +8,12 @@ use std::rc::Rc;
|
|||||||
/// // Signature
|
/// // Signature
|
||||||
/// print(m: &(Byte | Int | Long | Double | USize | Boolean | Object | Empty))
|
/// print(m: &(Byte | Int | Long | Double | USize | Boolean | Object | Empty))
|
||||||
/// ```
|
/// ```
|
||||||
pub fn dm_print(context: &mut DvmContext) {
|
pub fn dm_print(state: &mut DvmState, context: &DvmContext) {
|
||||||
print!("{}", get_string(context.pop_stack()));
|
print!("{}", get_string(state.get_stack_argument(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dm_println(context: &mut DvmContext) {
|
pub fn dm_println(state: &mut DvmState, context: &DvmContext) {
|
||||||
println!("{}", get_string(context.pop_stack()));
|
println!("{}", get_string(state.get_stack_argument(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_string(dvm_value: DvmValue) -> String {
|
fn get_string(dvm_value: DvmValue) -> String {
|
||||||
@ -26,29 +26,11 @@ fn get_string(dvm_value: DvmValue) -> String {
|
|||||||
DvmValue::Object(object) => object_to_string(object.clone()),
|
DvmValue::Object(object) => object_to_string(object.clone()),
|
||||||
DvmValue::USize(u) => u.to_string(),
|
DvmValue::USize(u) => u.to_string(),
|
||||||
DvmValue::Array(a) => a.borrow().to_string(),
|
DvmValue::Array(a) => a.borrow().to_string(),
|
||||||
DvmValue::ConstantPointer(p) => p.to_string(),
|
DvmValue::String(s) => s.to_string(),
|
||||||
DvmValue::Empty => String::from("Empty"),
|
DvmValue::Empty => String::from("Empty"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_to_string(object: Rc<RefCell<DvmObject>>) -> String {
|
fn object_to_string(object: Rc<RefCell<DvmObject>>) -> String {
|
||||||
if object.borrow().implementation().fqn() == "std::core::StringImpl" {
|
todo!("Lookup to_string method!")
|
||||||
extract_string_from_string(object.clone())
|
|
||||||
} else {
|
|
||||||
todo!("what happens if we don't have a String?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_string_from_string(string_object: Rc<RefCell<DvmObject>>) -> String {
|
|
||||||
let object_ref = string_object.borrow();
|
|
||||||
let bytes_field_value = object_ref.read_field("bytes");
|
|
||||||
if let DvmValue::ConstantPointer(bytes_ptr) = bytes_field_value {
|
|
||||||
let mut v = Vec::new();
|
|
||||||
for i in 0..bytes_ptr.length {
|
|
||||||
v.push(unsafe { bytes_ptr.raw_pointer.add(i).read() });
|
|
||||||
}
|
|
||||||
String::from_utf8(v).unwrap()
|
|
||||||
} else {
|
|
||||||
panic!("StringImpl.bytes field is not a DvmValue::ConstantPointer.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
6
src/vm/source_code_location.rs
Normal file
6
src/vm/source_code_location.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SourceCodeLocation {
|
||||||
|
pub source_file_name: String,
|
||||||
|
pub line: i64,
|
||||||
|
pub char: i64,
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
use crate::vm::array::DvmArray;
|
use crate::vm::array::DvmArray;
|
||||||
use crate::vm::object::DvmObject;
|
use crate::vm::object::DvmObject;
|
||||||
use crate::vm::pointer::DvmPointer;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -21,8 +20,8 @@ pub enum DvmValue {
|
|||||||
// Array
|
// Array
|
||||||
Array(Rc<RefCell<DvmArray>>),
|
Array(Rc<RefCell<DvmArray>>),
|
||||||
|
|
||||||
// Pointer to constant u8
|
// String
|
||||||
ConstantPointer(DvmPointer),
|
String(Rc<String>),
|
||||||
|
|
||||||
// Null
|
// Null
|
||||||
Empty,
|
Empty,
|
||||||
@ -45,7 +44,7 @@ impl Display for DvmValue {
|
|||||||
DvmValue::Boolean(b) => write!(f, "Boolean({})", b),
|
DvmValue::Boolean(b) => write!(f, "Boolean({})", b),
|
||||||
DvmValue::Object(o) => write!(f, "Object({:p})", &o),
|
DvmValue::Object(o) => write!(f, "Object({:p})", &o),
|
||||||
DvmValue::Array(a) => write!(f, "Array({:p})", &a),
|
DvmValue::Array(a) => write!(f, "Array({:p})", &a),
|
||||||
DvmValue::ConstantPointer(p) => write!(f, "ConstantPointer({})", p),
|
DvmValue::String(s) => write!(f, "String({})", s),
|
||||||
DvmValue::Empty => write!(f, "Empty"),
|
DvmValue::Empty => write!(f, "Empty"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +70,14 @@ impl DvmValue {
|
|||||||
panic!("Expected DvmValue::Int, but found DvmValue::{:?}", self);
|
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 {
|
pub fn expect_long(&self) -> i64 {
|
||||||
if let DvmValue::Long(l) = self {
|
if let DvmValue::Long(l) = self {
|
||||||
@ -103,6 +110,17 @@ impl DvmValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_object_or_else(
|
||||||
|
&self,
|
||||||
|
f: impl FnOnce(&Self) -> DvmObject,
|
||||||
|
) -> Rc<RefCell<DvmObject>> {
|
||||||
|
if let DvmValue::Object(o) = self {
|
||||||
|
o.clone()
|
||||||
|
} else {
|
||||||
|
Rc::new(RefCell::new(f(self)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn map_object<T>(
|
pub fn map_object<T>(
|
||||||
&self,
|
&self,
|
||||||
mapper: impl FnOnce(Rc<RefCell<DvmObject>>) -> T,
|
mapper: impl FnOnce(Rc<RefCell<DvmObject>>) -> T,
|
||||||
@ -136,7 +154,7 @@ impl DvmValue {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_array<T>(
|
pub fn map_array<T>(
|
||||||
&self,
|
&self,
|
||||||
mapper: impl FnOnce(Rc<RefCell<DvmArray>>) -> T,
|
mapper: impl FnOnce(Rc<RefCell<DvmArray>>) -> T,
|
||||||
@ -183,14 +201,19 @@ impl DvmValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_constant_pointer(&self) -> DvmPointer {
|
pub fn expect_string(&self) -> Rc<String> {
|
||||||
if let DvmValue::ConstantPointer(ptr) = self {
|
if let DvmValue::String(s) = self {
|
||||||
ptr.clone()
|
s.clone()
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!("Expected DvmValue::String, but found DvmValue::{:?}", self);
|
||||||
"Expected DvmValue::ConstantPointer, but found DvmValue::{:?}",
|
}
|
||||||
self
|
}
|
||||||
);
|
|
||||||
|
pub fn expect_string_or_else(&self, f: impl FnOnce(&Self) -> String) -> Rc<String> {
|
||||||
|
if let DvmValue::String(s) = self {
|
||||||
|
s.clone()
|
||||||
|
} else {
|
||||||
|
Rc::new(f(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user