mir: split build_module phases
This commit is contained in:
@ -125,10 +125,13 @@ impl MirBuilder {
|
||||
|
||||
/// Build a complete MIR module from AST
|
||||
pub fn build_module(&mut self, ast: ASTNode) -> Result<MirModule, String> {
|
||||
// Create a new module
|
||||
let module = MirModule::new("main".to_string());
|
||||
self.prepare_module()?;
|
||||
let result_value = self.lower_root(ast)?;
|
||||
self.finalize_module(result_value)
|
||||
}
|
||||
|
||||
// Create a main function to contain the AST
|
||||
fn prepare_module(&mut self) -> Result<(), String> {
|
||||
let module = MirModule::new("main".to_string());
|
||||
let main_signature = FunctionSignature {
|
||||
name: "main".to_string(),
|
||||
params: vec![],
|
||||
@ -140,20 +143,22 @@ impl MirBuilder {
|
||||
let mut main_function = MirFunction::new(main_signature, entry_block);
|
||||
main_function.metadata.is_entry_point = true;
|
||||
|
||||
// Set up building context
|
||||
self.current_module = Some(module);
|
||||
self.current_function = Some(main_function);
|
||||
self.current_block = Some(entry_block);
|
||||
|
||||
// Optional: Add safepoint at function entry (disabled by default)
|
||||
if std::env::var("NYASH_BUILDER_SAFEPOINT_ENTRY").ok().as_deref() == Some("1") {
|
||||
self.emit_instruction(MirInstruction::Safepoint)?;
|
||||
}
|
||||
|
||||
// Convert AST to MIR
|
||||
let result_value = self.build_expression(ast)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Add return instruction if needed
|
||||
fn lower_root(&mut self, ast: ASTNode) -> Result<ValueId, String> {
|
||||
self.build_expression(ast)
|
||||
}
|
||||
|
||||
fn finalize_module(&mut self, result_value: ValueId) -> Result<MirModule, String> {
|
||||
if let Some(block_id) = self.current_block {
|
||||
if let Some(ref mut function) = self.current_function {
|
||||
if let Some(block) = function.get_block_mut(block_id) {
|
||||
@ -162,7 +167,6 @@ impl MirBuilder {
|
||||
value: Some(result_value),
|
||||
});
|
||||
}
|
||||
// Infer return type from TyEnv (value_types)
|
||||
if let Some(mt) = self.value_types.get(&result_value).cloned() {
|
||||
function.signature.return_type = mt;
|
||||
}
|
||||
@ -170,33 +174,41 @@ impl MirBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize and return module
|
||||
let mut module = self.current_module.take().unwrap();
|
||||
let mut function = self.current_function.take().unwrap();
|
||||
// Flush value_types (TyEnv) into function metadata
|
||||
function.metadata.value_types = self.value_types.clone();
|
||||
// 補助: 本文中に明示的な return <expr> が存在する場合、
|
||||
// 末尾returnを挿入しなかった関数でも戻り型を推定する。
|
||||
if matches!(function.signature.return_type, super::MirType::Void | super::MirType::Unknown) {
|
||||
let mut inferred: Option<super::MirType> = None;
|
||||
'outer: for (_bid, bb) in function.blocks.iter() {
|
||||
for inst in bb.instructions.iter() {
|
||||
if let super::MirInstruction::Return { value: Some(v) } = inst {
|
||||
if let Some(mt) = self.value_types.get(v).cloned() { inferred = Some(mt); break 'outer; }
|
||||
// 追加: v が PHI の場合は入力側の型から推定
|
||||
if let Some(mt) = phi::infer_type_from_phi(&function, *v, &self.value_types) { inferred = Some(mt); break 'outer; }
|
||||
if let Some(mt) = self.value_types.get(v).cloned() {
|
||||
inferred = Some(mt);
|
||||
break 'outer;
|
||||
}
|
||||
if let Some(mt) = phi::infer_type_from_phi(&function, *v, &self.value_types) {
|
||||
inferred = Some(mt);
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(super::MirInstruction::Return { value: Some(v) }) = &bb.terminator {
|
||||
if let Some(mt) = self.value_types.get(v).cloned() { inferred = Some(mt); break; }
|
||||
if let Some(mt) = phi::infer_type_from_phi(&function, *v, &self.value_types) { inferred = Some(mt); break; }
|
||||
if let Some(mt) = self.value_types.get(v).cloned() {
|
||||
inferred = Some(mt);
|
||||
break;
|
||||
}
|
||||
if let Some(mt) = phi::infer_type_from_phi(&function, *v, &self.value_types) {
|
||||
inferred = Some(mt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(mt) = inferred { function.signature.return_type = mt; }
|
||||
}
|
||||
if let Some(mt) = inferred {
|
||||
function.signature.return_type = mt;
|
||||
}
|
||||
}
|
||||
module.add_function(function);
|
||||
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user