85 lines
2.5 KiB
Rust
85 lines
2.5 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use crate::{
|
|
compile::{
|
|
block::FunctionBlock, error::CompileError, function::FunctionSignature,
|
|
syntax::FunctionBody, value::CompileConstant,
|
|
},
|
|
vm::{
|
|
instruction::ConstantId,
|
|
module::{Module, ModuleConstant},
|
|
pool::Pool,
|
|
},
|
|
};
|
|
|
|
#[derive(Default)]
|
|
pub struct CompilationModule {
|
|
constant_pool: Pool<CompileConstant, { ConstantId::BITS }>,
|
|
pub(crate) local_functions: HashMap<u32, FunctionBlock>,
|
|
local_function_index: u32,
|
|
root: Option<u32>,
|
|
}
|
|
|
|
impl CompilationModule {
|
|
pub fn constant(&mut self, value: CompileConstant) -> Result<ConstantId, CompileError> {
|
|
match self.constant_pool.key(value) {
|
|
Some(key) => Ok(key),
|
|
None => todo!(),
|
|
}
|
|
}
|
|
|
|
pub fn compile_function(
|
|
&mut self,
|
|
signature: FunctionSignature,
|
|
body: &FunctionBody,
|
|
root: bool,
|
|
) -> Result<u32, CompileError> {
|
|
let index = self.local_function_index;
|
|
if root && self.root.is_some() {
|
|
todo!()
|
|
}
|
|
self.local_function_index += 1;
|
|
let mut function = FunctionBlock::new(signature);
|
|
function.compile_body(self, body)?;
|
|
self.local_functions.insert(index, function);
|
|
if root {
|
|
self.root = Some(index);
|
|
}
|
|
Ok(index)
|
|
}
|
|
|
|
pub fn compile_module(self) -> Result<Module, CompileError> {
|
|
// Emit all function code first
|
|
let mut function_offsets = HashMap::new();
|
|
let mut instructions = vec![];
|
|
let root = self.root.unwrap();
|
|
for (index, function) in self.local_functions.into_iter() {
|
|
function_offsets.insert(index, instructions.len());
|
|
instructions.extend(function.instructions.into_iter().map(u32::from));
|
|
}
|
|
let entry = *function_offsets.get(&root).unwrap();
|
|
let constants = self
|
|
.constant_pool
|
|
.into_iter()
|
|
.map(|(value, key)| {
|
|
(
|
|
key,
|
|
match value {
|
|
CompileConstant::Integer(value) => ModuleConstant::Integer(value),
|
|
CompileConstant::LocalFunction(index) => {
|
|
let address = *function_offsets.get(&index).unwrap();
|
|
ModuleConstant::LocalFunction(address)
|
|
}
|
|
},
|
|
)
|
|
})
|
|
.collect();
|
|
|
|
Ok(Module {
|
|
constants,
|
|
instructions,
|
|
entry,
|
|
})
|
|
}
|
|
}
|