More refactoring of dvm; add DvmValue::String and related.
This commit is contained in:
		
							parent
							
								
									172e82025d
								
							
						
					
					
						commit
						26d87acff5
					
				@ -16,7 +16,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 +30,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 +60,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 +89,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 +104,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 +123,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,4 +1,5 @@
 | 
				
			|||||||
use std::rc::Rc;
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					use crate::vm::constant::DvmConstant;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub enum Instruction {
 | 
					pub enum Instruction {
 | 
				
			||||||
@ -29,8 +30,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 +113,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,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										309
									
								
								src/vm/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								src/vm/mod.rs
									
									
									
									
									
								
							@ -1,4 +1,5 @@
 | 
				
			|||||||
mod array;
 | 
					mod array;
 | 
				
			||||||
 | 
					mod constant;
 | 
				
			||||||
mod field;
 | 
					mod field;
 | 
				
			||||||
mod function;
 | 
					mod function;
 | 
				
			||||||
pub mod implementation;
 | 
					pub mod implementation;
 | 
				
			||||||
@ -15,10 +16,11 @@ 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, SourceCodeLocation};
 | 
				
			||||||
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 std::cell::RefCell;
 | 
					use std::cell::RefCell;
 | 
				
			||||||
@ -26,22 +28,22 @@ 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) {
 | 
					fn dvm_panic(state: &DvmState, message: &str) {
 | 
				
			||||||
    println!("----");
 | 
					    println!("----");
 | 
				
			||||||
    println!("Deimos Virtual Machine: Panic!");
 | 
					    println!("Deimos Virtual Machine: Panic!");
 | 
				
			||||||
    println!("{}", message);
 | 
					    println!("{}", message);
 | 
				
			||||||
    println!("----");
 | 
					    println!("----");
 | 
				
			||||||
    println!("Current Instruction: {:?}", context.current_instruction);
 | 
					    println!("Current Instruction: {:?}", state.current_instruction);
 | 
				
			||||||
    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{}: {:?}", 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!("----");
 | 
				
			||||||
@ -54,13 +56,33 @@ macro_rules! dvm_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>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl DvmState {
 | 
				
			||||||
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
 | 
					        DvmState {
 | 
				
			||||||
 | 
					            call_stack: vec![],
 | 
				
			||||||
 | 
					            current_instruction: None,
 | 
				
			||||||
 | 
					            registers: vec![],
 | 
				
			||||||
 | 
					            stack: vec![],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn pop_stack(&mut self) -> DvmValue {
 | 
				
			||||||
 | 
					        self.stack.pop().unwrap_or_else(|| {
 | 
				
			||||||
 | 
					            dvm_panic!(self, "Stack underflow!");
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct DvmContext {
 | 
				
			||||||
    implementations: HashMap<String, Rc<DvmImplementation>>,
 | 
					    implementations: HashMap<String, Rc<DvmImplementation>>,
 | 
				
			||||||
    static_functions: HashMap<String, Rc<DvmFunction>>,
 | 
					    static_functions: HashMap<String, Rc<DvmFunction>>,
 | 
				
			||||||
    platform_functions: HashMap<String, PlatformFunction>,
 | 
					    platform_functions: HashMap<String, PlatformFunction>,
 | 
				
			||||||
@ -69,21 +91,11 @@ pub struct DvmContext {
 | 
				
			|||||||
impl DvmContext {
 | 
					impl DvmContext {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        DvmContext {
 | 
					        DvmContext {
 | 
				
			||||||
            call_stack: vec![],
 | 
					 | 
				
			||||||
            current_instruction: None,
 | 
					 | 
				
			||||||
            registers: vec![],
 | 
					 | 
				
			||||||
            stack: vec![],
 | 
					 | 
				
			||||||
            implementations: HashMap::new(),
 | 
					            implementations: HashMap::new(),
 | 
				
			||||||
            static_functions: HashMap::new(),
 | 
					            static_functions: HashMap::new(),
 | 
				
			||||||
            platform_functions: HashMap::new(),
 | 
					            platform_functions: HashMap::new(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn pop_stack(&mut self) -> DvmValue {
 | 
					 | 
				
			||||||
        self.stack.pop().unwrap_or_else(|| {
 | 
					 | 
				
			||||||
            dvm_panic!(self, "Stack underflow!");
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct DvmCall {
 | 
					pub struct DvmCall {
 | 
				
			||||||
@ -114,16 +126,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 +158,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 +176,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 +209,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 +218,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,135 +252,202 @@ 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,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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;
 | 
					        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");
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                state.registers[*destination_register] = 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(|| {
 | 
				
			||||||
 | 
					                        dvm_panic!(
 | 
				
			||||||
 | 
					                            state,
 | 
				
			||||||
 | 
					                            &format!(
 | 
				
			||||||
                                "Cannot find method {} for object {:?}",
 | 
					                                "Cannot find method {} for object {:?}",
 | 
				
			||||||
                        function_name, 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);
 | 
					                    });
 | 
				
			||||||
                pop_call_frame(context);
 | 
					
 | 
				
			||||||
 | 
					                // Do call
 | 
				
			||||||
 | 
					                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;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -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.pop_stack()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.pop_stack()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,8 +21,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 +45,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"),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -103,6 +103,14 @@ 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,
 | 
				
			||||||
@ -183,14 +191,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