diff --git a/CLAUDE.md b/CLAUDE.md index a42efc93..ba1e259f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -461,9 +461,10 @@ ls *.md | wc -l # エラー: "ls: 'glob' にアクセスできません find . -name "*.rs" # エラー: "glob"になる ls src/backend/vm_*.rs # エラー: "glob: そのようなファイルやディレクトリはありません" -# ✅ 回避策1: bash -c でラップ +# ✅ 回避策1: bash -c でラップ(最も簡単) bash -c 'ls *.md | wc -l' bash -c 'ls src/backend/vm_*.rs | xargs wc -l' +# → Claudeではなくbash自身がglob展開するので動作する # ✅ 回避策2: findコマンドを使う(最も確実) find src/backend -name "vm_*.rs" -exec wc -l {} \; @@ -483,6 +484,23 @@ ls src/backend/ | grep "^vm_" | xargs -I{} wc -l src/backend/{} **根本原因:** Claudeのコマンド再構築機能のバグ(`pattern`ではなく`op`フィールドを使用) +### 💡 実践的な使い分けガイド + +**`bash -c`を使うべき時:** +- glob展開 + パイプを使う時(`ls *.rs | wc -l`) +- 複雑なシェル機能を使う時(リダイレクト、サブシェル等) +- 「glob: そのようなファイル...」エラーが出た時 + +**findを使うべき時:** +- ディレクトリを再帰的に検索する時 +- より複雑なファイル条件(サイズ、更新日時等)を使う時 +- 確実性を最優先する時 + +**直接ファイル名を書くべき時:** +- ファイル数が少ない時(5個以下) +- ファイル名が確定している時 +- スクリプトで使う時(可読性重視) + ## 🔧 開発サポート ### 🤖 AI相談 diff --git a/src/backend/dispatch.rs b/src/backend/dispatch.rs index 75cb4050..c6151faa 100644 --- a/src/backend/dispatch.rs +++ b/src/backend/dispatch.rs @@ -6,7 +6,126 @@ */ use crate::mir::MirInstruction; -use super::vm::{VMError}; +use super::vm::{VM, VMError}; +use super::vm::ControlFlow; +use crate::mir::CompareOp; +use super::vm::VMValue; + +/// Minimal dispatcher that routes a single instruction to the appropriate handler. +/// Keeps behavior identical to the big match in vm.rs but centralized here. +pub fn execute_instruction(vm: &mut VM, instruction: &MirInstruction, debug_global: bool) -> Result { + match instruction { + // Basic operations + MirInstruction::Const { dst, value } => vm.execute_const(*dst, value), + + MirInstruction::BinOp { dst, op, lhs, rhs } => { + if debug_global || std::env::var("NYASH_VM_DEBUG_ANDOR").ok().as_deref() == Some("1") { + eprintln!("[VM] execute_instruction -> BinOp({:?})", op); + } + vm.execute_binop(*dst, op, *lhs, *rhs) + }, + + MirInstruction::UnaryOp { dst, op, operand } => vm.execute_unaryop(*dst, op, *operand), + + MirInstruction::Compare { dst, op, lhs, rhs } => { + let debug_cmp = debug_global || std::env::var("NYASH_VM_DEBUG_CMP").ok().as_deref() == Some("1"); + if debug_cmp { eprintln!("[VM] dispatch Compare op={:?} lhs={:?} rhs={:?}", op, lhs, rhs); } + if let (Ok(lv), Ok(rv)) = (vm.get_value(*lhs), vm.get_value(*rhs)) { + if debug_cmp { eprintln!("[VM] values before fastpath: left={:?} right={:?}", lv, rv); } + if let (VMValue::BoxRef(lb), VMValue::BoxRef(rb)) = (&lv, &rv) { + if debug_cmp { eprintln!("[VM] BoxRef types: lty={} rty={} lstr={} rstr={}", lb.type_name(), rb.type_name(), lb.to_string_box().value, rb.to_string_box().value); } + let li = lb.as_any().downcast_ref::().map(|x| x.value) + .or_else(|| lb.to_string_box().value.trim().parse::().ok()); + let ri = rb.as_any().downcast_ref::().map(|x| x.value) + .or_else(|| rb.to_string_box().value.trim().parse::().ok()); + if let (Some(li), Some(ri)) = (li, ri) { + let out = match op { CompareOp::Eq => li == ri, CompareOp::Ne => li != ri, CompareOp::Lt => li < ri, CompareOp::Le => li <= ri, CompareOp::Gt => li > ri, CompareOp::Ge => li >= ri }; + vm.set_value(*dst, VMValue::Bool(out)); + return Ok(ControlFlow::Continue); + } + } + } + vm.execute_compare(*dst, op, *lhs, *rhs) + }, + + // I/O operations + MirInstruction::Print { value, .. } => vm.execute_print(*value), + + // Type operations + MirInstruction::TypeOp { dst, op, value, ty } => vm.execute_typeop(*dst, op, *value, ty), + + // Control flow + MirInstruction::Return { value } => vm.execute_return(*value), + MirInstruction::Jump { target } => vm.execute_jump(*target), + MirInstruction::Branch { condition, then_bb, else_bb } => vm.execute_branch(*condition, *then_bb, *else_bb), + MirInstruction::Phi { dst, inputs } => vm.execute_phi(*dst, inputs), + + // Memory operations + MirInstruction::Load { dst, ptr } => vm.execute_load(*dst, *ptr), + MirInstruction::Store { value, ptr } => vm.execute_store(*value, *ptr), + MirInstruction::Copy { dst, src } => vm.execute_copy(*dst, *src), + + // Complex operations + MirInstruction::Call { dst, func, args, effects: _ } => vm.execute_call(*dst, *func, args), + MirInstruction::BoxCall { dst, box_val, method, args, effects: _ } => vm.execute_boxcall(*dst, *box_val, method, args), + MirInstruction::NewBox { dst, box_type, args } => vm.execute_newbox(*dst, box_type, args), + + // Array operations + MirInstruction::ArrayGet { dst, array, index } => vm.execute_array_get(*dst, *array, *index), + MirInstruction::ArraySet { array, index, value } => vm.execute_array_set(*array, *index, *value), + + // Reference operations + MirInstruction::RefNew { dst, box_val } => vm.execute_ref_new(*dst, *box_val), + MirInstruction::RefGet { dst, reference, field } => vm.execute_ref_get(*dst, *reference, field), + MirInstruction::RefSet { reference, field, value } => vm.execute_ref_set(*reference, field, *value), + + // Weak references + MirInstruction::WeakNew { dst, box_val } => vm.execute_weak_new(*dst, *box_val), + MirInstruction::WeakLoad { dst, weak_ref } => vm.execute_weak_load(*dst, *weak_ref), + MirInstruction::WeakRef { dst, op, value } => match op { + crate::mir::WeakRefOp::New => vm.execute_weak_new(*dst, *value), + crate::mir::WeakRefOp::Load => vm.execute_weak_load(*dst, *value), + }, + + // Barriers + MirInstruction::BarrierRead { .. } => Ok(ControlFlow::Continue), + MirInstruction::BarrierWrite { .. } => Ok(ControlFlow::Continue), + MirInstruction::Barrier { .. } => Ok(ControlFlow::Continue), + + // Exceptions + MirInstruction::Throw { exception, .. } => vm.execute_throw(*exception), + MirInstruction::Catch { exception_value, .. } => vm.execute_catch(*exception_value), + + // Futures + MirInstruction::FutureNew { dst, value } => { + let initial_value = vm.get_value(*value)?; + let future = crate::boxes::future::FutureBox::new(); + let nyash_box = initial_value.to_nyash_box(); + future.set_result(nyash_box); + vm.set_value(*dst, VMValue::Future(future)); + Ok(ControlFlow::Continue) + } + MirInstruction::FutureSet { future, value } => { + let future_val = vm.get_value(*future)?; + let new_value = vm.get_value(*value)?; + if let VMValue::Future(ref future_box) = future_val { + future_box.set_result(new_value.to_nyash_box()); + Ok(ControlFlow::Continue) + } else { + Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val))) + } + } + + // Special + MirInstruction::Await { dst, future } => vm.execute_await(*dst, *future), + MirInstruction::ExternCall { dst, iface_name, method_name, args, .. } => vm.execute_extern_call(*dst, iface_name, method_name, args), + MirInstruction::TypeCheck { dst, .. } => { vm.set_value(*dst, VMValue::Bool(true)); Ok(ControlFlow::Continue) } + MirInstruction::Cast { dst, value, .. } => { let val = vm.get_value(*value)?; vm.set_value(*dst, val); Ok(ControlFlow::Continue) } + MirInstruction::Debug { .. } => Ok(ControlFlow::Continue), + MirInstruction::Nop => Ok(ControlFlow::Continue), + MirInstruction::Safepoint => Ok(ControlFlow::Continue), + } +} /// Placeholder for an instruction dispatch entry pub struct DispatchEntry; @@ -23,4 +142,3 @@ impl DispatchTable { /// Example execution of a dispatch entry pub fn execute_entry(_entry: &DispatchEntry) -> Result<(), VMError> { Ok(()) } - diff --git a/src/backend/vm.rs b/src/backend/vm.rs index 6fbe7dd5..ffda221b 100644 --- a/src/backend/vm.rs +++ b/src/backend/vm.rs @@ -444,203 +444,10 @@ impl VM { let debug_exec = debug_global || std::env::var("NYASH_VM_DEBUG_EXEC").ok().as_deref() == Some("1"); if debug_exec { eprintln!("[VM] execute_instruction: {:?}", instruction); } self.record_instruction(instruction); + super::dispatch::execute_instruction(self, instruction, debug_global) - match instruction { - // Basic operations - MirInstruction::Const { dst, value } => - self.execute_const(*dst, value), - - MirInstruction::BinOp { dst, op, lhs, rhs } => { - if debug_global || std::env::var("NYASH_VM_DEBUG_ANDOR").ok().as_deref() == Some("1") { - eprintln!("[VM] execute_instruction -> BinOp({:?})", op); - } - self.execute_binop(*dst, op, *lhs, *rhs) - }, - - MirInstruction::UnaryOp { dst, op, operand } => - self.execute_unaryop(*dst, op, *operand), - - MirInstruction::Compare { dst, op, lhs, rhs } => { - let debug_cmp = debug_global || std::env::var("NYASH_VM_DEBUG_CMP").ok().as_deref() == Some("1"); - if debug_cmp { eprintln!("[VM] dispatch Compare op={:?} lhs={:?} rhs={:?}", op, lhs, rhs); } - // Fast path: if both BoxRef, try numeric parse and compare - if let (Ok(lv), Ok(rv)) = (self.get_value(*lhs), self.get_value(*rhs)) { - if debug_cmp { eprintln!("[VM] values before fastpath: left={:?} right={:?}", lv, rv); } - if let (VMValue::BoxRef(lb), VMValue::BoxRef(rb)) = (&lv, &rv) { - if debug_cmp { eprintln!("[VM] BoxRef types: lty={} rty={} lstr={} rstr={}", lb.type_name(), rb.type_name(), lb.to_string_box().value, rb.to_string_box().value); } - let li = lb.as_any().downcast_ref::().map(|x| x.value) - .or_else(|| lb.to_string_box().value.trim().parse::().ok()); - let ri = rb.as_any().downcast_ref::().map(|x| x.value) - .or_else(|| rb.to_string_box().value.trim().parse::().ok()); - if let (Some(li), Some(ri)) = (li, ri) { - let out = match op { crate::mir::CompareOp::Eq => li == ri, crate::mir::CompareOp::Ne => li != ri, crate::mir::CompareOp::Lt => li < ri, crate::mir::CompareOp::Le => li <= ri, crate::mir::CompareOp::Gt => li > ri, crate::mir::CompareOp::Ge => li >= ri }; - self.set_value(*dst, VMValue::Bool(out)); - return Ok(ControlFlow::Continue); - } - } - } - self.execute_compare(*dst, op, *lhs, *rhs) - }, - - // I/O operations - MirInstruction::Print { value, .. } => - self.execute_print(*value), - - // Type operations - MirInstruction::TypeOp { dst, op, value, ty } => - self.execute_typeop(*dst, op, *value, ty), - - // Control flow - MirInstruction::Return { value } => - self.execute_return(*value), - - MirInstruction::Jump { target } => - self.execute_jump(*target), - - MirInstruction::Branch { condition, then_bb, else_bb } => - self.execute_branch(*condition, *then_bb, *else_bb), - - MirInstruction::Phi { dst, inputs } => - self.execute_phi(*dst, inputs), - - // Memory operations - MirInstruction::Load { dst, ptr } => - self.execute_load(*dst, *ptr), - - MirInstruction::Store { value, ptr } => - self.execute_store(*value, *ptr), - - MirInstruction::Copy { dst, src } => - self.execute_copy(*dst, *src), - - // Complex operations - MirInstruction::Call { dst, func, args, effects: _ } => - self.execute_call(*dst, *func, args), - - MirInstruction::BoxCall { dst, box_val, method, args, effects: _ } => - self.execute_boxcall(*dst, *box_val, method, args), - - MirInstruction::NewBox { dst, box_type, args } => - self.execute_newbox(*dst, box_type, args), - - // Array operations - MirInstruction::ArrayGet { dst, array, index } => - self.execute_array_get(*dst, *array, *index), - - MirInstruction::ArraySet { array, index, value } => - self.execute_array_set(*array, *index, *value), - - // Reference operations - MirInstruction::RefNew { dst, box_val } => - self.execute_ref_new(*dst, *box_val), - - MirInstruction::RefGet { dst, reference, field } => - self.execute_ref_get(*dst, *reference, field), - - MirInstruction::RefSet { reference, field, value } => - self.execute_ref_set(*reference, field, *value), - - // Weak references - MirInstruction::WeakNew { dst, box_val } => - self.execute_weak_new(*dst, *box_val), - - MirInstruction::WeakLoad { dst, weak_ref } => - self.execute_weak_load(*dst, *weak_ref), - - // Unified weak reference operations - MirInstruction::WeakRef { dst, op, value } => { - match op { - crate::mir::WeakRefOp::New => { - self.execute_weak_new(*dst, *value) - } - crate::mir::WeakRefOp::Load => { - self.execute_weak_load(*dst, *value) - } - } - } - - // Barriers - MirInstruction::BarrierRead { ptr: _ } => { - // Memory barrier read is a no-op for now - Ok(ControlFlow::Continue) - } - - MirInstruction::BarrierWrite { ptr: _ } => { - // Memory barrier write is a no-op for now - Ok(ControlFlow::Continue) - } - - MirInstruction::Barrier { .. } => { - // Unified barrier is a no-op for now - Ok(ControlFlow::Continue) - } - - // Exception handling - MirInstruction::Throw { exception, effects: _ } => - self.execute_throw(*exception), - - MirInstruction::Catch { exception_type: _, exception_value, handler_bb: _ } => - self.execute_catch(*exception_value), - - // Future operations - MirInstruction::FutureNew { dst, value } => { - let initial_value = self.get_value(*value)?; - let future = crate::boxes::future::FutureBox::new(); - let nyash_box = initial_value.to_nyash_box(); - future.set_result(nyash_box); - self.set_value(*dst, VMValue::Future(future)); - Ok(ControlFlow::Continue) - } - - MirInstruction::FutureSet { future, value } => { - let future_val = self.get_value(*future)?; - let new_value = self.get_value(*value)?; - - if let VMValue::Future(ref future_box) = future_val { - future_box.set_result(new_value.to_nyash_box()); - Ok(ControlFlow::Continue) - } else { - Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val))) - } - } - - // Special operations - MirInstruction::Await { dst, future } => - self.execute_await(*dst, *future), - - MirInstruction::ExternCall { dst, iface_name, method_name, args, effects: _ } => - self.execute_extern_call(*dst, iface_name, method_name, args), - - // Deprecated/No-op instructions - MirInstruction::TypeCheck { dst, value: _, expected_type: _ } => { - // TypeCheck is deprecated in favor of TypeOp - self.set_value(*dst, VMValue::Bool(true)); - Ok(ControlFlow::Continue) - } - - MirInstruction::Cast { dst, value, target_type: _ } => { - // Cast is deprecated in favor of TypeOp - let val = self.get_value(*value)?; - self.set_value(*dst, val); - Ok(ControlFlow::Continue) - } - - MirInstruction::Debug { value: _, message: _ } => { - // Debug is a no-op in release mode - Ok(ControlFlow::Continue) - } - - MirInstruction::Nop => { - // No operation - Ok(ControlFlow::Continue) - } - - MirInstruction::Safepoint => { - // Safepoint for future GC/async support - Ok(ControlFlow::Continue) - } - } } + /// Get a value from storage