2025-11-23 08:38:15 +09:00
|
|
|
|
//! JoinIR 実験用のミニ実行器(Phase 27.2)
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! 目的: hand-written / minimal JoinIR を VM と A/B 比較するための軽量ランナー。
|
|
|
|
|
|
//! - 対応値: i64 / bool / String / Unit
|
|
|
|
|
|
//! - 対応命令: Const / BinOp / Compare / BoxCall(StringBox: length, substring) /
|
|
|
|
|
|
//! Call / Jump / Ret
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
//!
|
|
|
|
|
|
//! Phase 27.8: ops box 統合
|
|
|
|
|
|
//! - JoinValue / JoinIrOpError は join_ir_ops から再エクスポート
|
|
|
|
|
|
//! - eval_binop() / eval_compare() を使用(実装を一箇所に集約)
|
2025-11-23 08:38:15 +09:00
|
|
|
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::mir::join_ir::{
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
ConstValue, JoinFuncId, JoinInst, JoinModule, MirLikeInst, VarId,
|
2025-11-23 08:38:15 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
// Phase 27.8: ops box からの再エクスポート
|
|
|
|
|
|
pub use crate::mir::join_ir_ops::{JoinIrOpError, JoinValue};
|
2025-11-23 08:38:15 +09:00
|
|
|
|
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
// Phase 27.8: 互換性のため JoinRuntimeError を JoinIrOpError の別名として保持
|
|
|
|
|
|
pub type JoinRuntimeError = JoinIrOpError;
|
2025-11-23 08:38:15 +09:00
|
|
|
|
|
|
|
|
|
|
pub fn run_joinir_function(
|
|
|
|
|
|
module: &JoinModule,
|
|
|
|
|
|
entry: JoinFuncId,
|
|
|
|
|
|
args: &[JoinValue],
|
|
|
|
|
|
) -> Result<JoinValue, JoinRuntimeError> {
|
|
|
|
|
|
execute_function(module, entry, args.to_vec())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn execute_function(
|
|
|
|
|
|
module: &JoinModule,
|
|
|
|
|
|
mut current_func: JoinFuncId,
|
|
|
|
|
|
mut current_args: Vec<JoinValue>,
|
|
|
|
|
|
) -> Result<JoinValue, JoinRuntimeError> {
|
|
|
|
|
|
'exec: loop {
|
|
|
|
|
|
let func = module
|
|
|
|
|
|
.functions
|
|
|
|
|
|
.get(¤t_func)
|
|
|
|
|
|
.ok_or_else(|| JoinRuntimeError::new(format!("Function {:?} not found", current_func)))?;
|
|
|
|
|
|
|
|
|
|
|
|
if func.params.len() != current_args.len() {
|
|
|
|
|
|
return Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Arity mismatch for {:?}: expected {}, got {}",
|
|
|
|
|
|
func.id,
|
|
|
|
|
|
func.params.len(),
|
|
|
|
|
|
current_args.len()
|
|
|
|
|
|
)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut locals: HashMap<VarId, JoinValue> = HashMap::new();
|
|
|
|
|
|
for (param, arg) in func.params.iter().zip(current_args.iter()) {
|
|
|
|
|
|
locals.insert(*param, arg.clone());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut ip = 0usize;
|
|
|
|
|
|
while ip < func.body.len() {
|
|
|
|
|
|
match &func.body[ip] {
|
|
|
|
|
|
JoinInst::Compute(inst) => {
|
|
|
|
|
|
eval_compute(inst, &mut locals)?;
|
|
|
|
|
|
ip += 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
JoinInst::Call {
|
|
|
|
|
|
func: target,
|
|
|
|
|
|
args,
|
|
|
|
|
|
k_next,
|
|
|
|
|
|
dst,
|
|
|
|
|
|
} => {
|
|
|
|
|
|
if k_next.is_some() {
|
|
|
|
|
|
return Err(JoinRuntimeError::new(
|
|
|
|
|
|
"Join continuation (k_next) is not supported in the experimental runner",
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
let resolved_args = materialize_args(args, &locals)?;
|
|
|
|
|
|
if let Some(dst_var) = dst {
|
|
|
|
|
|
let value = execute_function(module, *target, resolved_args)?;
|
|
|
|
|
|
locals.insert(*dst_var, value);
|
|
|
|
|
|
ip += 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
current_func = *target;
|
|
|
|
|
|
current_args = resolved_args;
|
|
|
|
|
|
continue 'exec;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
JoinInst::Jump { cont: _, args, cond } => {
|
|
|
|
|
|
let should_jump = match cond {
|
|
|
|
|
|
Some(var) => as_bool(&read_var(&locals, *var)?)?,
|
|
|
|
|
|
None => true,
|
|
|
|
|
|
};
|
|
|
|
|
|
if should_jump {
|
|
|
|
|
|
let ret = if let Some(first) = args.first() {
|
|
|
|
|
|
read_var(&locals, *first)?
|
|
|
|
|
|
} else {
|
|
|
|
|
|
JoinValue::Unit
|
|
|
|
|
|
};
|
|
|
|
|
|
return Ok(ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
ip += 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
JoinInst::Ret { value } => {
|
|
|
|
|
|
let ret = match value {
|
|
|
|
|
|
Some(var) => read_var(&locals, *var)?,
|
|
|
|
|
|
None => JoinValue::Unit,
|
|
|
|
|
|
};
|
|
|
|
|
|
return Ok(ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// fallthrough without explicit return
|
|
|
|
|
|
return Ok(JoinValue::Unit);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn eval_compute(inst: &MirLikeInst, locals: &mut HashMap<VarId, JoinValue>) -> Result<(), JoinRuntimeError> {
|
|
|
|
|
|
match inst {
|
|
|
|
|
|
MirLikeInst::Const { dst, value } => {
|
|
|
|
|
|
let v = match value {
|
|
|
|
|
|
ConstValue::Integer(i) => JoinValue::Int(*i),
|
|
|
|
|
|
ConstValue::Bool(b) => JoinValue::Bool(*b),
|
|
|
|
|
|
ConstValue::String(s) => JoinValue::Str(s.clone()),
|
|
|
|
|
|
ConstValue::Null => JoinValue::Unit,
|
|
|
|
|
|
};
|
|
|
|
|
|
locals.insert(*dst, v);
|
|
|
|
|
|
}
|
|
|
|
|
|
MirLikeInst::BinOp { dst, op, lhs, rhs } => {
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
// Phase 27.8: ops box の eval_binop() を使用
|
2025-11-23 08:38:15 +09:00
|
|
|
|
let l = read_var(locals, *lhs)?;
|
|
|
|
|
|
let r = read_var(locals, *rhs)?;
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
let v = crate::mir::join_ir_ops::eval_binop(*op, &l, &r)?;
|
2025-11-23 08:38:15 +09:00
|
|
|
|
locals.insert(*dst, v);
|
|
|
|
|
|
}
|
|
|
|
|
|
MirLikeInst::Compare { dst, op, lhs, rhs } => {
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
// Phase 27.8: ops box の eval_compare() を使用
|
2025-11-23 08:38:15 +09:00
|
|
|
|
let l = read_var(locals, *lhs)?;
|
|
|
|
|
|
let r = read_var(locals, *rhs)?;
|
feat(joinir): Phase 27.8-1~3 — Ops Box導入 + Toggle対応完了
## Phase 27.8-1: JoinIR 命令意味箱(Ops Box)作成 ✅
**新規ファイル**: `src/mir/join_ir_ops.rs`
- `eval_binop()`: Add, Sub, Mul, Div, Or, And の評価ロジック一元化
- `eval_compare()`: Lt, Le, Gt, Ge, Eq, Ne の比較ロジック一元化
- エラー処理: `JoinIrOpError` 型で型安全
- 完全テストカバレッジ: 13個のユニットテスト
**効果**:
- BinOp/Compare の評価ロジックを一箇所に集約
- 再利用可能な API で将来の拡張が容易
- テスタビリティ向上
## Phase 27.8-2: join_ir_runner.rs の Ops Box 統合 ✅
**変更**: `src/mir/join_ir_runner.rs`
- BinOp/Compare の実装を ops box に完全移譲(約70行削減)
- `JoinValue` / `JoinIrOpError` を ops box から再エクスポート
- 後方互換性維持: `JoinRuntimeError = JoinIrOpError`
**効果**:
- コード重複削減(約70行)
- 実装の一貫性保証(ops box の単一実装を使用)
## Phase 27.8-3: MIR→JoinIR Toggle 対応 ✅
**変更**: `src/mir/join_ir.rs`
- `lower_skip_ws_to_joinir()`: トグル対応ディスパッチャー
- `lower_skip_ws_handwritten()`: 既存実装をリネーム(Phase 27.1-27.7)
- `lower_skip_ws_from_mir()`: MIR自動解析版スタブ(Phase 27.8-4 で実装予定)
**環境変数制御**:
```bash
# 手書き版(デフォルト)
./target/release/hakorune program.hako
# MIR自動解析版(Phase 27.8-4 実装予定)
NYASH_JOINIR_LOWER_FROM_MIR=1 ./target/release/hakorune program.hako
```
**効果**:
- 段階的な移行が可能(既存動作を完全に維持)
- A/B テストによる検証が容易
## 変更ファイル
- `src/mir/join_ir_ops.rs` (新規): Ops Box 実装
- `src/mir/join_ir_runner.rs`: Ops Box 使用に変更
- `src/mir/join_ir.rs`: Toggle 対応ディスパッチャー追加
- `src/mir/mod.rs`: join_ir_ops モジュール追加
## コンパイル結果
✅ 0 errors, 18 warnings(既存警告のみ)
✅ ビルド成功
## 次のステップ
**Phase 27.8-4**: `lower_skip_ws_from_mir()` 本実装
- MirQuery を使った MIR 解析
- パターンマッチング(init, header, break checks, body)
- JoinIR 自動生成(entry function + loop_step function)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 14:47:00 +09:00
|
|
|
|
let v = crate::mir::join_ir_ops::eval_compare(*op, &l, &r)?;
|
|
|
|
|
|
locals.insert(*dst, v);
|
2025-11-23 08:38:15 +09:00
|
|
|
|
}
|
2025-11-24 08:01:56 +09:00
|
|
|
|
// S-5.2: BoxCall → VM method_router 経由(ガードレール設計)
|
|
|
|
|
|
// - 制御フロー: JoinIR Runner が担当
|
|
|
|
|
|
// - Box/Plugin 実装: Rust VM に委譲(VM 2号機を避ける)
|
2025-11-23 08:38:15 +09:00
|
|
|
|
MirLikeInst::BoxCall {
|
|
|
|
|
|
dst,
|
|
|
|
|
|
box_name,
|
|
|
|
|
|
method,
|
|
|
|
|
|
args,
|
|
|
|
|
|
} => {
|
|
|
|
|
|
if box_name != "StringBox" {
|
|
|
|
|
|
return Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Unsupported box call target: {}",
|
|
|
|
|
|
box_name
|
|
|
|
|
|
)));
|
|
|
|
|
|
}
|
|
|
|
|
|
match method.as_str() {
|
|
|
|
|
|
"length" => {
|
|
|
|
|
|
let arg = expect_str(&read_var(locals, args[0])?)?;
|
2025-11-24 08:01:56 +09:00
|
|
|
|
// S-5.2: VM の StringBox.length() 実装を使用(hardcoded 削除)
|
|
|
|
|
|
let string_box = crate::boxes::basic::StringBox::new(arg);
|
|
|
|
|
|
let result_box = string_box.length();
|
|
|
|
|
|
let result_value = box_to_join_value(result_box)?;
|
|
|
|
|
|
let dst_var = dst.ok_or_else(|| {
|
2025-11-23 08:38:15 +09:00
|
|
|
|
JoinRuntimeError::new("length call requires destination")
|
2025-11-24 08:01:56 +09:00
|
|
|
|
})?;
|
|
|
|
|
|
locals.insert(dst_var, result_value);
|
2025-11-23 08:38:15 +09:00
|
|
|
|
}
|
|
|
|
|
|
"substring" => {
|
|
|
|
|
|
if args.len() != 3 {
|
|
|
|
|
|
return Err(JoinRuntimeError::new(
|
|
|
|
|
|
"substring expects 3 arguments (s, start, end)",
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
let s = expect_str(&read_var(locals, args[0])?)?;
|
2025-11-24 08:01:56 +09:00
|
|
|
|
let start = expect_int(&read_var(locals, args[1])?)? as usize;
|
|
|
|
|
|
let end = expect_int(&read_var(locals, args[2])?)? as usize;
|
|
|
|
|
|
// S-5.2: VM の StringBox.substring() 実装を使用(hardcoded 削除)
|
|
|
|
|
|
let string_box = crate::boxes::basic::StringBox::new(s);
|
|
|
|
|
|
let result_box = string_box.substring(start, end);
|
|
|
|
|
|
let result_value = box_to_join_value(result_box)?;
|
2025-11-23 08:38:15 +09:00
|
|
|
|
let dst_var = dst.ok_or_else(|| {
|
|
|
|
|
|
JoinRuntimeError::new("substring call requires destination")
|
|
|
|
|
|
})?;
|
2025-11-24 08:01:56 +09:00
|
|
|
|
locals.insert(dst_var, result_value);
|
2025-11-23 08:38:15 +09:00
|
|
|
|
}
|
|
|
|
|
|
_ => {
|
|
|
|
|
|
return Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Unsupported StringBox method: {}",
|
|
|
|
|
|
method
|
|
|
|
|
|
)))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn read_var(locals: &HashMap<VarId, JoinValue>, var: VarId) -> Result<JoinValue, JoinRuntimeError> {
|
|
|
|
|
|
locals
|
|
|
|
|
|
.get(&var)
|
|
|
|
|
|
.cloned()
|
|
|
|
|
|
.ok_or_else(|| JoinRuntimeError::new(format!("Variable {:?} not bound", var)))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn materialize_args(
|
|
|
|
|
|
args: &[VarId],
|
|
|
|
|
|
locals: &HashMap<VarId, JoinValue>,
|
|
|
|
|
|
) -> Result<Vec<JoinValue>, JoinRuntimeError> {
|
|
|
|
|
|
args.iter().map(|v| read_var(locals, *v)).collect()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn as_bool(value: &JoinValue) -> Result<bool, JoinRuntimeError> {
|
|
|
|
|
|
match value {
|
|
|
|
|
|
JoinValue::Bool(b) => Ok(*b),
|
|
|
|
|
|
JoinValue::Int(i) => Ok(*i != 0),
|
|
|
|
|
|
JoinValue::Unit => Ok(false),
|
|
|
|
|
|
other => Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Expected bool-compatible value, got {:?}",
|
|
|
|
|
|
other
|
|
|
|
|
|
))),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn expect_int(value: &JoinValue) -> Result<i64, JoinRuntimeError> {
|
|
|
|
|
|
match value {
|
|
|
|
|
|
JoinValue::Int(i) => Ok(*i),
|
|
|
|
|
|
other => Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Expected int, got {:?}",
|
|
|
|
|
|
other
|
|
|
|
|
|
))),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn expect_str(value: &JoinValue) -> Result<String, JoinRuntimeError> {
|
|
|
|
|
|
match value {
|
|
|
|
|
|
JoinValue::Str(s) => Ok(s.clone()),
|
|
|
|
|
|
other => Err(JoinRuntimeError::new(format!(
|
|
|
|
|
|
"Expected string, got {:?}",
|
|
|
|
|
|
other
|
|
|
|
|
|
))),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-24 08:01:56 +09:00
|
|
|
|
|
|
|
|
|
|
/// S-5.2: Convert Box<dyn NyashBox> from VM to JoinValue
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Tries to downcast to known primitive types first (IntegerBox, BoolBox, StringBox),
|
|
|
|
|
|
/// otherwise wraps as BoxRef for future use.
|
|
|
|
|
|
fn box_to_join_value(nyash_box: Box<dyn crate::box_trait::NyashBox>) -> Result<JoinValue, JoinRuntimeError> {
|
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
|
|
// Try to downcast to known primitive types first
|
|
|
|
|
|
if let Some(int_box) = nyash_box.as_any().downcast_ref::<crate::boxes::basic::IntegerBox>() {
|
|
|
|
|
|
return Ok(JoinValue::Int(int_box.value));
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(bool_box) = nyash_box.as_any().downcast_ref::<crate::boxes::basic::BoolBox>() {
|
|
|
|
|
|
return Ok(JoinValue::Bool(bool_box.value));
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(str_box) = nyash_box.as_any().downcast_ref::<crate::boxes::basic::StringBox>() {
|
|
|
|
|
|
return Ok(JoinValue::Str(str_box.value.clone()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Otherwise, wrap as BoxRef (for S-5.3/S-5.4 future use)
|
|
|
|
|
|
Ok(JoinValue::BoxRef(Arc::from(nyash_box)))
|
|
|
|
|
|
}
|