500 lines
17 KiB
Markdown
500 lines
17 KiB
Markdown
|
|
Status: Historical (context)
|
|||
|
|
Scope: ChatGPT Pro 相談用に、Phase 131–138 の “当時点” の状況と一般化案をまとめたメモ。
|
|||
|
|
Related:
|
|||
|
|
- SSOT (roadmap): `docs/development/current/main/10-Now.md`
|
|||
|
|
- SSOT (decisions): `docs/development/current/main/20-Decisions.md`
|
|||
|
|
- SSOT (design): `docs/development/current/main/design/normalized-expr-lowering.md`
|
|||
|
|
- phases: `docs/development/current/main/phases/phase-139/README.md`, `docs/development/current/main/phases/phase-140/README.md`
|
|||
|
|
|
|||
|
|
# Hakorune JoinIR 設計 - ChatGPT Pro 用コンテキスト
|
|||
|
|
|
|||
|
|
> 注意: この文書は “相談の前提” であり SSOT ではありません。コード断片は擬似コードを含みます。
|
|||
|
|
> 正本(収束方針)は `docs/development/current/main/design/normalized-expr-lowering.md` を参照してください。
|
|||
|
|
|
|||
|
|
## 概要
|
|||
|
|
|
|||
|
|
Hakorune(セルフホスティングコンパイラ)の JoinIR(Join Intermediate Representation)設計に関する一般化戦略の相談。
|
|||
|
|
|
|||
|
|
### 現状の問題
|
|||
|
|
|
|||
|
|
- Phase 131-138 で「パターン追加」方式で拡張中
|
|||
|
|
- このままでは無限に Phase が必要になる可能性
|
|||
|
|
- 目標: パターンマッチング → 式の一般化(AST walker)への移行
|
|||
|
|
|
|||
|
|
### 提案中の方向
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
制御フロー形(loop/if): 段階的拡張(正規化)OK
|
|||
|
|
式と return: 早期に一般化(ExprLowererBox)へ移行
|
|||
|
|
PHI: Normalized 内で避ける → 後段(SSA/PHI)に押し出す
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ファイル構成(主要部分抜粋)
|
|||
|
|
|
|||
|
|
### 1. LoopTrueBreakOnceBuilderBox (loop_true_break_once.rs - 主要実装)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
//! Phase 131-138: loop(true) break-once 正規化
|
|||
|
|
//!
|
|||
|
|
//! ## 責務
|
|||
|
|
//! - loop(true) { <assign>* ; break } パターンを JoinModule に変換
|
|||
|
|
//! - PHI-free: env パラメータ + 継続で値を渡す
|
|||
|
|
//! - Return lowering は ReturnValueLowererBox に委譲
|
|||
|
|
//!
|
|||
|
|
//! ## 生成される構造
|
|||
|
|
//! main(env)
|
|||
|
|
//! → TailCall(loop_step, env)
|
|||
|
|
//! loop_step(env)
|
|||
|
|
//! → TailCall(loop_body, env)
|
|||
|
|
//! loop_body(env)
|
|||
|
|
//! → <assign statements> → TailCall(k_exit, env)
|
|||
|
|
//! k_exit(env)
|
|||
|
|
//! → Ret(env[x]) or TailCall(post_k, env)
|
|||
|
|
//! post_k(env) [Phase 132-P4+]
|
|||
|
|
//! → <post assign> → Ret(env[x])
|
|||
|
|
|
|||
|
|
pub struct LoopTrueBreakOnceBuilderBox;
|
|||
|
|
|
|||
|
|
impl LoopTrueBreakOnceBuilderBox {
|
|||
|
|
pub fn lower(
|
|||
|
|
step_tree: &StepTree,
|
|||
|
|
env_layout: &EnvLayout,
|
|||
|
|
) -> Result<Option<(JoinModule, JoinFragmentMeta)>, String> {
|
|||
|
|
// 1. Extract loop(true) { body ; break } [; <post>] pattern
|
|||
|
|
let (prefix_nodes, loop_node, post_nodes) =
|
|||
|
|
Self::extract_loop_true_pattern(&step_tree.root)?;
|
|||
|
|
|
|||
|
|
// 2. Verify condition is Bool(true)
|
|||
|
|
let is_loop_true = Self::is_bool_true_literal(&cond_ast.0);
|
|||
|
|
if !is_loop_true {
|
|||
|
|
return Ok(None); // Fallback
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. Generate JoinModule with continuations
|
|||
|
|
// - main → loop_step → loop_body → k_exit [→ post_k]
|
|||
|
|
// - All parameters: env (BTreeMap<String, ValueId>)
|
|||
|
|
|
|||
|
|
// 4. Return lowering via ReturnValueLowererBox
|
|||
|
|
match ReturnValueLowererBox::lower_to_value_id(
|
|||
|
|
return_value_ast,
|
|||
|
|
&mut func.body,
|
|||
|
|
&mut next_value_id,
|
|||
|
|
&env,
|
|||
|
|
)? {
|
|||
|
|
Some(vid) => func.body.push(JoinInst::Ret { value: Some(vid) }),
|
|||
|
|
None => return Ok(None), // Out of scope
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Key Points**:
|
|||
|
|
- env は BTreeMap<String, ValueId> - 変数 → 値の対応
|
|||
|
|
- 継続関数は全て env をパラメータとして受け取る
|
|||
|
|
- Return lowering は ReturnValueLowererBox に委譲(SSOT)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 2. ReturnValueLowererBox (common/return_value_lowerer_box.rs - SSOT)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
//! Phase 136-138: Return 値 lowering SSOT
|
|||
|
|
//!
|
|||
|
|
//! ## 責務
|
|||
|
|
//! - return value (変数/リテラル/式) → ValueId に変換
|
|||
|
|
//! - 任意の式に対応する準備(現在は pure expression のみ)
|
|||
|
|
|
|||
|
|
pub struct ReturnValueLowererBox;
|
|||
|
|
|
|||
|
|
impl ReturnValueLowererBox {
|
|||
|
|
pub fn lower_to_value_id(
|
|||
|
|
value_ast: &Option<AstNodeHandle>,
|
|||
|
|
body: &mut Vec<JoinInst>,
|
|||
|
|
next_value_id: &mut u32,
|
|||
|
|
env: &BTreeMap<String, ValueId>,
|
|||
|
|
) -> Result<Option<ValueId>, String> {
|
|||
|
|
match value_ast {
|
|||
|
|
None => Ok(Some(ValueId(0))), // void return
|
|||
|
|
|
|||
|
|
Some(ast_handle) => {
|
|||
|
|
match ast_handle.0.as_ref() {
|
|||
|
|
// Variable: env lookup
|
|||
|
|
ASTNode::Variable { name, .. } => {
|
|||
|
|
env.get(name).copied().ok_or_else(|| {
|
|||
|
|
// Variable not in env - out of scope
|
|||
|
|
Ok(None)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Integer literal: Const generation
|
|||
|
|
ASTNode::Literal { value: LiteralValue::Integer(i), .. } => {
|
|||
|
|
let const_vid = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::Const {
|
|||
|
|
dst: const_vid,
|
|||
|
|
value: ConstValue::Integer(*i),
|
|||
|
|
}));
|
|||
|
|
Ok(Some(const_vid))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BinaryOp (Phase 137 P0: Add のみ)
|
|||
|
|
ASTNode::BinaryOp { operator, left, right, .. } => {
|
|||
|
|
if !matches!(operator, BinaryOperator::Add) {
|
|||
|
|
return Ok(None); // Out of scope
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Lower LHS and RHS recursively
|
|||
|
|
let lhs_vid = Self::lower_operand(left, body, next_value_id, env)?;
|
|||
|
|
let rhs_vid = Self::lower_operand(right, body, next_value_id, env)?;
|
|||
|
|
|
|||
|
|
// Generate BinOp
|
|||
|
|
let result_vid = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|||
|
|
dst: result_vid,
|
|||
|
|
op: BinOpKind::Add,
|
|||
|
|
lhs: lhs_vid,
|
|||
|
|
rhs: rhs_vid,
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
Ok(Some(result_vid))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_ => Ok(None) // Other types - out of scope
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**問題点**:
|
|||
|
|
- 現在は Add のみ対応(Phase 137)
|
|||
|
|
- Sub, Mul, Div を追加するたびに Phase が必要
|
|||
|
|
- → 一般化(Phase 140+)で `lower_operand()` を再帰的に拡張したい
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3. NormalizationPlanBox (plan_box.rs - パターン検出)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
//! Phase 134-138: Pattern detection SSOT
|
|||
|
|
//!
|
|||
|
|
//! ## 責務
|
|||
|
|
//! - Block suffix が "正規化可能なパターン" か判定
|
|||
|
|
//! - loop(true) のみ受け入れ(loop(i<n) は Ok(None))
|
|||
|
|
//! - post-loop statements の形を検出
|
|||
|
|
|
|||
|
|
pub struct NormalizationPlanBox;
|
|||
|
|
|
|||
|
|
impl NormalizationPlanBox {
|
|||
|
|
pub fn plan_block_suffix(
|
|||
|
|
remaining: &[ASTNode],
|
|||
|
|
...,
|
|||
|
|
) -> Result<Option<NormalizationPlan>, String> {
|
|||
|
|
// 1. First statement must be loop(true)
|
|||
|
|
let is_loop_true = match &remaining[0] {
|
|||
|
|
ASTNode::Loop { condition, .. } => {
|
|||
|
|
matches!(
|
|||
|
|
condition.as_ref(),
|
|||
|
|
ASTNode::Literal { value: LiteralValue::Bool(true), .. }
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
_ => false,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if !is_loop_true {
|
|||
|
|
return Ok(None); // Fallback: loop(i<n) など
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. Count post-loop assignments
|
|||
|
|
let mut post_assign_count = 0;
|
|||
|
|
for i in 1..remaining.len() {
|
|||
|
|
if matches!(&remaining[i], ASTNode::Assignment { .. }) {
|
|||
|
|
post_assign_count += 1;
|
|||
|
|
} else {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. After assignments, must have return
|
|||
|
|
let return_index = 1 + post_assign_count;
|
|||
|
|
if return_index >= remaining.len() {
|
|||
|
|
return Ok(None);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let has_return = matches!(&remaining[return_index], ASTNode::Return { .. });
|
|||
|
|
if !has_return {
|
|||
|
|
return Ok(None);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. Return plan
|
|||
|
|
Ok(Some(NormalizationPlan {
|
|||
|
|
consumed: return_index + 1,
|
|||
|
|
kind: if post_assign_count == 0 {
|
|||
|
|
PlanKind::LoopOnly
|
|||
|
|
} else {
|
|||
|
|
PlanKind::LoopWithPost { post_assign_count }
|
|||
|
|
},
|
|||
|
|
requires_return: true,
|
|||
|
|
}))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Problem**:
|
|||
|
|
- パターンが複雑になると判定ロジックが肥大化
|
|||
|
|
- ネストした if などには対応困難
|
|||
|
|
- → 一般化で「制御フロー構造」と「式」を分離したい
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4. NormalizationExecuteBox (execute_box.rs - 実行ロジック)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
//! Phase 134-138: Plan の実行
|
|||
|
|
|
|||
|
|
pub struct NormalizationExecuteBox;
|
|||
|
|
|
|||
|
|
impl NormalizationExecuteBox {
|
|||
|
|
pub fn execute(
|
|||
|
|
builder: &mut MirBuilder,
|
|||
|
|
plan: &NormalizationPlan,
|
|||
|
|
remaining: &[ASTNode],
|
|||
|
|
...,
|
|||
|
|
) -> Result<ValueId, String> {
|
|||
|
|
match &plan.kind {
|
|||
|
|
PlanKind::LoopOnly => {
|
|||
|
|
Self::execute_loop_only(builder, remaining, ...)
|
|||
|
|
}
|
|||
|
|
PlanKind::LoopWithPost { post_assign_count } => {
|
|||
|
|
Self::execute_loop_with_post(builder, plan, remaining, ...)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn execute_loop_only(...) -> Result<ValueId, String> {
|
|||
|
|
// 1. Build StepTree from loop AST
|
|||
|
|
let tree = StepTreeBuilderBox::build_from_ast(&loop_ast);
|
|||
|
|
|
|||
|
|
// 2. Lower to JoinModule (PHI-free)
|
|||
|
|
let (join_module, join_meta) =
|
|||
|
|
match StepTreeNormalizedShadowLowererBox::try_lower_if_only(
|
|||
|
|
&tree,
|
|||
|
|
&available_inputs
|
|||
|
|
)? {
|
|||
|
|
Ok(Some(result)) => result,
|
|||
|
|
Ok(None) => return Err("Out of scope".to_string()),
|
|||
|
|
Err(e) => return Err(e),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 3. Merge into MIR (DirectValue mode)
|
|||
|
|
Self::merge_normalized_joinir(
|
|||
|
|
builder,
|
|||
|
|
join_module,
|
|||
|
|
join_meta,
|
|||
|
|
...,
|
|||
|
|
)?;
|
|||
|
|
|
|||
|
|
Ok(void_id)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fn merge_normalized_joinir(...) -> Result<(), String> {
|
|||
|
|
// DirectValue mode: No PHI generation
|
|||
|
|
// Exit values from join_meta → variable_map reconnection
|
|||
|
|
let boundary = JoinInlineBoundary::new_with_exit_bindings(
|
|||
|
|
vec![],
|
|||
|
|
vec![],
|
|||
|
|
exit_bindings,
|
|||
|
|
);
|
|||
|
|
boundary.exit_reconnect_mode = ExitReconnectMode::DirectValue;
|
|||
|
|
|
|||
|
|
// Bridge JoinIR → MIR
|
|||
|
|
let mir_module = bridge_joinir_to_mir_with_meta(...)?;
|
|||
|
|
|
|||
|
|
// Merge with boundary
|
|||
|
|
merge::merge_joinir_mir_blocks(builder, &mir_module, Some(&boundary), ...)?;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Problem**:
|
|||
|
|
- Plan と Execute の責務が曖昧
|
|||
|
|
- パターン検出と実行ロジックが 1:1 対応
|
|||
|
|
- → Plan を「どこまで拡張するか」の判断基準が不明確
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 式の一般化案(Phase 140+ 向け)
|
|||
|
|
|
|||
|
|
### 提案: NormalizedExprLowererBox
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
//! Phase 140 P0: Pure expression 一般化
|
|||
|
|
//!
|
|||
|
|
//! ## 責務
|
|||
|
|
//! - 任意の pure expression → ValueId に変換
|
|||
|
|
//! - 再帰的に operand を lower
|
|||
|
|
|
|||
|
|
pub struct NormalizedExprLowererBox;
|
|||
|
|
|
|||
|
|
impl NormalizedExprLowererBox {
|
|||
|
|
pub fn lower_expr(
|
|||
|
|
ast: &ASTNode,
|
|||
|
|
body: &mut Vec<JoinInst>,
|
|||
|
|
next_value_id: &mut u32,
|
|||
|
|
env: &BTreeMap<String, ValueId>,
|
|||
|
|
) -> Result<Option<ValueId>, String> {
|
|||
|
|
match ast {
|
|||
|
|
// Variable
|
|||
|
|
ASTNode::Variable { name, .. } => {
|
|||
|
|
env.get(name).copied().ok_or_else(|| Ok(None))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Literals
|
|||
|
|
ASTNode::Literal { value: LiteralValue::Integer(i), .. } => {
|
|||
|
|
let vid = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::Const {
|
|||
|
|
dst: vid,
|
|||
|
|
value: ConstValue::Integer(*i),
|
|||
|
|
}));
|
|||
|
|
Ok(Some(vid))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ASTNode::Literal { value: LiteralValue::Bool(b), .. } => {
|
|||
|
|
let vid = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::Const {
|
|||
|
|
dst: vid,
|
|||
|
|
value: ConstValue::Bool(*b),
|
|||
|
|
}));
|
|||
|
|
Ok(Some(vid))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BinaryOp - recursive
|
|||
|
|
ASTNode::BinaryOp { operator, left, right, .. } => {
|
|||
|
|
let lhs = Self::lower_expr(left, body, next_value_id, env)?
|
|||
|
|
.ok_or_else(|| Ok(None))?;
|
|||
|
|
let rhs = Self::lower_expr(right, body, next_value_id, env)?
|
|||
|
|
.ok_or_else(|| Ok(None))?;
|
|||
|
|
|
|||
|
|
let result = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
|
|||
|
|
let op = match operator {
|
|||
|
|
BinaryOperator::Add => BinOpKind::Add,
|
|||
|
|
BinaryOperator::Sub => BinOpKind::Sub,
|
|||
|
|
BinaryOperator::Mul => BinOpKind::Mul,
|
|||
|
|
BinaryOperator::Div => BinOpKind::Div,
|
|||
|
|
BinaryOperator::Equal => BinOpKind::Eq,
|
|||
|
|
BinaryOperator::Less => BinOpKind::Lt,
|
|||
|
|
// ... other operators
|
|||
|
|
_ => return Ok(None), // Out of scope
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
|||
|
|
dst: result,
|
|||
|
|
op,
|
|||
|
|
lhs,
|
|||
|
|
rhs,
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
Ok(Some(result))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UnaryOp - recursive
|
|||
|
|
ASTNode::UnaryOp { operator, operand, .. } => {
|
|||
|
|
let operand_vid = Self::lower_expr(
|
|||
|
|
operand,
|
|||
|
|
body,
|
|||
|
|
next_value_id,
|
|||
|
|
env,
|
|||
|
|
)?
|
|||
|
|
.ok_or_else(|| Ok(None))?;
|
|||
|
|
|
|||
|
|
let result = ValueId(*next_value_id);
|
|||
|
|
*next_value_id += 1;
|
|||
|
|
|
|||
|
|
let op = match operator {
|
|||
|
|
UnaryOperator::Not => UnaryOpKind::Not,
|
|||
|
|
UnaryOperator::Minus => UnaryOpKind::Neg,
|
|||
|
|
_ => return Ok(None),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
body.push(JoinInst::Compute(MirLikeInst::UnaryOp {
|
|||
|
|
dst: result,
|
|||
|
|
op,
|
|||
|
|
operand: operand_vid,
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
Ok(Some(result))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Call/MethodCall - Phase 141+ で対応
|
|||
|
|
ASTNode::Call { .. } | ASTNode::MethodCall { .. } => {
|
|||
|
|
Ok(None) // Out of scope (Phase 141+)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_ => Ok(None) // Out of scope
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**利点**:
|
|||
|
|
- 新しい operator を追加する際、1箇所だけ修正(総当たりにならない)
|
|||
|
|
- 再帰的なので、ネストした式も自動的に対応
|
|||
|
|
- Phase 141+ で Call/MethodCall を追加しても、Return lowering は変更不要
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 現在の Phase スケジュール
|
|||
|
|
|
|||
|
|
| Phase | 内容 | Status |
|
|||
|
|
|-------|------|--------|
|
|||
|
|
| 131 | loop(true) break-once | ✅ DONE |
|
|||
|
|
| 132-133 | + post assigns | ✅ DONE |
|
|||
|
|
| 134 | NormalizationPlan 統一 | ✅ DONE |
|
|||
|
|
| 135 | post assigns 0個対応 | ✅ DONE |
|
|||
|
|
| 136 | return literal | ✅ DONE |
|
|||
|
|
| 137 | return add expr (x+2) | ✅ DONE |
|
|||
|
|
| 138 | ReturnValueLowererBox SSOT | ✅ DONE |
|
|||
|
|
| 139 | post_if_post_k 統一(計画中) | ⏳ |
|
|||
|
|
| **140** | **ExprLowererBox 初版(pure のみ)** | 📋 提案 |
|
|||
|
|
| 141+ | Call/MethodCall 対応 | 📋 提案 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 質問(ChatGPT Pro 向け)
|
|||
|
|
|
|||
|
|
1. **式の一般化と責務分離**
|
|||
|
|
- ExprLowererBox と MirBuilder の責務の境界は?
|
|||
|
|
- JoinIR 層でやるべきか MIR 層に押し出すべきか?
|
|||
|
|
|
|||
|
|
2. **PHI-free の限界**
|
|||
|
|
- PHI-free は無限に維持可能か?
|
|||
|
|
- ネストした条件式(return if(a) {x} else {y})で PHI-free は可能か?
|
|||
|
|
|
|||
|
|
3. **Pattern2 との統合**
|
|||
|
|
- loop(true) break-once と loop(i < n) をどう統一するか?
|
|||
|
|
- 「canonical」戦略は正しいか?
|
|||
|
|
|
|||
|
|
4. **Call/MethodCall の分離**
|
|||
|
|
- pure expression と impure expression の分離は正しいか?
|
|||
|
|
- 混在する式(x + f(y))の扱いは?
|
|||
|
|
|
|||
|
|
5. **セルフホスティングとの整合性**
|
|||
|
|
- JoinIR 設計は .hako 側でも再現可能か?
|
|||
|
|
- 二重実装の問題をどう解決すべきか?
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 参考: 現在の環境
|
|||
|
|
|
|||
|
|
- **Rust コンパイラ**: `src/mir/control_tree/normalized_shadow/`
|
|||
|
|
- **テスト**: Phase 131-138 全て green(VM + LLVM EXE)
|
|||
|
|
- **セルフホスト**: 開発中(.hako で Nyash コンパイラを実装予定)
|