Phase 12.7完了 + ChatGPT5によるVMリファクタリング

## 📚 Phase 12.7 ドキュメント整理
- ChatGPT5作成のANCP Token仕様書v1を整備
- フォルダ構造を機能別に再編成:
  - ancp-specs/ : ANCP圧縮技法仕様
  - grammar-specs/ : 文法改革仕様
  - implementation/ : 実装計画
  - ai-feedback/ : AIアドバイザーフィードバック
- 各フォルダにREADME.md作成で導線改善

## 🔧 ChatGPT5によるVMリファクタリング
- vm_instructions.rs (1927行) をモジュール分割:
  - boxcall.rs : Box呼び出し処理
  - call.rs : 関数呼び出し処理
  - extern_call.rs : 外部関数処理
  - function_new.rs : FunctionBox生成
  - newbox.rs : Box生成処理
  - plugin_invoke.rs : プラグイン呼び出し
- VM実行をファイル分割で整理:
  - vm_state.rs : 状態管理
  - vm_exec.rs : 実行エンジン
  - vm_control_flow.rs : 制御フロー
  - vm_gc.rs : GC処理
- plugin_loader_v2もモジュール化

##  新機能実装
- FunctionBox呼び出しのVM/MIR統一進捗
- ラムダ式のFunctionBox変換テスト追加
- 関数値の直接呼び出し基盤整備

次ステップ: ANCPプロトタイプ実装開始(Week 1)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-09-04 03:41:02 +09:00
parent 7455c9ec97
commit 6488b0542e
57 changed files with 3803 additions and 3871 deletions

View File

@ -0,0 +1,65 @@
use crate::interpreter::NyashInterpreter;
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, IntegerBox};
#[test]
fn functionbox_call_via_variable_with_capture() {
let mut interp = NyashInterpreter::new();
// local x = 10
interp.declare_local_variable("x", Box::new(IntegerBox::new(10)));
// f = function() { return x }
let lam = ASTNode::Lambda { params: vec![], body: vec![
ASTNode::Return { value: Some(Box::new(ASTNode::Variable { name: "x".to_string(), span: crate::ast::Span::unknown() })), span: crate::ast::Span::unknown() }
], span: crate::ast::Span::unknown() };
let assign_f = ASTNode::Assignment {
target: Box::new(ASTNode::Variable { name: "f".to_string(), span: crate::ast::Span::unknown() }),
value: Box::new(lam.clone()),
span: crate::ast::Span::unknown(),
};
let _ = interp.execute_statement(&assign_f).expect("assign f");
// x = 20
let assign_x = ASTNode::Assignment {
target: Box::new(ASTNode::Variable { name: "x".to_string(), span: crate::ast::Span::unknown() }),
value: Box::new(ASTNode::Literal { value: crate::ast::LiteralValue::Integer(20), span: crate::ast::Span::unknown() }),
span: crate::ast::Span::unknown(),
};
let _ = interp.execute_statement(&assign_x).expect("assign x");
// return f()
let call_f = ASTNode::Call { callee: Box::new(ASTNode::Variable { name: "f".to_string(), span: crate::ast::Span::unknown() }), arguments: vec![], span: crate::ast::Span::unknown() };
let out = interp.execute_expression(&call_f).expect("call f");
let ib = out.as_any().downcast_ref::<IntegerBox>().expect("integer ret");
assert_eq!(ib.value, 20);
}
#[test]
fn functionbox_call_via_field() {
let mut interp = NyashInterpreter::new();
// obj with field f
let inst = crate::instance_v2::InstanceBox::from_declaration("C".to_string(), vec!["f".to_string()], std::collections::HashMap::new());
interp.declare_local_variable("obj", Box::new(inst.clone()));
// obj.f = function(a){ return a }
let lam = ASTNode::Lambda { params: vec!["a".to_string()], body: vec![
ASTNode::Return { value: Some(Box::new(ASTNode::Variable { name: "a".to_string(), span: crate::ast::Span::unknown() })), span: crate::ast::Span::unknown() }
], span: crate::ast::Span::unknown() };
let assign = ASTNode::Assignment {
target: Box::new(ASTNode::FieldAccess { object: Box::new(ASTNode::Variable { name: "obj".to_string(), span: crate::ast::Span::unknown() }), field: "f".to_string(), span: crate::ast::Span::unknown() }),
value: Box::new(lam.clone()),
span: crate::ast::Span::unknown(),
};
let _ = interp.execute_statement(&assign).expect("assign field");
// return (obj.f)(7)
let call = ASTNode::Call {
callee: Box::new(ASTNode::FieldAccess { object: Box::new(ASTNode::Variable { name: "obj".to_string(), span: crate::ast::Span::unknown() }), field: "f".to_string(), span: crate::ast::Span::unknown() }),
arguments: vec![ASTNode::Literal { value: crate::ast::LiteralValue::Integer(7), span: crate::ast::Span::unknown() }],
span: crate::ast::Span::unknown(),
};
let out = interp.execute_expression(&call).expect("call obj.f");
let ib = out.as_any().downcast_ref::<IntegerBox>().expect("integer ret");
assert_eq!(ib.value, 7);
}

