Yay! Class lookup and allocation e2e.
This commit is contained in:
parent
0e24ce1784
commit
f7e8cef380
@ -41,6 +41,9 @@ pub fn std_core_println(args: &[Value]) -> Result<Value, Box<dyn Error>> {
|
|||||||
None => Err(Box::new(StdCoreError::new("Missing to_print arg"))),
|
None => Err(Box::new(StdCoreError::new("Missing to_print arg"))),
|
||||||
Some(to_print) => {
|
Some(to_print) => {
|
||||||
match to_print {
|
match to_print {
|
||||||
|
Value::Object(o) => {
|
||||||
|
println!("{}", o.borrow());
|
||||||
|
}
|
||||||
Value::Int(i) => {
|
Value::Int(i) => {
|
||||||
println!("{}", i);
|
println!("{}", i);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use dvm_lib::vm::function::Function;
|
|||||||
use dvm_lib::vm::operand::Operand;
|
use dvm_lib::vm::operand::Operand;
|
||||||
use dvm_lib::vm::{CallStack, DvmContext, call};
|
use dvm_lib::vm::{CallStack, DvmContext, call};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usize) {
|
pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usize) {
|
||||||
let input = std::fs::read_to_string(script).unwrap();
|
let input = std::fs::read_to_string(script).unwrap();
|
||||||
@ -51,7 +52,7 @@ pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usiz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
let (ir_classes, mut ir_functions) = compilation_unit.to_ir(&symbol_table);
|
||||||
|
|
||||||
if show_ir {
|
if show_ir {
|
||||||
for ir_function in &ir_functions {
|
for ir_function in &ir_functions {
|
||||||
@ -68,6 +69,11 @@ pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usiz
|
|||||||
functions.push(function);
|
functions.push(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let classes = ir_classes
|
||||||
|
.iter()
|
||||||
|
.map(|ir_class| ir_class.to_vm_class())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if show_asm {
|
if show_asm {
|
||||||
for function in &functions {
|
for function in &functions {
|
||||||
println!("{}", function);
|
println!("{}", function);
|
||||||
@ -85,6 +91,12 @@ pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usiz
|
|||||||
.insert(function.name_owned(), function);
|
.insert(function.name_owned(), function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for class in classes {
|
||||||
|
dvm_context
|
||||||
|
.classes_mut()
|
||||||
|
.insert(class.fqn().into(), Rc::new(class));
|
||||||
|
}
|
||||||
|
|
||||||
for (name, content) in &constants_table.string_constants() {
|
for (name, content) in &constants_table.string_constants() {
|
||||||
dvm_context.constants_mut().insert(
|
dvm_context.constants_mut().insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
use crate::ast::constructor::Constructor;
|
use crate::ast::constructor::Constructor;
|
||||||
use crate::ast::field::Field;
|
use crate::ast::field::Field;
|
||||||
use crate::ast::fqn_context::FqnContext;
|
use crate::ast::fqn_context::FqnContext;
|
||||||
|
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||||
|
use crate::ir::ir_class::{IrClass, IrField};
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
use crate::symbol::class_symbol::ClassSymbol;
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -43,16 +46,17 @@ impl Class {
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
fqn_context: &mut FqnContext,
|
fqn_context: &mut FqnContext,
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
// 0. Push class name on fqn
|
|
||||||
fqn_context.push(self.declared_name.clone());
|
|
||||||
|
|
||||||
// 1. insert class symbol
|
// 1. insert class symbol
|
||||||
let to_insert = ClassSymbol::new(
|
let to_insert = ClassSymbol::new(
|
||||||
&self.declared_name,
|
&self.declared_name,
|
||||||
self.declared_name_source_range.clone(),
|
self.declared_name_source_range.clone(),
|
||||||
|
fqn_context.resolve(&self.declared_name),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 1a. Push class name on fqn
|
||||||
|
fqn_context.push(self.declared_name.clone());
|
||||||
|
|
||||||
let class_symbol = symbol_table
|
let class_symbol = symbol_table
|
||||||
.insert_class_symbol(to_insert)
|
.insert_class_symbol(to_insert)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
@ -260,7 +264,7 @@ impl Class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
pub fn to_ir(&self, symbol_table: &SymbolTable) -> (IrClass, Vec<IrFunction>) {
|
||||||
let mut ir_functions: Vec<IrFunction> = vec![];
|
let mut ir_functions: Vec<IrFunction> = vec![];
|
||||||
if let Some(constructor) = &self.constructor {
|
if let Some(constructor) = &self.constructor {
|
||||||
ir_functions.push(constructor.to_ir(
|
ir_functions.push(constructor.to_ir(
|
||||||
@ -277,77 +281,23 @@ impl Class {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_functions
|
let class_symbol = self.class_symbol.as_ref().unwrap().borrow();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
let ir_class = IrClass::new(
|
||||||
mod tests {
|
class_symbol.declared_name_owned(),
|
||||||
use super::*;
|
fqn_parts_to_string(class_symbol.fqn_parts()).into(),
|
||||||
use crate::constants_table::ConstantsTable;
|
self.fields
|
||||||
use crate::parser::parse_compilation_unit;
|
.iter()
|
||||||
|
.map(|field| {
|
||||||
#[test]
|
IrField::new(
|
||||||
fn complete_example_no_diagnostics() {
|
field.declared_name().into(),
|
||||||
let parse_result = parse_compilation_unit(
|
field.field_symbol().borrow().field_index(),
|
||||||
"
|
field.field_symbol().borrow().type_info().clone(),
|
||||||
class Foo
|
)
|
||||||
mut bar: Int = 42
|
})
|
||||||
|
.collect(),
|
||||||
ctor(_bar: Int)
|
|
||||||
end
|
|
||||||
|
|
||||||
fn baz() -> Int
|
|
||||||
bar
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Qux
|
|
||||||
fn foo() -> Foo
|
|
||||||
Foo(42)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
",
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut compilation_unit = match parse_result {
|
(ir_class, ir_functions)
|
||||||
Ok(compilation_unit) => compilation_unit,
|
|
||||||
Err(diagnostics) => {
|
|
||||||
panic!("{:?}", diagnostics);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
match compilation_unit.gather_declared_names(&mut symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
panic!("{:?}", diagnostics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match compilation_unit.check_name_usages(&symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
panic!("{:?}", diagnostics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match compilation_unit.type_check(&symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
panic!("{:?}", diagnostics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
|
||||||
for ir_function in &mut ir_functions {
|
|
||||||
println!("{}", ir_function);
|
|
||||||
}
|
|
||||||
let mut constants_table = ConstantsTable::new();
|
|
||||||
for ir_function in &mut ir_functions {
|
|
||||||
let (_, stack_size) = ir_function.assign_registers(8);
|
|
||||||
let vm_function = ir_function.assemble(stack_size, &mut constants_table);
|
|
||||||
println!("{}", vm_function)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use crate::ast::extern_function::ExternFunction;
|
|||||||
use crate::ast::fqn_context::FqnContext;
|
use crate::ast::fqn_context::FqnContext;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_class::IrClass;
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
|
|
||||||
@ -138,16 +139,21 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
pub fn to_ir(&self, symbol_table: &SymbolTable) -> (Vec<IrClass>, Vec<IrFunction>) {
|
||||||
let mut functions: Vec<IrFunction> = vec![];
|
let mut functions: Vec<IrFunction> = vec![];
|
||||||
|
let mut classes: Vec<IrClass> = vec![];
|
||||||
|
|
||||||
self.functions
|
self.functions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| f.to_ir(symbol_table, None))
|
.map(|f| f.to_ir(symbol_table, None))
|
||||||
.for_each(|f| functions.push(f));
|
.for_each(|f| functions.push(f));
|
||||||
self.classes
|
|
||||||
.iter()
|
for class in &self.classes {
|
||||||
.flat_map(|c| c.to_ir(symbol_table))
|
let (class, mut class_functions) = class.to_ir(symbol_table);
|
||||||
.for_each(|f| functions.push(f));
|
functions.append(&mut class_functions);
|
||||||
functions
|
classes.push(class);
|
||||||
|
}
|
||||||
|
|
||||||
|
(classes, functions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ pub mod extern_function;
|
|||||||
pub mod field;
|
pub mod field;
|
||||||
pub mod fqn;
|
pub mod fqn;
|
||||||
pub mod fqn_context;
|
pub mod fqn_context;
|
||||||
mod fqn_util;
|
pub mod fqn_util;
|
||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub mod integer_literal;
|
pub mod integer_literal;
|
||||||
|
|||||||
61
dmc-lib/src/ir/ir_class.rs
Normal file
61
dmc-lib/src/ir/ir_class.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use dvm_lib::vm::class::{Class, Field};
|
||||||
|
use dvm_lib::vm::type_info::TypeInfo as VmTypeInfo;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct IrClass {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
fqn: Rc<str>,
|
||||||
|
fields: Vec<IrField>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrClass {
|
||||||
|
pub fn new(declared_name: Rc<str>, fqn: Rc<str>, fields: Vec<IrField>) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name,
|
||||||
|
fqn,
|
||||||
|
fields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_vm_class(&self) -> Class {
|
||||||
|
Class::new(
|
||||||
|
self.declared_name.clone(),
|
||||||
|
self.fqn.clone(),
|
||||||
|
self.fields.iter().map(IrField::to_vm_field).collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrField {
|
||||||
|
debug_name: Rc<str>,
|
||||||
|
field_index: usize,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrField {
|
||||||
|
pub fn new(debug_name: Rc<str>, field_index: usize, type_info: TypeInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name,
|
||||||
|
field_index,
|
||||||
|
type_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_vm_field(&self) -> Field {
|
||||||
|
Field::new(
|
||||||
|
self.debug_name.clone(),
|
||||||
|
self.field_index,
|
||||||
|
match &self.type_info {
|
||||||
|
TypeInfo::Integer => VmTypeInfo::Int,
|
||||||
|
TypeInfo::Double => VmTypeInfo::Double,
|
||||||
|
TypeInfo::String => VmTypeInfo::String,
|
||||||
|
TypeInfo::ClassInstance(class_symbol) => VmTypeInfo::ClassInstance(
|
||||||
|
fqn_parts_to_string(class_symbol.borrow().fqn_parts()).into(),
|
||||||
|
),
|
||||||
|
_ => panic!(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ pub mod ir_allocate;
|
|||||||
pub mod ir_assign;
|
pub mod ir_assign;
|
||||||
pub mod ir_block;
|
pub mod ir_block;
|
||||||
pub mod ir_call;
|
pub mod ir_call;
|
||||||
|
pub mod ir_class;
|
||||||
pub mod ir_expression;
|
pub mod ir_expression;
|
||||||
pub mod ir_function;
|
pub mod ir_function;
|
||||||
pub mod ir_get_field_ref;
|
pub mod ir_get_field_ref;
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use std::rc::Rc;
|
|||||||
pub struct ClassSymbol {
|
pub struct ClassSymbol {
|
||||||
declared_name: Rc<str>,
|
declared_name: Rc<str>,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
|
fqn_parts: Vec<Rc<str>>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
||||||
fields: HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>>,
|
fields: HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>>,
|
||||||
@ -20,11 +21,13 @@ impl ClassSymbol {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
declared_name: &Rc<str>,
|
declared_name: &Rc<str>,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
|
fqn_parts: Vec<Rc<str>>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
declared_name: declared_name.clone(),
|
declared_name: declared_name.clone(),
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
|
fqn_parts,
|
||||||
is_extern,
|
is_extern,
|
||||||
constructor_symbol: None,
|
constructor_symbol: None,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
@ -32,6 +35,10 @@ impl ClassSymbol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fqn_parts(&self) -> &[Rc<str>] {
|
||||||
|
&self.fqn_parts
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_constructor_symbol(
|
pub fn set_constructor_symbol(
|
||||||
&mut self,
|
&mut self,
|
||||||
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
||||||
|
|||||||
57
dvm-lib/src/vm/class.rs
Normal file
57
dvm-lib/src/vm/class.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use crate::vm::type_info::TypeInfo;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct Class {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
fqn: Rc<str>,
|
||||||
|
fields: Vec<Field>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Class {
|
||||||
|
pub fn new(declared_name: Rc<str>, fqn: Rc<str>, fields: Vec<Field>) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name,
|
||||||
|
fqn,
|
||||||
|
fields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fqn(&self) -> &str {
|
||||||
|
&self.fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> &[Field] {
|
||||||
|
&self.fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Class {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.fqn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Class {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.fqn == other.fqn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Class {}
|
||||||
|
|
||||||
|
pub struct Field {
|
||||||
|
debug_name: Rc<str>,
|
||||||
|
field_index: usize,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Field {
|
||||||
|
pub fn new(debug_name: Rc<str>, field_index: usize, type_info: TypeInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name,
|
||||||
|
field_index,
|
||||||
|
type_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,9 @@
|
|||||||
use crate::instruction::Instruction;
|
use crate::instruction::Instruction;
|
||||||
use crate::platform_function::PlatformFunction;
|
use crate::platform_function::PlatformFunction;
|
||||||
|
use crate::vm::class::Class;
|
||||||
use crate::vm::constant::Constant;
|
use crate::vm::constant::Constant;
|
||||||
use crate::vm::function::Function;
|
use crate::vm::function::Function;
|
||||||
|
use crate::vm::object::get_object;
|
||||||
use crate::vm::operand::Operand;
|
use crate::vm::operand::Operand;
|
||||||
use crate::vm::operand_helpers::{
|
use crate::vm::operand_helpers::{
|
||||||
add_operand_to_value, move_operand_to_value, multiply_operand_to_value, push_operand_to_value,
|
add_operand_to_value, move_operand_to_value, multiply_operand_to_value, push_operand_to_value,
|
||||||
@ -9,19 +11,23 @@ use crate::vm::operand_helpers::{
|
|||||||
};
|
};
|
||||||
use crate::vm::util::*;
|
use crate::vm::util::*;
|
||||||
use crate::vm::value::Value;
|
use crate::vm::value::Value;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub mod class;
|
||||||
pub mod constant;
|
pub mod constant;
|
||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod object;
|
pub mod object;
|
||||||
pub mod operand;
|
pub mod operand;
|
||||||
mod operand_helpers;
|
mod operand_helpers;
|
||||||
|
pub mod type_info;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
pub struct DvmContext {
|
pub struct DvmContext {
|
||||||
|
classes: HashMap<Rc<str>, Rc<Class>>,
|
||||||
functions: HashMap<Rc<str>, Function>,
|
functions: HashMap<Rc<str>, Function>,
|
||||||
platform_functions: HashMap<Rc<str>, PlatformFunction>,
|
platform_functions: HashMap<Rc<str>, PlatformFunction>,
|
||||||
constants: HashMap<Rc<str>, Constant>,
|
constants: HashMap<Rc<str>, Constant>,
|
||||||
@ -30,12 +36,21 @@ pub struct DvmContext {
|
|||||||
impl DvmContext {
|
impl DvmContext {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
classes: HashMap::new(),
|
||||||
functions: HashMap::new(),
|
functions: HashMap::new(),
|
||||||
platform_functions: HashMap::new(),
|
platform_functions: HashMap::new(),
|
||||||
constants: HashMap::new(),
|
constants: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn classes(&self) -> &HashMap<Rc<str>, Rc<Class>> {
|
||||||
|
&self.classes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn classes_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<Class>> {
|
||||||
|
&mut self.classes
|
||||||
|
}
|
||||||
|
|
||||||
pub fn functions(&self) -> &HashMap<Rc<str>, Function> {
|
pub fn functions(&self) -> &HashMap<Rc<str>, Function> {
|
||||||
&self.functions
|
&self.functions
|
||||||
}
|
}
|
||||||
@ -320,11 +335,15 @@ pub fn call<'a>(
|
|||||||
|
|
||||||
/* Object instructions */
|
/* Object instructions */
|
||||||
Instruction::Allocate(class_fqn, destination) => {
|
Instruction::Allocate(class_fqn, destination) => {
|
||||||
// let class = context.classes().get(class_fqn).expect("No such class loaded: {}")
|
let class = context
|
||||||
// let object: Gc<GcCell<Object>> = Object::new(class, heap)
|
.classes()
|
||||||
// let value = Value::Object(object)
|
.get(class_fqn)
|
||||||
// put_value(registers, call_stack.top_mut(), destination, result)
|
.expect(&format!("No such class loaded: {}", class_fqn));
|
||||||
todo!()
|
let object = get_object(class);
|
||||||
|
let as_rc = Rc::new(RefCell::new(object));
|
||||||
|
let value = Value::Object(as_rc);
|
||||||
|
put_value(registers, call_stack.top_mut(), destination, value);
|
||||||
|
call_stack.top_mut().increment_ip();
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction::GetFieldPointer(self_location, field_index, destination) => {
|
Instruction::GetFieldPointer(self_location, field_index, destination) => {
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
|
use crate::vm::class::Class;
|
||||||
use crate::vm::value::Value;
|
use crate::vm::value::Value;
|
||||||
use std::alloc::{Layout, alloc};
|
use std::alloc::{Layout, alloc};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
header: ObjectHeader,
|
header: ObjectHeader,
|
||||||
@ -8,6 +12,10 @@ pub struct Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Object {
|
impl Object {
|
||||||
|
pub fn header(&self) -> &ObjectHeader {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fields(&self) -> &[Value] {
|
pub fn fields(&self) -> &[Value] {
|
||||||
&self.fields
|
&self.fields
|
||||||
}
|
}
|
||||||
@ -17,22 +25,45 @@ impl Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ObjectHeader {
|
impl PartialEq for Object {
|
||||||
field_count: usize,
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
todo!("eq on Object not yet supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_object(field_count: usize) -> Box<Object> {
|
impl Display for Object {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let self_class = &self.header.self_class;
|
||||||
|
write!(f, "{}@{:p}", self_class.fqn(), &self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ObjectHeader {
|
||||||
|
self_class: Rc<Class>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectHeader {
|
||||||
|
pub fn self_class(&self) -> &Rc<Class> {
|
||||||
|
&self.self_class
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this will be more tied to the gc later
|
||||||
|
pub fn get_object(class: &Rc<Class>) -> Box<Object> {
|
||||||
|
let field_count = class.fields().len();
|
||||||
|
|
||||||
let (layout, fields_base) = Layout::array::<Value>(field_count)
|
let (layout, fields_base) = Layout::array::<Value>(field_count)
|
||||||
.and_then(|fields_array_layout| Layout::new::<ObjectHeader>().extend(fields_array_layout))
|
.and_then(|fields_array_layout| Layout::new::<ObjectHeader>().extend(fields_array_layout))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("{:?}", layout);
|
|
||||||
let ptr = unsafe { alloc(layout) };
|
let ptr = unsafe { alloc(layout) };
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
panic!("failed to allocate memory");
|
panic!("failed to allocate memory");
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr.cast::<ObjectHeader>()
|
ptr.cast::<ObjectHeader>().write(ObjectHeader {
|
||||||
.write(ObjectHeader { field_count });
|
self_class: class.clone(),
|
||||||
|
});
|
||||||
let fields_ptr = ptr.add(fields_base).cast::<Value>();
|
let fields_ptr = ptr.add(fields_base).cast::<Value>();
|
||||||
// initialize each field to Value::Null
|
// initialize each field to Value::Null
|
||||||
for i in 0..field_count {
|
for i in 0..field_count {
|
||||||
@ -44,17 +75,3 @@ fn get_object(field_count: usize) -> Box<Object> {
|
|||||||
Box::from_raw(std::ptr::slice_from_raw_parts(ptr as *mut Value, field_count) as *mut Object)
|
Box::from_raw(std::ptr::slice_from_raw_parts(ptr as *mut Value, field_count) as *mut Object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn melt_the_processor() {
|
|
||||||
let mut o = get_object(3);
|
|
||||||
assert_eq!(o.header.field_count, 3);
|
|
||||||
assert_eq!(o.fields.len(), 3);
|
|
||||||
o.fields.fill(Value::Int(42));
|
|
||||||
assert!(o.fields.iter().all(|v| *v == Value::Int(42)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
41
dvm-lib/src/vm/type_info.rs
Normal file
41
dvm-lib/src/vm/type_info.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use crate::vm::class::Class;
|
||||||
|
use crate::vm::value::Value;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub enum TypeInfo {
|
||||||
|
ClassInstance(Rc<str>),
|
||||||
|
Int,
|
||||||
|
Double,
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeInfo {
|
||||||
|
pub fn is_instance_of(&self, value: &Value, classes: &HashMap<Rc<str>, Rc<Class>>) -> bool {
|
||||||
|
match self {
|
||||||
|
TypeInfo::ClassInstance(class_fqn) => match value {
|
||||||
|
Value::Object(o) => {
|
||||||
|
let o_ref = o.borrow();
|
||||||
|
let o_self_class = o_ref.header().self_class();
|
||||||
|
|
||||||
|
let check_class = classes.get(class_fqn);
|
||||||
|
if check_class.is_none() {
|
||||||
|
panic!("No such class {}", class_fqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
*check_class.unwrap() == *o_self_class
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
TypeInfo::Int => {
|
||||||
|
matches!(value, Value::Int(_))
|
||||||
|
}
|
||||||
|
TypeInfo::Double => {
|
||||||
|
matches!(value, Value::Double(_))
|
||||||
|
}
|
||||||
|
TypeInfo::String => {
|
||||||
|
matches!(value, Value::String(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,11 @@
|
|||||||
use crate::vm::object::Object;
|
use crate::vm::object::Object;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
Object(Rc<RefCell<Box<Object>>>),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Double(f64),
|
Double(f64),
|
||||||
String(Rc<str>),
|
String(Rc<str>),
|
||||||
@ -39,18 +40,27 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_object(&self) -> &Rc<RefCell<Object>> {
|
pub fn unwrap_object(&self) -> &Rc<RefCell<Box<Object>>> {
|
||||||
todo!()
|
match self {
|
||||||
|
Value::Object(o) => o,
|
||||||
|
_ => panic!("Attempt to unwrap Object; found {:?}", self),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_object_mut(&mut self) -> &mut Rc<RefCell<Object>> {
|
pub fn unwrap_object_mut(&mut self) -> &mut Rc<RefCell<Box<Object>>> {
|
||||||
todo!()
|
match self {
|
||||||
|
Value::Object(o) => o,
|
||||||
|
_ => panic!("Attempt to unwrap Object; found {:?}", self),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Value::Object(o) => {
|
||||||
|
write!(f, "{}", o.borrow())
|
||||||
|
}
|
||||||
Value::Int(i) => {
|
Value::Int(i) => {
|
||||||
write!(f, "{}", i)
|
write!(f, "{}", i)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ mod e2e_tests {
|
|||||||
use dmc_lib::diagnostic::Diagnostic;
|
use dmc_lib::diagnostic::Diagnostic;
|
||||||
use dmc_lib::parser::parse_compilation_unit;
|
use dmc_lib::parser::parse_compilation_unit;
|
||||||
use dmc_lib::symbol_table::SymbolTable;
|
use dmc_lib::symbol_table::SymbolTable;
|
||||||
|
use dvm_lib::vm::class::Class;
|
||||||
use dvm_lib::vm::constant::{Constant, StringConstant};
|
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||||
use dvm_lib::vm::function::Function;
|
use dvm_lib::vm::function::Function;
|
||||||
use dvm_lib::vm::operand::Operand;
|
use dvm_lib::vm::operand::Operand;
|
||||||
@ -57,7 +58,7 @@ mod e2e_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
let (ir_classes, mut ir_functions) = compilation_unit.to_ir(&symbol_table);
|
||||||
|
|
||||||
let mut functions: Vec<Function> = vec![];
|
let mut functions: Vec<Function> = vec![];
|
||||||
let mut constants_table = ConstantsTable::new();
|
let mut constants_table = ConstantsTable::new();
|
||||||
@ -68,8 +69,19 @@ mod e2e_tests {
|
|||||||
functions.push(function);
|
functions.push(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut classes: Vec<Class> = vec![];
|
||||||
|
for ir_class in &ir_classes {
|
||||||
|
classes.push(ir_class.to_vm_class());
|
||||||
|
}
|
||||||
|
|
||||||
let mut dvm_context = DvmContext::new();
|
let mut dvm_context = DvmContext::new();
|
||||||
|
|
||||||
|
for class in classes {
|
||||||
|
dvm_context
|
||||||
|
.classes_mut()
|
||||||
|
.insert(class.fqn().into(), Rc::new(class));
|
||||||
|
}
|
||||||
|
|
||||||
for function in functions {
|
for function in functions {
|
||||||
dvm_context
|
dvm_context
|
||||||
.functions_mut()
|
.functions_mut()
|
||||||
@ -201,6 +213,41 @@ mod e2e_tests {
|
|||||||
Value::Double(1.0),
|
Value::Double(1.0),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn two_classes() {
|
||||||
|
let context = prepare_context(
|
||||||
|
"
|
||||||
|
class Foo
|
||||||
|
mut bar: Int = 42
|
||||||
|
|
||||||
|
ctor(_bar: Int)
|
||||||
|
end
|
||||||
|
|
||||||
|
fn baz() -> Int
|
||||||
|
bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Qux
|
||||||
|
fn foo() -> Foo
|
||||||
|
Foo(42)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fn foo(n: Int) -> Foo
|
||||||
|
Foo(n)
|
||||||
|
end
|
||||||
|
",
|
||||||
|
);
|
||||||
|
let result = get_result(&context, "foo", &[Value::Int(42)]);
|
||||||
|
assert!(result.is_some());
|
||||||
|
let value = result.unwrap();
|
||||||
|
assert!(matches!(value, Value::Object(_)));
|
||||||
|
let o = value.unwrap_object().borrow();
|
||||||
|
assert_eq!(o.fields().len(), 1);
|
||||||
|
assert_eq!(o.fields()[0].unwrap_int(), 42);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user