Complete sketch of interface between dmc-lib compile functions and other modules.
This commit is contained in:
parent
85e29367a8
commit
01df9a708f
@ -19,7 +19,7 @@ use dvm_lib::instruction::{
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
struct FunctionAssemblyContext<'a> {
|
struct FunctionAssemblyContext<'a> {
|
||||||
type_infos: &'a Vec<IrTypeInfo>,
|
type_infos: &'a [IrTypeInfo],
|
||||||
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
||||||
variable_locations: &'a VariableLocations,
|
variable_locations: &'a VariableLocations,
|
||||||
parameters: &'a [IrParameter],
|
parameters: &'a [IrParameter],
|
||||||
@ -29,7 +29,7 @@ struct FunctionAssemblyContext<'a> {
|
|||||||
|
|
||||||
pub fn assemble_ir_function(
|
pub fn assemble_ir_function(
|
||||||
ir_function: &IrFunction,
|
ir_function: &IrFunction,
|
||||||
type_infos: &Vec<IrTypeInfo>,
|
type_infos: &[IrTypeInfo],
|
||||||
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
||||||
variable_locations: &VariableLocations,
|
variable_locations: &VariableLocations,
|
||||||
constants_table: &mut ConstantsTable,
|
constants_table: &mut ConstantsTable,
|
||||||
|
|||||||
@ -55,6 +55,7 @@ impl IrFunction {
|
|||||||
self.return_type_info.as_ref()
|
self.return_type_info.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
pub fn assign_registers(&self, register_count: usize) -> VariableLocations {
|
pub fn assign_registers(&self, register_count: usize) -> VariableLocations {
|
||||||
if self.blocks.is_empty() {
|
if self.blocks.is_empty() {
|
||||||
return VariableLocations::new(HashMap::new(), HashMap::new());
|
return VariableLocations::new(HashMap::new(), HashMap::new());
|
||||||
@ -66,6 +67,7 @@ impl IrFunction {
|
|||||||
block_assign_registers(block, register_count)
|
block_assign_registers(block, register_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
pub fn assemble(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
type_infos: &Vec<IrTypeInfo>,
|
type_infos: &Vec<IrTypeInfo>,
|
||||||
|
|||||||
@ -1,3 +1,13 @@
|
|||||||
|
use crate::constants_table::ConstantsTable;
|
||||||
|
use crate::ir::assemble::assemble_ir_function;
|
||||||
|
use crate::ir::ir_function::IrFunction;
|
||||||
|
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
||||||
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
|
use crate::ir::register_allocation::block_assign_registers;
|
||||||
|
use crate::ir::variable_locations::VariableLocations;
|
||||||
|
use dvm_lib::vm::function::Function;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod assemble;
|
mod assemble;
|
||||||
mod debug_print;
|
mod debug_print;
|
||||||
pub mod ir_allocate;
|
pub mod ir_allocate;
|
||||||
@ -22,3 +32,36 @@ pub mod ir_variable;
|
|||||||
mod register_allocation;
|
mod register_allocation;
|
||||||
mod util;
|
mod util;
|
||||||
mod variable_locations;
|
mod variable_locations;
|
||||||
|
|
||||||
|
pub fn compile_dvm_function(
|
||||||
|
ir_function: &IrFunction,
|
||||||
|
ir_type_infos: &[IrTypeInfo],
|
||||||
|
ir_variables_to_ir_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
||||||
|
constants_table: &mut ConstantsTable,
|
||||||
|
) -> Function {
|
||||||
|
let variable_locations = assign_registers(ir_function);
|
||||||
|
let instructions = assemble_ir_function(
|
||||||
|
ir_function,
|
||||||
|
ir_type_infos,
|
||||||
|
ir_variables_to_ir_type_infos,
|
||||||
|
&variable_locations,
|
||||||
|
constants_table,
|
||||||
|
);
|
||||||
|
Function::new(
|
||||||
|
ir_function.fqn().into(),
|
||||||
|
ir_function.parameters().len(),
|
||||||
|
variable_locations.stack_size(),
|
||||||
|
instructions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_registers(ir_function: &IrFunction) -> VariableLocations {
|
||||||
|
if ir_function.blocks().is_empty() {
|
||||||
|
return VariableLocations::new(HashMap::new(), HashMap::new());
|
||||||
|
}
|
||||||
|
if ir_function.blocks().len() > 1 {
|
||||||
|
unimplemented!("having more than one block in a function is not yet implemented.")
|
||||||
|
}
|
||||||
|
let block = &ir_function.blocks()[0];
|
||||||
|
block_assign_registers(block, 16) // TODO: make this configurable
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,13 @@
|
|||||||
|
use crate::constants_table::ConstantsTable;
|
||||||
|
use crate::diagnostic::Diagnostics;
|
||||||
|
use crate::ir::compile_dvm_function;
|
||||||
|
use crate::lowering::lower_to_ir;
|
||||||
|
use crate::parser::parse_compilation_unit;
|
||||||
|
use crate::semantic_analysis::analyze_compilation_unit;
|
||||||
|
use dvm_lib::vm::function::Function;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod compile_pipeline;
|
pub mod compile_pipeline;
|
||||||
pub mod constants_table;
|
pub mod constants_table;
|
||||||
@ -19,3 +29,45 @@ pub mod token;
|
|||||||
pub mod type_info;
|
pub mod type_info;
|
||||||
pub mod types_table;
|
pub mod types_table;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
pub type Filename = Rc<str>;
|
||||||
|
pub type FileId = usize;
|
||||||
|
|
||||||
|
pub struct CompileCompilationUnitResult {
|
||||||
|
pub functions: HashMap<Rc<str>, Function>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_compilation_unit(
|
||||||
|
input: &str,
|
||||||
|
constants_table: &mut ConstantsTable,
|
||||||
|
) -> Result<CompileCompilationUnitResult, Diagnostics> {
|
||||||
|
let (compilation_unit, diagnostics) = parse_compilation_unit(input, None);
|
||||||
|
if !diagnostics.is_empty() {
|
||||||
|
return Err(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (analysis_result, diagnostics) = analyze_compilation_unit(&compilation_unit);
|
||||||
|
if !diagnostics.is_empty() {
|
||||||
|
return Err(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lower_to_ir_result = lower_to_ir(
|
||||||
|
&compilation_unit,
|
||||||
|
&analysis_result.symbols,
|
||||||
|
&analysis_result.nodes_to_symbols,
|
||||||
|
&analysis_result.type_infos,
|
||||||
|
&analysis_result.symbols_to_type_infos,
|
||||||
|
&analysis_result.nodes_to_type_infos,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut dvm_functions = HashMap::new();
|
||||||
|
|
||||||
|
for ir_function in &lower_to_ir_result.functions {
|
||||||
|
let dvm_function = compile_dvm_function(ir_function, todo!(), todo!(), constants_table);
|
||||||
|
dvm_functions.insert(dvm_function.name_owned(), dvm_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(CompileCompilationUnitResult {
|
||||||
|
functions: dvm_functions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
use crate::ast::NodeId;
|
use crate::ast::NodeId;
|
||||||
use crate::ast::compilation_unit::CompilationUnit;
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
use crate::compile_pipeline::FileId;
|
|
||||||
use crate::diagnostic::Diagnostics;
|
use crate::diagnostic::Diagnostics;
|
||||||
use crate::semantic_analysis::collect_scopes::collect_scopes;
|
use crate::semantic_analysis::collect_scopes::collect_scopes;
|
||||||
use crate::semantic_analysis::collect_symbols::collect_symbols;
|
use crate::semantic_analysis::collect_symbols::collect_symbols;
|
||||||
use crate::semantic_analysis::collect_types::collect_types;
|
use crate::semantic_analysis::collect_types::collect_types;
|
||||||
use crate::semantic_analysis::resolve_names::resolve_names;
|
use crate::semantic_analysis::resolve_names::resolve_names;
|
||||||
use crate::semantic_analysis::resolve_types::resolve_types;
|
use crate::semantic_analysis::resolve_types::resolve_types;
|
||||||
use crate::semantic_analysis::scope::{Scope, ScopeId};
|
|
||||||
use crate::semantic_analysis::symbol::{Symbol, SymbolId};
|
use crate::semantic_analysis::symbol::{Symbol, SymbolId};
|
||||||
use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId};
|
use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -24,89 +22,53 @@ pub mod symbol;
|
|||||||
pub mod type_info;
|
pub mod type_info;
|
||||||
|
|
||||||
pub struct AnalysisResult {
|
pub struct AnalysisResult {
|
||||||
|
pub symbols: Vec<Symbol>,
|
||||||
|
pub nodes_to_symbols: HashMap<NodeId, SymbolId>,
|
||||||
pub type_infos: Vec<TypeInfo>,
|
pub type_infos: Vec<TypeInfo>,
|
||||||
|
pub symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>,
|
||||||
pub nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
|
pub nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyze(
|
pub fn analyze_compilation_unit(
|
||||||
compilation_units: &HashMap<FileId, CompilationUnit>,
|
compilation_unit: &CompilationUnit,
|
||||||
) -> HashMap<FileId, AnalysisResult> {
|
) -> (AnalysisResult, Diagnostics) {
|
||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
|
|
||||||
let mut files_to_scopes: HashMap<FileId, Vec<Scope>> = HashMap::new();
|
let mut scopes_result = collect_scopes(compilation_unit);
|
||||||
let mut files_to_nodes_to_scopes: HashMap<FileId, HashMap<NodeId, ScopeId>> = HashMap::new();
|
|
||||||
|
|
||||||
for (file_id, compilation_unit) in compilation_units {
|
let mut symbols_result = collect_symbols(
|
||||||
let result = collect_scopes(compilation_unit);
|
compilation_unit,
|
||||||
files_to_scopes.insert(*file_id, result.scopes);
|
&mut scopes_result.scopes,
|
||||||
files_to_nodes_to_scopes.insert(*file_id, result.nodes_to_scopes);
|
&scopes_result.nodes_to_scopes,
|
||||||
}
|
);
|
||||||
|
diagnostics.append(&mut symbols_result.diagnostics);
|
||||||
|
|
||||||
let mut files_to_symbols: HashMap<FileId, Vec<Symbol>> = HashMap::new();
|
let mut names_result = resolve_names(
|
||||||
|
compilation_unit,
|
||||||
|
&mut scopes_result.scopes,
|
||||||
|
&mut symbols_result.symbols,
|
||||||
|
&scopes_result.nodes_to_scopes,
|
||||||
|
);
|
||||||
|
diagnostics.append(&mut names_result.diagnostics);
|
||||||
|
|
||||||
for (file_id, compilation_unit) in compilation_units {
|
let mut collect_types_result = collect_types(compilation_unit, &names_result.nodes_to_symbols);
|
||||||
let scopes = files_to_scopes.get_mut(file_id).unwrap();
|
|
||||||
let nodes_to_scopes = files_to_nodes_to_scopes.get(file_id).unwrap();
|
|
||||||
let mut result = collect_symbols(compilation_unit, scopes, nodes_to_scopes);
|
|
||||||
files_to_symbols.insert(*file_id, result.symbols);
|
|
||||||
diagnostics.append(&mut result.diagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut files_to_nodes_to_symbols: HashMap<FileId, HashMap<NodeId, SymbolId>> = HashMap::new();
|
let mut resolve_types_result = resolve_types(
|
||||||
|
compilation_unit,
|
||||||
|
&names_result.nodes_to_symbols,
|
||||||
|
&mut collect_types_result.type_infos,
|
||||||
|
&mut collect_types_result.symbols_to_type_infos,
|
||||||
|
);
|
||||||
|
diagnostics.append(&mut resolve_types_result.diagnostics);
|
||||||
|
|
||||||
for (file_id, compilation_unit) in compilation_units {
|
(
|
||||||
let scopes = files_to_scopes.get_mut(file_id).unwrap();
|
AnalysisResult {
|
||||||
let symbols = files_to_symbols.get_mut(file_id).unwrap();
|
symbols: symbols_result.symbols,
|
||||||
let nodes_to_scopes = files_to_nodes_to_scopes.get(file_id).unwrap();
|
nodes_to_symbols: names_result.nodes_to_symbols,
|
||||||
|
type_infos: collect_types_result.type_infos,
|
||||||
let mut result = resolve_names(compilation_unit, scopes, symbols, nodes_to_scopes);
|
symbols_to_type_infos: collect_types_result.symbols_to_type_infos,
|
||||||
|
nodes_to_type_infos: resolve_types_result.nodes_to_type_infos,
|
||||||
files_to_nodes_to_symbols.insert(*file_id, result.nodes_to_symbols);
|
},
|
||||||
diagnostics.append(&mut result.diagnostics);
|
diagnostics,
|
||||||
}
|
)
|
||||||
|
|
||||||
let mut files_to_type_infos: HashMap<FileId, Vec<TypeInfo>> = HashMap::new();
|
|
||||||
let mut files_to_symbols_to_type_infos: HashMap<FileId, HashMap<SymbolId, TypeInfoId>> =
|
|
||||||
HashMap::new();
|
|
||||||
|
|
||||||
for (file_id, compilation_unit) in compilation_units {
|
|
||||||
let nodes_to_symbols = files_to_nodes_to_symbols.get(&file_id).unwrap();
|
|
||||||
let result = collect_types(compilation_unit, nodes_to_symbols);
|
|
||||||
|
|
||||||
files_to_type_infos.insert(*file_id, result.type_infos);
|
|
||||||
files_to_symbols_to_type_infos.insert(*file_id, result.symbols_to_type_infos);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut files_to_nodes_to_type_infos: HashMap<FileId, HashMap<NodeId, TypeInfoId>> =
|
|
||||||
HashMap::new();
|
|
||||||
|
|
||||||
for (file_id, compilation_unit) in compilation_units {
|
|
||||||
let nodes_to_symbols = files_to_nodes_to_symbols.get_mut(file_id).unwrap();
|
|
||||||
let type_infos = files_to_type_infos.get_mut(file_id).unwrap();
|
|
||||||
let symbols_to_type_infos = files_to_symbols_to_type_infos.get_mut(file_id).unwrap();
|
|
||||||
|
|
||||||
let mut result = resolve_types(
|
|
||||||
compilation_unit,
|
|
||||||
nodes_to_symbols,
|
|
||||||
type_infos,
|
|
||||||
symbols_to_type_infos,
|
|
||||||
);
|
|
||||||
|
|
||||||
files_to_nodes_to_type_infos.insert(*file_id, result.nodes_to_type_infos);
|
|
||||||
diagnostics.append(&mut result.diagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut files_to_results: HashMap<FileId, AnalysisResult> = HashMap::new();
|
|
||||||
|
|
||||||
for (file_id, _) in compilation_units {
|
|
||||||
let type_infos = files_to_type_infos.remove(file_id).unwrap();
|
|
||||||
let nodes_to_type_infos = files_to_nodes_to_type_infos.remove(file_id).unwrap();
|
|
||||||
let analysis_result = AnalysisResult {
|
|
||||||
type_infos,
|
|
||||||
nodes_to_type_infos,
|
|
||||||
};
|
|
||||||
files_to_results.insert(*file_id, analysis_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
files_to_results
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,14 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod e2e_tests {
|
mod e2e_tests {
|
||||||
|
use dmc_lib::compile_compilation_unit;
|
||||||
use dmc_lib::constants_table::ConstantsTable;
|
use dmc_lib::constants_table::ConstantsTable;
|
||||||
use dmc_lib::diagnostic::Diagnostic;
|
use dmc_lib::diagnostic::{Diagnostic, Diagnostics};
|
||||||
use dmc_lib::intrinsics::{insert_intrinsic_symbols, insert_intrinsic_types};
|
|
||||||
use dmc_lib::offset_counter::OffsetCounter;
|
|
||||||
use dmc_lib::parser::parse_compilation_unit;
|
|
||||||
use dmc_lib::symbol_table::SymbolTable;
|
|
||||||
use dmc_lib::types_table::TypesTable;
|
|
||||||
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::value::Value;
|
use dvm_lib::vm::value::Value;
|
||||||
use dvm_lib::vm::{DvmContext, call};
|
use dvm_lib::vm::{DvmContext, call};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
const REGISTER_COUNT: usize = 8;
|
const REGISTER_COUNT: usize = 16;
|
||||||
|
|
||||||
fn report_diagnostics(diagnostics: &[Diagnostic]) -> ! {
|
fn report_diagnostics(diagnostics: &[Diagnostic]) -> ! {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@ -28,55 +22,15 @@ mod e2e_tests {
|
|||||||
panic!("There were diagnostics.");
|
panic!("There were diagnostics.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_context(input: &str) -> Result<DvmContext, Vec<Diagnostic>> {
|
fn prepare_context(input: &str) -> Result<DvmContext, Diagnostics> {
|
||||||
let (mut compilation_unit, diagnostics) = parse_compilation_unit(input, None);
|
|
||||||
if !diagnostics.is_empty() {
|
|
||||||
return Err(diagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
symbol_table.push_module_scope("global_scope");
|
|
||||||
insert_intrinsic_symbols(&mut symbol_table);
|
|
||||||
|
|
||||||
let mut types_table = TypesTable::new();
|
|
||||||
insert_intrinsic_types(&symbol_table, &mut types_table);
|
|
||||||
|
|
||||||
compilation_unit.init_scopes(&mut symbol_table);
|
|
||||||
compilation_unit.gather_symbols_into(&mut symbol_table)?;
|
|
||||||
compilation_unit.check_names(&mut symbol_table)?;
|
|
||||||
compilation_unit.gather_types_into(&symbol_table, &mut types_table)?;
|
|
||||||
compilation_unit.type_check(&symbol_table, &mut types_table)?;
|
|
||||||
|
|
||||||
let (ir_classes, mut ir_functions) = compilation_unit.to_ir(&symbol_table, &types_table);
|
|
||||||
|
|
||||||
let mut functions: Vec<Function> = vec![];
|
|
||||||
let mut constants_table = ConstantsTable::new();
|
let mut constants_table = ConstantsTable::new();
|
||||||
|
|
||||||
for ir_function in &mut ir_functions {
|
let compile_compilation_unit_result = compile_compilation_unit(input, &mut constants_table);
|
||||||
let mut offset_counter = OffsetCounter::new();
|
|
||||||
ir_function.assign_registers(REGISTER_COUNT, &mut offset_counter);
|
|
||||||
let stack_size = offset_counter.get_count();
|
|
||||||
let function = ir_function.assemble(stack_size, &mut constants_table);
|
|
||||||
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 {
|
for (name, function) in compile_compilation_unit_result?.functions {
|
||||||
dvm_context
|
dvm_context.functions_mut().insert(name, function);
|
||||||
.classes_mut()
|
|
||||||
.insert(class.fqn().into(), Rc::new(class));
|
|
||||||
}
|
|
||||||
|
|
||||||
for function in functions {
|
|
||||||
dvm_context
|
|
||||||
.functions_mut()
|
|
||||||
.insert(function.name_owned(), function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, content) in &constants_table.string_constants() {
|
for (name, content) in &constants_table.string_constants() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user