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

@ -301,28 +301,27 @@ impl MirBuilder {
self.build_function_call(name.clone(), arguments.clone())
},
ASTNode::Call { callee, arguments, .. } => {
// 最小P1: callee が Lambda の場合のみ対応
// P1.5: Lambdaはインライン、それ以外は Call に正規化
if let ASTNode::Lambda { params, body, .. } = callee.as_ref() {
if params.len() != arguments.len() {
return Err(format!("Lambda expects {} args, got {}", params.len(), arguments.len()));
}
// 引数を評価
let mut arg_vals: Vec<ValueId> = Vec::new();
for a in arguments { arg_vals.push(self.build_expression(a)?); }
// スコープ保存
let saved_vars = self.variable_map.clone();
// パラメータ束縛
for (p, v) in params.iter().zip(arg_vals.iter()) {
self.variable_map.insert(p.clone(), *v);
}
// 本体を Program として Lower
for (p, v) in params.iter().zip(arg_vals.iter()) { self.variable_map.insert(p.clone(), *v); }
let prog = ASTNode::Program { statements: body.clone(), span: crate::ast::Span::unknown() };
let out = self.build_expression(prog)?;
// 復元
self.variable_map = saved_vars;
Ok(out)
} else {
Err("Callee is not callable (lambda required)".to_string())
// callee/args を評価し、Call を発行VM 側で FunctionBox/関数名の両対応)
let callee_id = self.build_expression(*callee.clone())?;
let mut arg_ids = Vec::new();
for a in arguments { arg_ids.push(self.build_expression(a)?); }
let dst = self.value_gen.next();
self.emit_instruction(MirInstruction::Call { dst: Some(dst), func: callee_id, args: arg_ids, effects: EffectMask::PURE })?;
Ok(dst)
}
},
@ -440,11 +439,68 @@ impl MirBuilder {
},
ASTNode::Lambda { params, body, .. } => {
// Minimal P1: represent as constant string for now
// Lambda→FunctionBox 値 Lower最小 + 簡易キャプチャ解析)
let dst = self.value_gen.next();
let s = format!("Lambda(params={}, body={})", params.len(), body.len());
self.emit_instruction(MirInstruction::Const { dst, value: ConstValue::String(s) })?;
self.value_types.insert(dst, super::MirType::String);
// Collect free variable names: variables used in body but not in params, and not 'me'/'this'
use std::collections::HashSet;
let mut used: HashSet<String> = HashSet::new();
let mut locals: HashSet<String> = HashSet::new();
for p in params.iter() { locals.insert(p.clone()); }
fn collect_vars(node: &crate::ast::ASTNode, used: &mut HashSet<String>, locals: &mut HashSet<String>) {
match node {
crate::ast::ASTNode::Variable { name, .. } => {
if name != "me" && name != "this" && !locals.contains(name) {
used.insert(name.clone());
}
}
crate::ast::ASTNode::Local { variables, .. } => { for v in variables { locals.insert(v.clone()); } }
crate::ast::ASTNode::Assignment { target, value, .. } => { collect_vars(target, used, locals); collect_vars(value, used, locals); }
crate::ast::ASTNode::BinaryOp { left, right, .. } => { collect_vars(left, used, locals); collect_vars(right, used, locals); }
crate::ast::ASTNode::UnaryOp { operand, .. } => { collect_vars(operand, used, locals); }
crate::ast::ASTNode::MethodCall { object, arguments, .. } => { collect_vars(object, used, locals); for a in arguments { collect_vars(a, used, locals); } }
crate::ast::ASTNode::FunctionCall { arguments, .. } => { for a in arguments { collect_vars(a, used, locals); } }
crate::ast::ASTNode::Call { callee, arguments, .. } => { collect_vars(callee, used, locals); for a in arguments { collect_vars(a, used, locals); } }
crate::ast::ASTNode::FieldAccess { object, .. } => { collect_vars(object, used, locals); }
crate::ast::ASTNode::New { arguments, .. } => { for a in arguments { collect_vars(a, used, locals); } }
crate::ast::ASTNode::If { condition, then_body, else_body, .. } => {
collect_vars(condition, used, locals);
for st in then_body { collect_vars(st, used, locals); }
if let Some(eb) = else_body { for st in eb { collect_vars(st, used, locals); } }
}
crate::ast::ASTNode::Loop { condition, body, .. } => { collect_vars(condition, used, locals); for st in body { collect_vars(st, used, locals); } }
crate::ast::ASTNode::TryCatch { try_body, catch_clauses, finally_body, .. } => {
for st in try_body { collect_vars(st, used, locals); }
for c in catch_clauses { for st in &c.body { collect_vars(st, used, locals); } }
if let Some(fb) = finally_body { for st in fb { collect_vars(st, used, locals); } }
}
crate::ast::ASTNode::Throw { expression, .. } => { collect_vars(expression, used, locals); }
crate::ast::ASTNode::Print { expression, .. } => { collect_vars(expression, used, locals); }
crate::ast::ASTNode::Return { value, .. } => { if let Some(v) = value { collect_vars(v, used, locals); } }
crate::ast::ASTNode::AwaitExpression { expression, .. } => { collect_vars(expression, used, locals); }
crate::ast::ASTNode::PeekExpr { scrutinee, arms, else_expr, .. } => {
collect_vars(scrutinee, used, locals);
for (_, e) in arms { collect_vars(e, used, locals); }
collect_vars(else_expr, used, locals);
}
crate::ast::ASTNode::Program { statements, .. } => { for st in statements { collect_vars(st, used, locals); } }
crate::ast::ASTNode::FunctionDeclaration { params, body, .. } => {
let mut inner = locals.clone();
for p in params { inner.insert(p.clone()); }
for st in body { collect_vars(st, used, &mut inner); }
}
_ => {}
}
}
for st in body.iter() { collect_vars(st, &mut used, &mut locals); }
// Materialize captures from current variable_map if known
let mut captures: Vec<(String, ValueId)> = Vec::new();
for name in used.into_iter() {
if let Some(&vid) = self.variable_map.get(&name) { captures.push((name, vid)); }
}
// me capture存在すれば
let me = self.variable_map.get("me").copied();
self.emit_instruction(MirInstruction::FunctionNew { dst, params: params.clone(), body: body.clone(), captures, me })?;
self.value_types.insert(dst, super::MirType::Box("FunctionBox".to_string()));
Ok(dst)
},

