use crate::ir::{IRExpr, IRType};
use std::cell::Cell;
use std::collections::HashMap;
pub const SCRATCH_LOCALS: u32 = 8;
pub const COLLECTION_HEAP_BASE: u32 = 131072;
pub fn strlen_local_name(name: &str) -> String {
format!("__strlen_{name}")
}
pub struct LocalInfo {
pub index: u32,
pub var_type: IRType,
}
#[derive(Clone, Copy)]
pub struct LoopContext {
pub break_level: u32,
pub continue_level: u32,
}
pub struct FunctionInfo {
pub index: u32,
#[allow(dead_code)]
pub param_types: Vec<IRType>,
pub return_type: IRType,
}
pub struct ClassInfo {
pub name: String,
pub methods: HashMap<String, u32>, pub field_offsets: HashMap<String, u64>, pub field_types: HashMap<String, IRType>, pub class_var_values: HashMap<String, IRExpr>, pub instance_size: u32, }
pub struct CompilationContext {
pub locals_map: HashMap<String, LocalInfo>,
pub local_count: u32,
pub function_map: HashMap<String, FunctionInfo>,
pub class_map: HashMap<String, ClassInfo>,
pub module_vars: HashMap<String, (Option<IRType>, IRExpr)>,
pub temp_local: u32, pub temp_local_f64: u32, pub for_loop_seq: u32,
pub block_depth: u32,
pub loop_stack: Vec<LoopContext>,
pub collection_alloc_offset: Cell<u32>,
pub alloc_func_index: u32,
}
impl CompilationContext {
pub fn new() -> Self {
CompilationContext {
locals_map: HashMap::new(),
local_count: 0,
function_map: HashMap::new(),
class_map: HashMap::new(),
module_vars: HashMap::new(),
temp_local: 0,
temp_local_f64: 0,
for_loop_seq: 0,
block_depth: 0,
loop_stack: Vec::new(),
collection_alloc_offset: Cell::new(0),
alloc_func_index: 0,
}
}
pub fn alloc_collection(&self, size: u32) -> u32 {
let aligned = (size + 7) & !7;
let offset = self.collection_alloc_offset.get();
self.collection_alloc_offset.set(offset + aligned);
COLLECTION_HEAP_BASE + offset
}
pub fn add_local(&mut self, name: &str, var_type: IRType) -> u32 {
let idx = self.local_count;
self.locals_map.insert(
name.to_string(),
LocalInfo {
index: idx,
var_type,
},
);
self.local_count += 1;
idx
}
pub fn get_local_info(&self, name: &str) -> Option<&LocalInfo> {
self.locals_map.get(name)
}
pub fn get_local_index(&self, name: &str) -> Option<u32> {
self.locals_map.get(name).map(|info| info.index)
}
pub fn add_function(
&mut self,
name: &str,
index: u32,
param_types: Vec<IRType>,
return_type: IRType,
) {
self.function_map.insert(
name.to_string(),
FunctionInfo {
index,
param_types,
return_type,
},
);
}
pub fn get_function_info(&self, name: &str) -> Option<&FunctionInfo> {
self.function_map.get(name)
}
pub fn add_class(&mut self, class_info: ClassInfo) {
self.class_map.insert(class_info.name.clone(), class_info);
}
pub fn get_class_info(&self, name: &str) -> Option<&ClassInfo> {
self.class_map.get(name)
}
pub fn add_module_var(&mut self, name: &str, var_type: Option<IRType>, value: IRExpr) {
self.module_vars.insert(name.to_string(), (var_type, value));
}
pub fn get_module_var(&self, name: &str) -> Option<&(Option<IRType>, IRExpr)> {
self.module_vars.get(name)
}
}