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:
65
src/tests/functionbox_call_tests.rs
Normal file
65
src/tests/functionbox_call_tests.rs
Normal 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);
|
||||
}
|
||||
|
||||
25
src/tests/mir_lambda_functionbox.rs
Normal file
25
src/tests/mir_lambda_functionbox.rs
Normal 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); }
|
||||
}
|
||||
|
||||
49
src/tests/vm_functionbox_call.rs
Normal file
49
src/tests/vm_functionbox_call.rs
Normal 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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user