Files
lysp/src/compile/module.rs
T
2026-04-30 16:23:39 +03:00

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,
})
}
}