vm: extract instruction dispatch into backend::dispatch::execute_instruction; route from vm.rs; keep behavior and env debug flags; moderate refactor
This commit is contained in:
20
CLAUDE.md
20
CLAUDE.md
@ -461,9 +461,10 @@ ls *.md | wc -l # エラー: "ls: 'glob' にアクセスできません
|
|||||||
find . -name "*.rs" # エラー: "glob"になる
|
find . -name "*.rs" # エラー: "glob"になる
|
||||||
ls src/backend/vm_*.rs # エラー: "glob: そのようなファイルやディレクトリはありません"
|
ls src/backend/vm_*.rs # エラー: "glob: そのようなファイルやディレクトリはありません"
|
||||||
|
|
||||||
# ✅ 回避策1: bash -c でラップ
|
# ✅ 回避策1: bash -c でラップ(最も簡単)
|
||||||
bash -c 'ls *.md | wc -l'
|
bash -c 'ls *.md | wc -l'
|
||||||
bash -c 'ls src/backend/vm_*.rs | xargs wc -l'
|
bash -c 'ls src/backend/vm_*.rs | xargs wc -l'
|
||||||
|
# → Claudeではなくbash自身がglob展開するので動作する
|
||||||
|
|
||||||
# ✅ 回避策2: findコマンドを使う(最も確実)
|
# ✅ 回避策2: findコマンドを使う(最も確実)
|
||||||
find src/backend -name "vm_*.rs" -exec wc -l {} \;
|
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`フィールドを使用)
|
**根本原因:** Claudeのコマンド再構築機能のバグ(`pattern`ではなく`op`フィールドを使用)
|
||||||
|
|
||||||
|
### 💡 実践的な使い分けガイド
|
||||||
|
|
||||||
|
**`bash -c`を使うべき時:**
|
||||||
|
- glob展開 + パイプを使う時(`ls *.rs | wc -l`)
|
||||||
|
- 複雑なシェル機能を使う時(リダイレクト、サブシェル等)
|
||||||
|
- 「glob: そのようなファイル...」エラーが出た時
|
||||||
|
|
||||||
|
**findを使うべき時:**
|
||||||
|
- ディレクトリを再帰的に検索する時
|
||||||
|
- より複雑なファイル条件(サイズ、更新日時等)を使う時
|
||||||
|
- 確実性を最優先する時
|
||||||
|
|
||||||
|
**直接ファイル名を書くべき時:**
|
||||||
|
- ファイル数が少ない時(5個以下)
|
||||||
|
- ファイル名が確定している時
|
||||||
|
- スクリプトで使う時(可読性重視)
|
||||||
|
|
||||||
## 🔧 開発サポート
|
## 🔧 開発サポート
|
||||||
|
|
||||||
### 🤖 AI相談
|
### 🤖 AI相談
|
||||||
|
|||||||
@ -6,7 +6,126 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::mir::MirInstruction;
|
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<ControlFlow, VMError> {
|
||||||
|
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::<crate::box_trait::IntegerBox>().map(|x| x.value)
|
||||||
|
.or_else(|| lb.to_string_box().value.trim().parse::<i64>().ok());
|
||||||
|
let ri = rb.as_any().downcast_ref::<crate::box_trait::IntegerBox>().map(|x| x.value)
|
||||||
|
.or_else(|| rb.to_string_box().value.trim().parse::<i64>().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
|
/// Placeholder for an instruction dispatch entry
|
||||||
pub struct DispatchEntry;
|
pub struct DispatchEntry;
|
||||||
@ -23,4 +142,3 @@ impl DispatchTable {
|
|||||||
|
|
||||||
/// Example execution of a dispatch entry
|
/// Example execution of a dispatch entry
|
||||||
pub fn execute_entry(_entry: &DispatchEntry) -> Result<(), VMError> { Ok(()) }
|
pub fn execute_entry(_entry: &DispatchEntry) -> Result<(), VMError> { Ok(()) }
|
||||||
|
|
||||||
|
|||||||
@ -444,205 +444,12 @@ impl VM {
|
|||||||
let debug_exec = debug_global || std::env::var("NYASH_VM_DEBUG_EXEC").ok().as_deref() == Some("1");
|
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); }
|
if debug_exec { eprintln!("[VM] execute_instruction: {:?}", instruction); }
|
||||||
self.record_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::<crate::box_trait::IntegerBox>().map(|x| x.value)
|
|
||||||
.or_else(|| lb.to_string_box().value.trim().parse::<i64>().ok());
|
|
||||||
let ri = rb.as_any().downcast_ref::<crate::box_trait::IntegerBox>().map(|x| x.value)
|
|
||||||
.or_else(|| rb.to_string_box().value.trim().parse::<i64>().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
|
/// Get a value from storage
|
||||||
pub(super) fn get_value(&self, value_id: ValueId) -> Result<VMValue, VMError> {
|
pub(super) fn get_value(&self, value_id: ValueId) -> Result<VMValue, VMError> {
|
||||||
let index = value_id.to_usize();
|
let index = value_id.to_usize();
|
||||||
|
|||||||
Reference in New Issue
Block a user