diff --git a/src/mir/builder.rs b/src/mir/builder.rs index 25e309fc..cbe413e3 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -125,35 +125,40 @@ impl MirBuilder { /// Build a complete MIR module from AST pub fn build_module(&mut self, ast: ASTNode) -> Result { - // Create a new module + self.prepare_module()?; + let result_value = self.lower_root(ast)?; + self.finalize_module(result_value) + } + + fn prepare_module(&mut self) -> Result<(), String> { let module = MirModule::new("main".to_string()); - - // Create a main function to contain the AST let main_signature = FunctionSignature { name: "main".to_string(), params: vec![], return_type: MirType::Void, effects: EffectMask::PURE, }; - + let entry_block = self.block_gen.next(); 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)?; - - // Add return instruction if needed + + Ok(()) + } + + fn lower_root(&mut self, ast: ASTNode) -> Result { + self.build_expression(ast) + } + + fn finalize_module(&mut self, result_value: ValueId) -> Result { 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,41 +167,48 @@ 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; } } } } - - // 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 が存在する場合、 - // 末尾returnを挿入しなかった関数でも戻り型を推定する。 if matches!(function.signature.return_type, super::MirType::Void | super::MirType::Unknown) { let mut inferred: Option = 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) }