ConstantValue initialization
This commit is contained in:
parent
4ee673d5ff
commit
25d3509ccf
4 changed files with 167 additions and 69 deletions
|
@ -1,12 +1,11 @@
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::error::Error as ErrorTrait;
|
use std::error::Error as ErrorTrait;
|
||||||
use core::fmt::{Display, Formatter, Debug};
|
use core::fmt::{Display, Formatter, Debug};
|
||||||
use core::mem::{ discriminant, Discriminant };
|
|
||||||
use core::str::Utf8Error;
|
use core::str::Utf8Error;
|
||||||
|
|
||||||
use crate::accessmasks::*;
|
use crate::accessmasks::*;
|
||||||
use crate::bytecode::Bytecode;
|
use crate::bytecode::Bytecode;
|
||||||
use crate::constantpool::{ ConstantPoolInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantClassInfo, ConstantNameAndTypeInfo };
|
use crate::constantpool::{ ConstantPoolInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo };
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -164,14 +163,14 @@ impl JavaClassFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_classname(&self) -> Result<String, Error> {
|
pub fn get_classname(&self) -> Result<String, Error> {
|
||||||
let class_info_entry = pool_entry(&self.constant_pool, self.this_class as usize)?;
|
let class_info_entry = self.pool_entry(self.this_class)?;
|
||||||
|
|
||||||
let class_info_entry = match class_info_entry {
|
let class_info_entry = match class_info_entry {
|
||||||
ConstantPoolInfo::Class(data) => data,
|
ConstantPoolInfo::Class(data) => data,
|
||||||
_ => return Err(Error::BadFileError(format!("Invalid this_class index, expected index to ClassInfo but found {:?}", class_info_entry)))
|
_ => return Err(Error::BadFileError(format!("Invalid this_class index, expected index to ClassInfo but found {:?}", class_info_entry)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let name_entry = pool_entry(&self.constant_pool, class_info_entry.name_index.into())?;
|
let name_entry = self.pool_entry(class_info_entry.name_index.into())?;
|
||||||
let name_entry = match name_entry {
|
let name_entry = match name_entry {
|
||||||
ConstantPoolInfo::Utf8(utf8data) => utf8data,
|
ConstantPoolInfo::Utf8(utf8data) => utf8data,
|
||||||
_ => return Err(Error::BadFileError(format!("Invalid class_info.name_index from this_class, expected index to Utf8 but found {:?}", name_entry)))
|
_ => return Err(Error::BadFileError(format!("Invalid class_info.name_index from this_class, expected index to Utf8 but found {:?}", name_entry)))
|
||||||
|
@ -192,28 +191,12 @@ impl JavaClassFile {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typed_pool_entry(&self, index: u16, variant: Discriminant<ConstantPoolInfo>) -> Result<&ConstantPoolInfo, Error> {
|
fn pool_entry(&self, index: u16) -> Result<&ConstantPoolInfo, Error> {
|
||||||
let pool_entry = &self.constant_pool[(index - 1) as usize];
|
return pool_entry(&self.constant_pool, index);
|
||||||
|
|
||||||
if discriminant(pool_entry) != variant {
|
|
||||||
return Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type {:#?} but found {:#?}", index, self.get_classname()?, variant, discriminant(pool_entry))));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(pool_entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pool_methodref_entry(&self, index: u16) -> Result<&ConstantMethodRefInfo, Error> {
|
pub fn pool_methodref_entry(&self, index: u16) -> Result<&ConstantMethodRefInfo, Error> {
|
||||||
let pool_entry = self.typed_pool_entry(
|
let pool_entry = self.pool_entry(index)?;
|
||||||
index,
|
|
||||||
discriminant(
|
|
||||||
&ConstantPoolInfo::MethodRef(
|
|
||||||
ConstantMethodRefInfo {
|
|
||||||
class_index: 0,
|
|
||||||
name_and_type_index: 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let methodref_entry = match pool_entry {
|
let methodref_entry = match pool_entry {
|
||||||
ConstantPoolInfo::MethodRef(data) => data,
|
ConstantPoolInfo::MethodRef(data) => data,
|
||||||
|
@ -224,29 +207,38 @@ impl JavaClassFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pool_class_entry(&self, index: u16) -> Result<&ConstantClassInfo, Error> {
|
pub fn pool_class_entry(&self, index: u16) -> Result<&ConstantClassInfo, Error> {
|
||||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::Class(ConstantClassInfo {name_index: 0})))?;
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
return match pool_entry {
|
return match pool_entry {
|
||||||
ConstantPoolInfo::Class(data) => Ok(data),
|
ConstantPoolInfo::Class(data) => Ok(data),
|
||||||
_ => unreachable!(),
|
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type Class but found {:?}", index, self.get_classname()?, pool_entry)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pool_utf8_entry(&self, index: u16) -> Result<&ConstantUtf8Info, Error> {
|
pub fn pool_utf8_entry(&self, index: u16) -> Result<&ConstantUtf8Info, Error> {
|
||||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::Utf8(ConstantUtf8Info {utf8: "".to_string()})))?;
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
return match pool_entry {
|
return match pool_entry {
|
||||||
ConstantPoolInfo::Utf8(data) => Ok(data),
|
ConstantPoolInfo::Utf8(data) => Ok(data),
|
||||||
_ => unreachable!(),
|
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type Utf8 but found {:?}", index, self.get_classname()?, pool_entry)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pool_int_entry(&self, index: u16) -> Result<&ConstantIntegerInfo, Error> {
|
||||||
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
|
return match pool_entry {
|
||||||
|
ConstantPoolInfo::Integer(data) => Ok(data),
|
||||||
|
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type Integer but found {:?}", index, self.get_classname()?, pool_entry)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pool_nameandtype_entry(&self, index: u16) -> Result<&ConstantNameAndTypeInfo, Error> {
|
pub fn pool_nameandtype_entry(&self, index: u16) -> Result<&ConstantNameAndTypeInfo, Error> {
|
||||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo {name_index: 0, descriptor_index: 0})))?;
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
return match pool_entry {
|
return match pool_entry {
|
||||||
ConstantPoolInfo::NameAndType(data) => Ok(data),
|
ConstantPoolInfo::NameAndType(data) => Ok(data),
|
||||||
_ => unreachable!(),
|
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type NameAndType but found {:?}", index, self.get_classname()?, pool_entry)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +311,7 @@ impl FieldInfo {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConstantValueAttributeData {
|
pub struct ConstantValueAttributeData {
|
||||||
constant_value_index: u16,
|
pub constant_value_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -970,13 +962,13 @@ pub fn read_u8(reader: &mut dyn Read) -> Result<u8, std::io::Error> {
|
||||||
return Ok(u8::from_be_bytes(u8_buffer));
|
return Ok(u8::from_be_bytes(u8_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pool_entry<'a>(pool: &Box<[ConstantPoolInfo]>, index: usize) -> Result<&ConstantPoolInfo, Error> {
|
fn pool_entry(constant_pool: &Box<[ConstantPoolInfo]>, index: u16) -> Result<&ConstantPoolInfo, Error> {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
return Err(Error::BadFileError(format!("Bad pool index: 0")));
|
return Err(Error::BadFileError(format!("Bad pool index: 0")));
|
||||||
}
|
}
|
||||||
if index - 1 >= pool.len() {
|
if usize::from(index - 1) >= constant_pool.len() {
|
||||||
return Err(Error::BadFileError(format!("Bad pool index: {}", index - 1)));
|
return Err(Error::BadFileError(format!("Bad pool index: {}", index - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(&pool[index - 1]);
|
return Ok(&constant_pool[usize::from(index - 1)]);
|
||||||
}
|
}
|
||||||
|
|
108
src/heap_area.rs
108
src/heap_area.rs
|
@ -1,8 +1,8 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::accessmasks::FieldAccessFlag;
|
use crate::accessmasks::FieldAccessFlag;
|
||||||
use crate::stackframe::StackValue;
|
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo, AbstractTypeKind };
|
||||||
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo };
|
use crate::jvm::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HeapArea {
|
pub struct HeapArea {
|
||||||
|
@ -21,6 +21,10 @@ impl HeapArea {
|
||||||
static_area: StaticArea::default(),
|
static_area: StaticArea::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_static(&mut self, class: &JavaClassFile, class_index: usize) {
|
||||||
|
self.memory_used += self.static_area.make(class, class_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ObjectReference=u32;
|
pub type ObjectReference=u32;
|
||||||
|
@ -56,18 +60,38 @@ pub struct StaticArea {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StaticArea {
|
impl StaticArea {
|
||||||
pub fn make(&mut self, class: &JavaClassFile, class_index: usize) {
|
|
||||||
|
pub fn set(&mut self, class_name: &String, field_name: &String, field_value: FieldValue) -> Result<(), Error> {
|
||||||
|
let static_object = match self.static_objects.get_mut(class_name) {
|
||||||
|
Some(o) => o,
|
||||||
|
None => return Err(Error::RunTimeError(format!("Trying to set '{}.{}={:?}' but there is no such static object.", class_name, field_name, field_value))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_index = match static_object.field_index_from_name(&field_name) {
|
||||||
|
Some(i) => i,
|
||||||
|
None => return Err(Error::RunTimeError(format!("Trying to set '{}.{}={:?}' but there is no such static field on this object.", class_name, field_name, field_value))),
|
||||||
|
};
|
||||||
|
|
||||||
|
field_value.check_type(&static_object.fields[field_index].descriptor, class_name)?;
|
||||||
|
|
||||||
|
static_object.fields[field_index].value = field_value;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make(&mut self, class: &JavaClassFile, class_index: usize) -> usize {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
|
|
||||||
|
let mut fields_cumulative_size = 0;
|
||||||
for field in &class.fields {
|
for field in &class.fields {
|
||||||
if field.access_flags & FieldAccessFlag::Static {
|
if field.access_flags & FieldAccessFlag::Static {
|
||||||
fields.push(
|
let new_field = StaticField {
|
||||||
StaticField {
|
|
||||||
name: field.name.clone(),
|
name: field.name.clone(),
|
||||||
type_description: field.descriptor.clone(),
|
descriptor: field.descriptor.clone(),
|
||||||
value: StackValue::default_for(field.descriptor),
|
value: FieldValue::default_for(&field.descriptor),
|
||||||
}
|
};
|
||||||
)
|
fields_cumulative_size += std::mem::size_of_val(&new_field);
|
||||||
|
fields.push(new_field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +101,13 @@ impl StaticArea {
|
||||||
methods: Box::new([]),
|
methods: Box::new([]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let object_memory_size = std::mem::size_of_val(&new_object);
|
||||||
|
let field_array_size = std::mem::size_of_val(&new_object.fields);
|
||||||
|
let method_array_size = std::mem::size_of_val(&new_object.methods);
|
||||||
|
|
||||||
let _ = self.static_objects.insert(class.get_classname().unwrap(), new_object);
|
let _ = self.static_objects.insert(class.get_classname().unwrap(), new_object);
|
||||||
|
|
||||||
|
return object_memory_size + field_array_size + fields_cumulative_size + method_array_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,15 +118,69 @@ pub struct StaticObject {
|
||||||
pub methods: Box<[MethodInfo]>,
|
pub methods: Box<[MethodInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StaticObject {
|
||||||
|
fn field_index_from_name(&self, name: &String) -> Option<usize> {
|
||||||
|
for (index, field) in self.fields.iter().enumerate() {
|
||||||
|
if field.name == *name {
|
||||||
|
return Some(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StaticField {
|
pub struct StaticField {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub type_description: AbstractTypeDescription,
|
pub descriptor: AbstractTypeDescription,
|
||||||
pub value: StackValue,
|
pub value: FieldValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectField {
|
pub struct ObjectField {
|
||||||
pub type_description: AbstractTypeDescription,
|
pub type_description: AbstractTypeDescription,
|
||||||
pub value: StackValue,
|
pub value: FieldValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FieldValue {
|
||||||
|
Boolean(bool),
|
||||||
|
Byte(u8),
|
||||||
|
Char(u16),
|
||||||
|
Short(i16),
|
||||||
|
Int(i32),
|
||||||
|
Float(f32),
|
||||||
|
Reference(ObjectReference),
|
||||||
|
Double(f64),
|
||||||
|
Long(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FieldValue {
|
||||||
|
fn check_type(&self, t: &AbstractTypeDescription, class_name: &String) -> Result<(), Error> {
|
||||||
|
let default_val = FieldValue::default_for(t);
|
||||||
|
|
||||||
|
return if std::mem::discriminant(&default_val) != std::mem::discriminant(self) {
|
||||||
|
Err(Error::RunTimeError(format!("Type Mismatch: trying to set {:?} on a field of type {:?} in class {}", self, default_val, class_name)))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_for(t: &AbstractTypeDescription) -> Self {
|
||||||
|
if t.array_level != 0 {
|
||||||
|
return Self::Reference(0);
|
||||||
|
}
|
||||||
|
match &t.kind {
|
||||||
|
AbstractTypeKind::Void() => unreachable!(),
|
||||||
|
AbstractTypeKind::Byte() => Self::Byte(0),
|
||||||
|
AbstractTypeKind::Char() => Self::Char(0),
|
||||||
|
AbstractTypeKind::Double() => Self::Double(0.0),
|
||||||
|
AbstractTypeKind::Float() => Self::Float(0.0),
|
||||||
|
AbstractTypeKind::Int() => Self::Int(0),
|
||||||
|
AbstractTypeKind::Long() => Self::Long(0),
|
||||||
|
AbstractTypeKind::Classname(_) => Self::Reference(0),
|
||||||
|
AbstractTypeKind::Short() => Self::Short(0),
|
||||||
|
AbstractTypeKind::Boolean() => Self::Boolean(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
49
src/jvm.rs
49
src/jvm.rs
|
@ -3,14 +3,14 @@ use core::fmt::{Display, Formatter};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::error::Error as ErrorTrait;
|
use std::error::Error as ErrorTrait;
|
||||||
|
|
||||||
use crate::accessmasks::{ ClassAccessFlagMask, ClassAccessFlag, MethodAccessFlagMask, MethodAccessFlag};
|
use crate::accessmasks::{ ClassAccessFlagMask, ClassAccessFlag, MethodAccessFlagMask, MethodAccessFlag, FieldAccessFlag };
|
||||||
use crate::bytecode::{ Bytecode, Instruction };
|
use crate::bytecode::{ Bytecode, Instruction };
|
||||||
use crate::classfile;
|
use crate::classfile;
|
||||||
use crate::classfile::{ JavaClassFile, MethodInfo, MethodDescriptor, AbstractTypeDescription, AbstractTypeKind, AttributeInfo, AttributeData, CodeAttributeData };
|
use crate::classfile::{ JavaClassFile, MethodInfo, MethodDescriptor, AbstractTypeDescription, AbstractTypeKind, AttributeInfo, AttributeData, CodeAttributeData, ConstantValueAttributeData };
|
||||||
use crate::classstore;
|
use crate::classstore;
|
||||||
use crate::classstore::ClassStore;
|
use crate::classstore::ClassStore;
|
||||||
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
|
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
|
||||||
use crate::heap_area::HeapArea;
|
use crate::heap_area::{ HeapArea, FieldValue };
|
||||||
use crate::stackframe;
|
use crate::stackframe;
|
||||||
use crate::stackframe::{ StackFrame, StackValue, OperandStack };
|
use crate::stackframe::{ StackFrame, StackValue, OperandStack };
|
||||||
|
|
||||||
|
@ -173,10 +173,49 @@ impl JVM {
|
||||||
let class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
|
let class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
|
||||||
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
|
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
|
||||||
|
|
||||||
// TODO: Static Stuff
|
self.heap_area.make_static(class_file, class_idx);
|
||||||
self.heap_area.static_area.make(class_file, class_idx);
|
|
||||||
|
|
||||||
// TODO: ConstantValue Attributes (final)
|
// TODO: ConstantValue Attributes (final)
|
||||||
|
for field in &class_file.fields {
|
||||||
|
if field.access_flags & FieldAccessFlag::Static {
|
||||||
|
let cvalue_attrs: Vec<&ConstantValueAttributeData> = (&field.attributes).iter()
|
||||||
|
.filter(|a| match a.data { AttributeData::ConstantValue(_) => true, _ => false })
|
||||||
|
.map(|a| match &a.data { AttributeData::ConstantValue(c) => c, _ => unreachable!() })
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert!(cvalue_attrs.len() < 2);
|
||||||
|
// TODO: Throw error
|
||||||
|
|
||||||
|
if cvalue_attrs.len() == 1 {
|
||||||
|
let constant_value_info = cvalue_attrs[0];
|
||||||
|
|
||||||
|
assert!(field.descriptor.array_level == 0);
|
||||||
|
// TODO: Throw Error
|
||||||
|
|
||||||
|
let field_value = match field.descriptor.kind {
|
||||||
|
AbstractTypeKind::Boolean() => {
|
||||||
|
let int_entry = class_file.pool_int_entry(constant_value_info.constant_value_index)?;
|
||||||
|
|
||||||
|
FieldValue::Boolean(int_entry.value != 0)
|
||||||
|
},
|
||||||
|
AbstractTypeKind::Int() => {
|
||||||
|
let int_entry = class_file.pool_int_entry(constant_value_info.constant_value_index)?;
|
||||||
|
|
||||||
|
FieldValue::Int(int_entry.value)
|
||||||
|
},
|
||||||
|
AbstractTypeKind::Short() => {
|
||||||
|
let int_entry = class_file.pool_int_entry(constant_value_info.constant_value_index)?;
|
||||||
|
|
||||||
|
FieldValue::Short(int_entry.value as i16)
|
||||||
|
},
|
||||||
|
_ => todo!()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.heap_area.static_area.set(&class_file.get_classname()?, &field.name, field_value)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Push clinit function
|
// TODO: Push clinit function
|
||||||
|
|
||||||
self.class_store.set_init(class_idx, true);
|
self.class_store.set_init(class_idx, true);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::classfile::{ JavaClassFile, AttributeData, AbstractTypeDescription };
|
use crate::classfile::{ JavaClassFile, AttributeData };
|
||||||
use crate::heap_area::ObjectReference;
|
use crate::heap_area::ObjectReference;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -18,23 +18,6 @@ pub enum StackValue {
|
||||||
Empty(),
|
Empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackValue {
|
|
||||||
fn default_for(t: AbstractTypeDescription) -> Self {
|
|
||||||
match t {
|
|
||||||
AbstractTypeDescription::Void() => unreachable!(),
|
|
||||||
AbstractTypeDescription::Byte() => StackValue::Byte(0),
|
|
||||||
AbstractTypeDescription::Char() => StackValue::Char(0),
|
|
||||||
AbstractTypeDescription::Double() => StackValue::Double(0),
|
|
||||||
AbstractTypeDescription::Float() => ,
|
|
||||||
AbstractTypeDescription::Int() => ,
|
|
||||||
AbstractTypeDescription::Long() => ,
|
|
||||||
AbstractTypeDescription::Classname(String) => ,
|
|
||||||
AbstractTypeDescription::Short() => ,
|
|
||||||
AbstractTypeDescription::Boolean() => ,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OperandStack {
|
pub struct OperandStack {
|
||||||
stack: Box<[StackValue]>,
|
stack: Box<[StackValue]>,
|
||||||
|
|
Loading…
Reference in a new issue