feat: using system完全実装+旧スモークテストアーカイブ完了

 using nyashstd完全動作(ChatGPT実装)
- builtin:nyashstd自動解決
- 環境変数不要でデフォルト有効
- console.log等の基本機能完備

 Fixture plugin追加(テスト用最小構成)
 v2スモークテスト構造への移行
 旧tools/test/smoke/削除(100+ファイル)

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Selfhosting Dev
2025-09-24 21:45:27 +09:00
parent 6755d9bde1
commit c0978634d9
150 changed files with 2119 additions and 3214 deletions

View File

@ -16,12 +16,16 @@ use crate::mir::{
};
pub struct MirInterpreter {
// SSA value table
// SSA value table (per-function; swapped on call)
regs: HashMap<ValueId, VMValue>,
// Simple local memory for Load/Store where `ptr` is a ValueId token
mem: HashMap<ValueId, VMValue>,
// Object field storage for RefGet/RefSet (keyed by reference ValueId)
obj_fields: HashMap<ValueId, HashMap<String, VMValue>>,
// Function table (current module)
functions: HashMap<String, MirFunction>,
// Currently executing function name (for call resolution preferences)
cur_fn: Option<String>,
}
impl MirInterpreter {
@ -30,11 +34,15 @@ impl MirInterpreter {
regs: HashMap::new(),
mem: HashMap::new(),
obj_fields: HashMap::new(),
functions: HashMap::new(),
cur_fn: None,
}
}
/// Execute module entry (main) and return boxed result
pub fn execute_module(&mut self, module: &MirModule) -> Result<Box<dyn NyashBox>, VMError> {
// Snapshot functions for call resolution
self.functions = module.functions.clone();
let func = module
.functions
.get("main")
@ -44,6 +52,27 @@ impl MirInterpreter {
}
fn execute_function(&mut self, func: &MirFunction) -> Result<VMValue, VMError> {
self._exec_function_inner(func, None)
}
fn _exec_function_inner(
&mut self,
func: &MirFunction,
arg_vals: Option<&[VMValue]>,
) -> Result<VMValue, VMError> {
// Swap in a fresh register file for this call
let saved_regs = std::mem::take(&mut self.regs);
let saved_fn = self.cur_fn.clone();
self.cur_fn = Some(func.signature.name.clone());
// Bind parameters if provided
if let Some(args) = arg_vals {
for (i, pid) in func.params.iter().enumerate() {
let v = args.get(i).cloned().unwrap_or(VMValue::Void);
self.regs.insert(*pid, v);
}
}
let mut cur = func.entry_block;
let mut last_pred: Option<BasicBlockId> = None;
loop {
@ -433,12 +462,12 @@ impl MirInterpreter {
}
}
// Handle terminator
match &block.terminator {
let out = match &block.terminator {
Some(MirInstruction::Return { value }) => {
if let Some(v) = value {
return self.reg_load(*v);
self.reg_load(*v)
} else {
return Ok(VMValue::Void);
Ok(VMValue::Void)
}
}
Some(MirInstruction::Jump { target }) => {
@ -458,18 +487,24 @@ impl MirInterpreter {
continue;
}
None => {
return Err(VMError::InvalidBasicBlock(format!(
Err(VMError::InvalidBasicBlock(format!(
"unterminated block {:?}",
block.id
)))
}
Some(other) => {
return Err(VMError::InvalidInstruction(format!(
Err(VMError::InvalidInstruction(format!(
"invalid terminator in MIR interp: {:?}",
other
)))
}
}
};
// Function finished (return or error)
// Restore previous register file and current function
let result = out;
self.cur_fn = saved_fn;
self.regs = saved_regs;
return result;
}
}
@ -595,13 +630,66 @@ impl MirInterpreter {
}
/// LEGACY: 従来の文字列ベース解決(後方互換性)
fn execute_legacy_call(&mut self, func_id: ValueId, _args: &[ValueId]) -> Result<VMValue, VMError> {
// 従来の実装: func_idから関数名を取得して呼び出し
// 簡易実装 - 実際には関数テーブルやシンボル解決が必要
Err(VMError::InvalidInstruction(format!(
"Legacy function call (ValueId: {}) not implemented in VM interpreter. Please use Callee-typed calls.",
func_id
)))
fn execute_legacy_call(&mut self, func_id: ValueId, args: &[ValueId]) -> Result<VMValue, VMError> {
// 1) 名前を取り出す
let name_val = self.reg_load(func_id)?;
let raw = match name_val {
VMValue::String(ref s) => s.clone(),
other => other.to_string(),
};
// 2) 直接一致を優先
let mut pick: Option<String> = None;
if self.functions.contains_key(&raw) {
pick = Some(raw.clone());
} else {
let arity = args.len();
let mut cands: Vec<String> = Vec::new();
// a) 末尾サフィックス一致: ".name/arity"
let suf = format!(".{}{}", raw, format!("/{}", arity));
for k in self.functions.keys() {
if k.ends_with(&suf) { cands.push(k.clone()); }
}
// b) raw に '/' が含まれ、完全名っぽい場合はそのままも候補に(既に上で除外)
if cands.is_empty() && raw.contains('/') && self.functions.contains_key(&raw) {
cands.push(raw.clone());
}
// c) 優先: 現在のボックス名と一致するもの
if cands.len() > 1 {
if let Some(cur) = &self.cur_fn {
let cur_box = cur.split('.').next().unwrap_or("");
let scoped: Vec<String> = cands
.iter()
.filter(|k| k.starts_with(&format!("{}.", cur_box)))
.cloned()
.collect();
if scoped.len() == 1 { cands = scoped; }
}
}
if cands.len() == 1 {
pick = Some(cands.remove(0));
} else if cands.len() > 1 {
cands.sort();
pick = Some(cands[0].clone());
}
}
let fname = pick.ok_or_else(|| VMError::InvalidInstruction(format!(
"call unresolved: '{}' (arity={})",
raw,
args.len()
)))?;
if std::env::var("NYASH_VM_CALL_TRACE").ok().as_deref() == Some("1") {
eprintln!("[vm] legacy-call resolved '{}' -> '{}'", raw, fname);
}
let callee = self
.functions
.get(&fname)
.cloned()
.ok_or_else(|| VMError::InvalidInstruction(format!("function not found: {}", fname)))?;
// 3) 実引数の評価
let mut argv: Vec<VMValue> = Vec::new();
for a in args { argv.push(self.reg_load(*a)?); }
// 4) 実行
self._exec_function_inner(&callee, Some(&argv))
}
/// グローバル関数実行nyash.builtin.*