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;
|
||||
|
||||
struct FunctionAssemblyContext<'a> {
|
||||
type_infos: &'a Vec<IrTypeInfo>,
|
||||
type_infos: &'a [IrTypeInfo],
|
||||
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
||||
variable_locations: &'a VariableLocations,
|
||||
parameters: &'a [IrParameter],
|
||||
@ -29,7 +29,7 @@ struct FunctionAssemblyContext<'a> {
|
||||
|
||||
pub fn assemble_ir_function(
|
||||
ir_function: &IrFunction,
|
||||
type_infos: &Vec<IrTypeInfo>,
|
||||
type_infos: &[IrTypeInfo],
|
||||
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
||||
variable_locations: &VariableLocations,
|
||||
constants_table: &mut ConstantsTable,
|
||||
|
||||
@ -55,6 +55,7 @@ impl IrFunction {
|
||||
self.return_type_info.as_ref()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn assign_registers(&self, register_count: usize) -> VariableLocations {
|
||||
if self.blocks.is_empty() {
|
||||
return VariableLocations::new(HashMap::new(), HashMap::new());
|
||||
@ -66,6 +67,7 @@ impl IrFunction {
|
||||
block_assign_registers(block, register_count)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn assemble(
|
||||
&self,
|
||||
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 debug_print;
|
||||
pub mod ir_allocate;
|
||||
@ -22,3 +32,36 @@ pub mod ir_variable;
|
||||
mod register_allocation;
|
||||
mod util;
|
||||
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 compile_pipeline;
|
||||
pub mod constants_table;
|
||||
@ -19,3 +29,45 @@ pub mod token;
|
||||
pub mod type_info;
|
||||
pub mod types_table;
|
||||
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::compilation_unit::CompilationUnit;
|
||||
use crate::compile_pipeline::FileId;
|
||||
use crate::diagnostic::Diagnostics;
|
||||
use crate::semantic_analysis::collect_scopes::collect_scopes;
|
||||
use crate::semantic_analysis::collect_symbols::collect_symbols;
|
||||
use crate::semantic_analysis::collect_types::collect_types;
|
||||
use crate::semantic_analysis::resolve_names::resolve_names;
|
||||
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::type_info::{TypeInfo, TypeInfoId};
|
||||
use std::collections::HashMap;
|
||||
@ -24,89 +22,53 @@ pub mod symbol;
|
||||
pub mod type_info;
|
||||
|
||||
pub struct AnalysisResult {
|
||||
pub symbols: Vec<Symbol>,
|
||||
pub nodes_to_symbols: HashMap<NodeId, SymbolId>,
|
||||
pub type_infos: Vec<TypeInfo>,
|
||||
pub symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>,
|
||||
pub nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
|
||||
}
|
||||
|
||||
pub fn analyze(
|
||||
compilation_units: &HashMap<FileId, CompilationUnit>,
|
||||
) -> HashMap<FileId, AnalysisResult> {
|
||||
pub fn analyze_compilation_unit(
|
||||
compilation_unit: &CompilationUnit,
|
||||
) -> (AnalysisResult, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
let mut files_to_scopes: HashMap<FileId, Vec<Scope>> = HashMap::new();
|
||||
let mut files_to_nodes_to_scopes: HashMap<FileId, HashMap<NodeId, ScopeId>> = HashMap::new();
|
||||
let mut scopes_result = collect_scopes(compilation_unit);
|
||||
|
||||
for (file_id, compilation_unit) in compilation_units {
|
||||
let result = collect_scopes(compilation_unit);
|
||||
files_to_scopes.insert(*file_id, result.scopes);
|
||||
files_to_nodes_to_scopes.insert(*file_id, result.nodes_to_scopes);
|
||||
}
|
||||
let mut symbols_result = collect_symbols(
|
||||
compilation_unit,
|
||||
&mut scopes_result.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 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 collect_types_result = collect_types(compilation_unit, &names_result.nodes_to_symbols);
|
||||
|
||||
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();
|
||||
let symbols = files_to_symbols.get_mut(file_id).unwrap();
|
||||
let nodes_to_scopes = files_to_nodes_to_scopes.get(file_id).unwrap();
|
||||
|
||||
let mut result = resolve_names(compilation_unit, scopes, symbols, nodes_to_scopes);
|
||||
|
||||
files_to_nodes_to_symbols.insert(*file_id, result.nodes_to_symbols);
|
||||
diagnostics.append(&mut result.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
|
||||
(
|
||||
AnalysisResult {
|
||||
symbols: symbols_result.symbols,
|
||||
nodes_to_symbols: names_result.nodes_to_symbols,
|
||||
type_infos: collect_types_result.type_infos,
|
||||
symbols_to_type_infos: collect_types_result.symbols_to_type_infos,
|
||||
nodes_to_type_infos: resolve_types_result.nodes_to_type_infos,
|
||||
},
|
||||
diagnostics,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,20 +1,14 @@
|
||||
#[cfg(test)]
|
||||
mod e2e_tests {
|
||||
use dmc_lib::compile_compilation_unit;
|
||||
use dmc_lib::constants_table::ConstantsTable;
|
||||
use dmc_lib::diagnostic::Diagnostic;
|
||||
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 dmc_lib::diagnostic::{Diagnostic, Diagnostics};
|
||||
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||
use dvm_lib::vm::function::Function;
|
||||
use dvm_lib::vm::value::Value;
|
||||
use dvm_lib::vm::{DvmContext, call};
|
||||
use std::rc::Rc;
|
||||
|
||||
const REGISTER_COUNT: usize = 8;
|
||||
const REGISTER_COUNT: usize = 16;
|
||||
|
||||
fn report_diagnostics(diagnostics: &[Diagnostic]) -> ! {
|
||||
eprintln!(
|
||||
@ -28,55 +22,15 @@ mod e2e_tests {
|
||||
panic!("There were diagnostics.");
|
||||
}
|
||||
|
||||
fn prepare_context(input: &str) -> Result<DvmContext, Vec<Diagnostic>> {
|
||||
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![];
|
||||
fn prepare_context(input: &str) -> Result<DvmContext, Diagnostics> {
|
||||
let mut constants_table = ConstantsTable::new();
|
||||
|
||||
for ir_function in &mut ir_functions {
|
||||
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 compile_compilation_unit_result = compile_compilation_unit(input, &mut constants_table);
|
||||
|
||||
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 {
|
||||
dvm_context
|
||||
.functions_mut()
|
||||
.insert(function.name_owned(), function);
|
||||
for (name, function) in compile_compilation_unit_result?.functions {
|
||||
dvm_context.functions_mut().insert(name, function);
|
||||
}
|
||||
|
||||
for (name, content) in &constants_table.string_constants() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user