40 lines
1.6 KiB
Rust
40 lines
1.6 KiB
Rust
|
|
use super::{LoopBuilder, ValueId};
|
|||
|
|
use crate::ast::ASTNode;
|
|||
|
|
use crate::mir::utils::is_current_block_terminated;
|
|||
|
|
use crate::mir::ConstValue;
|
|||
|
|
|
|||
|
|
impl<'a> LoopBuilder<'a> {
|
|||
|
|
pub(super) fn build_statement(&mut self, stmt: ASTNode) -> Result<ValueId, String> {
|
|||
|
|
// Preserve the originating span for loop-local control instructions (break/continue/phi).
|
|||
|
|
self.parent_builder.current_span = stmt.span();
|
|||
|
|
match stmt {
|
|||
|
|
// Ensure nested bare blocks inside loops are lowered with loop-aware semantics
|
|||
|
|
ASTNode::Program { statements, .. } => {
|
|||
|
|
let mut last = None;
|
|||
|
|
for s in statements.into_iter() {
|
|||
|
|
last = Some(self.build_statement(s)?);
|
|||
|
|
// フェーズS修正:統一終端検出ユーティリティ使用
|
|||
|
|
if is_current_block_terminated(self.parent_builder)? {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
Ok(last.unwrap_or_else(|| {
|
|||
|
|
let void_id = self.new_value();
|
|||
|
|
// Emit a void const to keep SSA consistent when block is empty
|
|||
|
|
let _ = self.emit_const(void_id, ConstValue::Void);
|
|||
|
|
void_id
|
|||
|
|
}))
|
|||
|
|
}
|
|||
|
|
ASTNode::If {
|
|||
|
|
condition,
|
|||
|
|
then_body,
|
|||
|
|
else_body,
|
|||
|
|
..
|
|||
|
|
} => self.lower_if_in_loop(*condition, then_body, else_body),
|
|||
|
|
ASTNode::Break { .. } => self.do_break(),
|
|||
|
|
ASTNode::Continue { .. } => self.do_continue(),
|
|||
|
|
other => self.parent_builder.build_expression(other),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|