View File

@ -71,6 +71,19 @@ pub enum MirInstruction {
args: Vec<ValueId>,
effects: EffectMask,
},
/// Create a function value (FunctionBox) from params/body and optional captures
/// `%dst = function_new [params] {body} [captures...]`
/// Minimal lowering support: captures may be empty; 'me' is optional.
FunctionNew {
dst: ValueId,
params: Vec<String>,
body: Vec<crate::ast::ASTNode>,
/// Pairs of (name, value) to capture by value
captures: Vec<(String, ValueId)>,
/// Optional 'me' value to capture weakly if it is a BoxRef at runtime
me: Option<ValueId>,
},
/// Box method invocation
/// `%dst = invoke %box.method(%args...)`
@ -454,6 +467,8 @@ impl MirInstruction {
// Phase 9.7: External Function Calls
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
// Function value construction: treat as pure with allocation
MirInstruction::FunctionNew { .. } => EffectMask::PURE.add(Effect::Alloc),
}
}
@ -479,6 +494,7 @@ impl MirInstruction {
MirInstruction::WeakRef { dst, .. } |
MirInstruction::FutureNew { dst, .. } |
MirInstruction::Await { dst, .. } => Some(*dst),
MirInstruction::FunctionNew { dst, .. } => Some(*dst),
MirInstruction::Call { dst, .. } |
MirInstruction::BoxCall { dst, .. } |
@ -540,6 +556,12 @@ impl MirInstruction {
used.extend(args);
used
},
MirInstruction::FunctionNew { captures, me, .. } => {
let mut used: Vec<ValueId> = Vec::new();
used.extend(captures.iter().map(|(_, v)| *v));
if let Some(m) = me { used.push(*m); }
used
}
MirInstruction::BoxCall { box_val, args, .. } | MirInstruction::PluginInvoke { box_val, args, .. } => {
let mut used = vec![*box_val];

View File

@ -311,6 +311,13 @@ impl MirPrinter {
format!("call {}({})", func, args_str)
}
},
MirInstruction::FunctionNew { dst, params, body, captures, me } => {
let p = params.join(", ");
let c = captures.iter().map(|(n, v)| format!("{}={}", n, v)).collect::<Vec<_>>().join(", ");
let me_s = me.map(|m| format!(" me={}", m)).unwrap_or_default();
let cap_s = if c.is_empty() { String::new() } else { format!(" [{}]", c) };
format!("{} = function_new ({}) {{...{}}}{}{}", dst, p, body.len(), cap_s, me_s)
},
MirInstruction::BoxCall { dst, box_val, method, method_id, args, effects: _ } => {
let args_str = args.iter()