View File

@ -0,0 +1,25 @@
use crate::parser::NyashParser;
use crate::mir::{MirCompiler};
use crate::backend::VM;
#[test]
fn lambda_value_then_call_returns_increment() {
// Nyash code:
// f = function(a) { return a + 1 }
// f(41)
let code = r#"
f = function(a) {
return a + 1
}
f(41)
"#;
let ast = NyashParser::parse_from_string(code).expect("parse");
let mut mc = MirCompiler::new();
let cr = mc.compile(ast).expect("mir");
// Execute on VM
let mut vm = VM::new();
let out = vm.execute_module(&cr.module).expect("vm exec");
if let crate::backend::vm::VMValue::Integer(i) = out { assert_eq!(i, 42); }
else { panic!("Expected Integer 42, got {:?}", out); }
}

View File

@ -0,0 +1,49 @@
use crate::mir::{MirModule, MirFunction, FunctionSignature, MirInstruction, EffectMask, BasicBlockId, ConstValue};
use crate::backend::vm::VM;
use crate::backend::vm::VMValue;
use crate::boxes::function_box::{FunctionBox, ClosureEnv};
use crate::box_trait::NyashBox;
#[test]
fn vm_call_functionbox_returns_42() {
// Build FunctionBox: function(a) { return a + 1 }
let params = vec!["a".to_string()];
let body = vec![
crate::ast::ASTNode::Return {
value: Some(Box::new(crate::ast::ASTNode::BinaryOp {
left: Box::new(crate::ast::ASTNode::Variable { name: "a".to_string(), span: crate::ast::Span::unknown() }),
operator: crate::ast::BinaryOperator::Add,
right: Box::new(crate::ast::ASTNode::Literal { value: crate::ast::LiteralValue::Integer(1), span: crate::ast::Span::unknown() }),
span: crate::ast::Span::unknown(),
})),
span: crate::ast::Span::unknown(),
}
];
let fun = FunctionBox::with_env(params, body, ClosureEnv::new());
// Build MIR: arg=41; res = call func_id(arg); return res
let sig = FunctionSignature { name: "main".into(), params: vec![], return_type: crate::mir::MirType::Integer, effects: EffectMask::PURE };
let mut f = MirFunction::new(sig, BasicBlockId::new(0));
let bb = f.entry_block;
// Reserve an id for function value (we'll inject VMValue::BoxRef later)
let func_id = f.next_value_id();
// arg const
let arg = f.next_value_id();
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Const { dst: arg, value: ConstValue::Integer(41) });
// call
let res = f.next_value_id();
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Call { dst: Some(res), func: func_id, args: vec![arg], effects: EffectMask::PURE });
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Return { value: Some(res) });
let mut m = MirModule::new("vm_funbox".into());
m.add_function(f.clone());
// Prepare VM and inject FunctionBox into func_id
let mut vm = VM::new();
let arc_fun: std::sync::Arc<dyn NyashBox> = std::sync::Arc::from(Box::new(fun) as Box<dyn NyashBox>);
vm.set_value(func_id, VMValue::BoxRef(arc_fun));
let out = vm.execute_module(&m).expect("vm exec");
assert_eq!(out.to_string_box().value, "42");
}