Phase 12.7文法改革: ドキュメント文法統一 + VMリファクタリング準備

🌟 Phase 12.7文法改革に基づくドキュメント更新
- init {} → field: TypeBox 個別フィールド宣言形式
- init() → birth() コンストラクタ統一
- pack() → 廃止(birth()に統一)
- public {}/private {} → 個別フィールド修飾子
- override → 廃止(メソッド定義はシンプルに)

📚 更新したドキュメント
- CLAUDE.md: メイン開発ガイド
- docs/quick-reference/syntax-cheatsheet.md: 構文早見表
- docs/reference/language/LANGUAGE_REFERENCE_2025.md: 言語リファレンス
- docs/development/roadmap/phases/phase-15/README.md: Phase 15計画

🔧 VMリファクタリング準備
- vm_methods.rs: VMメソッド呼び出しの分離
- plugin_loader.rs → plugin_loader/: ディレクトリ構造化
- mir/builder/exprs.rs: 式ビルダー分離

📝 新規ドキュメント追加
- 論文戦略・ロードマップ
- Phase 15セルフホスティング準備資料
- Codex Androidセットアップガイド

ビルドは正常に通ることを確認済み!🎉

🤖 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 06:27:39 +09:00
parent 6488b0542e
commit 4e824fa00e
27 changed files with 2804 additions and 1656 deletions

View File

@ -244,67 +244,7 @@ pub struct VM {
impl VM {
pub fn runtime_ref(&self) -> &NyashRuntime { &self.runtime }
/// Print a simple breakdown of root VMValue kinds and top BoxRef types (old-moved placeholder)
pub(super) fn gc_print_roots_breakdown_old(&self) {
use std::collections::HashMap;
let roots = self.scope_tracker.roots_snapshot();
let mut kinds: HashMap<&'static str, u64> = HashMap::new();
let mut box_types: HashMap<String, u64> = HashMap::new();
for v in &roots {
match v {
VMValue::Integer(_) => *kinds.entry("Integer").or_insert(0) += 1,
VMValue::Float(_) => *kinds.entry("Float").or_insert(0) += 1,
VMValue::Bool(_) => *kinds.entry("Bool").or_insert(0) += 1,
VMValue::String(_) => *kinds.entry("String").or_insert(0) += 1,
VMValue::Future(_) => *kinds.entry("Future").or_insert(0) += 1,
VMValue::Void => *kinds.entry("Void").or_insert(0) += 1,
VMValue::BoxRef(b) => {
let tn = b.type_name().to_string();
*box_types.entry(tn).or_insert(0) += 1;
}
}
}
eprintln!("[GC] roots_breakdown: kinds={:?}", kinds);
let mut top: Vec<(String, u64)> = box_types.into_iter().collect();
top.sort_by(|a, b| b.1.cmp(&a.1));
top.truncate(5);
eprintln!("[GC] roots_boxref_top5: {:?}", top);
}
pub(super) fn gc_print_reachability_depth2_old(&self) {
use std::collections::HashMap;
let roots = self.scope_tracker.roots_snapshot();
let mut child_types: HashMap<String, u64> = HashMap::new();
let mut child_count = 0u64;
for v in &roots {
if let VMValue::BoxRef(b) = v {
if let Some(arr) = b.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
if let Ok(items) = arr.items.read() {
for item in items.iter() {
let tn = item.type_name().to_string();
*child_types.entry(tn).or_insert(0) += 1;
child_count += 1;
}
}
}
if let Some(map) = b.as_any().downcast_ref::<crate::boxes::map_box::MapBox>() {
let vals = map.values();
if let Some(arr2) = vals.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
if let Ok(items) = arr2.items.read() {
for item in items.iter() {
let tn = item.type_name().to_string();
*child_types.entry(tn).or_insert(0) += 1;
child_count += 1;
}
}
}
}
}
}
let mut top: Vec<(String, u64)> = child_types.into_iter().collect();
top.sort_by(|a, b| b.1.cmp(&a.1));
top.truncate(5);
eprintln!("[GC] depth2_children: total={} top5={:?}", child_count, top);
}
// TODO: Re-enable when interpreter refactoring is complete
@ -330,232 +270,11 @@ impl VM {
}
*/
/// Execute a MIR module (old placeholder; moved to vm_exec.rs)
pub fn execute_module_old_moved(&mut self, _module: &MirModule) -> Result<Box<dyn NyashBox>, VMError> {
Ok(Box::new(VoidBox::new()))
}
fn print_cache_stats_summary_old(&self) {
let sites_poly = self.boxcall_poly_pic.len();
let entries_poly: usize = self.boxcall_poly_pic.values().map(|v| v.len()).sum();
let avg_entries = if sites_poly > 0 { (entries_poly as f64) / (sites_poly as f64) } else { 0.0 };
let sites_mono = self.boxcall_pic_funcname.len();
let hits_total: u64 = self.boxcall_pic_hits.values().map(|v| *v as u64).sum();
let vt_entries = self.boxcall_vtable_funcname.len();
eprintln!(
"[VM] PIC/VT summary: poly_sites={} avg_entries={:.2} mono_sites={} hits_total={} vt_entries={} | hits: vt={} poly={} mono={} generic={}",
sites_poly, avg_entries, sites_mono, hits_total, vt_entries,
self.boxcall_hits_vtable, self.boxcall_hits_poly_pic, self.boxcall_hits_mono_pic, self.boxcall_hits_generic
);
// Top sites by hits (up to 5)
let mut hits: Vec<(&String, &u32)> = self.boxcall_pic_hits.iter().collect();
hits.sort_by(|a, b| b.1.cmp(a.1));
for (i, (k, v)) in hits.into_iter().take(5).enumerate() {
eprintln!(" #{} {} hits={}", i+1, k, v);
}
}
/// Call a MIR function by name with VMValue arguments
pub(super) fn call_function_by_name_old(&mut self, func_name: &str, args: Vec<VMValue>) -> Result<VMValue, VMError> {
// Root region: ensure args stay rooted during nested call
self.enter_root_region();
self.pin_roots(args.iter());
let module_ref = self.module.as_ref().ok_or_else(|| VMError::InvalidInstruction("No active module".to_string()))?;
let function_ref = module_ref.get_function(func_name)
.ok_or_else(|| VMError::InvalidInstruction(format!("Function '{}' not found", func_name)))?;
// Clone function to avoid borrowing conflicts during execution
let function = function_ref.clone();
// Save current frame
let saved_values = std::mem::take(&mut self.values);
let saved_current_function = self.current_function.clone();
let saved_current_block = self.frame.current_block;
let saved_previous_block = self.previous_block;
let saved_pc = self.frame.pc;
let saved_last_result = self.frame.last_result;
// Bind parameters
for (i, param_id) in function.params.iter().enumerate() {
if let Some(arg) = args.get(i) {
self.set_value(*param_id, arg.clone());
}
}
// Heuristic: map `me` (first param) to class name parsed from function name (e.g., User.method/N)
if let Some(first) = function.params.get(0) {
if let Some((class_part, _rest)) = func_name.split_once('.') {
// Record class for internal field visibility checks
self.object_class.insert(*first, class_part.to_string());
// Mark internal reference
self.object_internal.insert(*first);
}
}
// Execute the function
let result = self.execute_function(&function);
// Restore frame
self.values = saved_values;
self.current_function = saved_current_function;
self.frame.current_block = saved_current_block;
self.previous_block = saved_previous_block;
self.frame.pc = saved_pc;
self.frame.last_result = saved_last_result;
// Leave GC root region
self.scope_tracker.leave_root_region();
result
}
/// Execute a single function
fn execute_function_old(&mut self, function: &MirFunction) -> Result<VMValue, VMError> {
self.current_function = Some(function.signature.name.clone());
// Phase 10_a: JIT profiling (function entry)
if let Some(jm) = &mut self.jit_manager {
// Allow threshold to react to env updates (e.g., DebugConfigBox.apply at runtime)
if let Ok(s) = std::env::var("NYASH_JIT_THRESHOLD") {
if let Ok(t) = s.parse::<u32>() { if t > 0 { jm.set_threshold(t); } }
}
jm.record_entry(&function.signature.name);
// Try compile if hot (no-op for now, returns fake handle)
let _ = jm.maybe_compile(&function.signature.name, function);
// Record per-function lower stats captured during last JIT lower (if any)
// Note: The current engine encapsulates its LowerCore; expose via last_stats on a new instance as needed.
if jm.is_compiled(&function.signature.name) && std::env::var("NYASH_JIT_STATS").ok().as_deref() == Some("1") {
if let Some(h) = jm.handle_of(&function.signature.name) {
eprintln!("[JIT] dispatch would go to handle={} for {} (stub)", h, function.signature.name);
}
}
}
// Initialize loop executor for this function
self.loop_executor.initialize();
// Enter a new scope for this function
self.scope_tracker.push_scope();
crate::runtime::global_hooks::push_task_scope();
// Phase 10_c: try a JIT dispatch when enabled; fallback to VM on trap/miss
// Prepare arguments from current frame params before borrowing jit_manager mutably
let args_vec: Vec<VMValue> = function
.params
.iter()
.filter_map(|pid| self.get_value(*pid).ok())
.collect();
if std::env::var("NYASH_JIT_EXEC").ok().as_deref() == Some("1") {
let jit_only = std::env::var("NYASH_JIT_ONLY").ok().as_deref() == Some("1");
// Root regionize args for JIT call
self.enter_root_region();
self.pin_roots(args_vec.iter());
if let Some(compiled) = self.jit_manager.as_ref().map(|jm| jm.is_compiled(&function.signature.name)) {
if compiled {
crate::runtime::host_api::set_current_vm(self as *mut _);
let jit_val = if let Some(jm_mut) = self.jit_manager.as_mut() { jm_mut.execute_compiled(&function.signature.name, &function.signature.return_type, &args_vec) } else { None };
crate::runtime::host_api::clear_current_vm();
if let Some(val) = jit_val {
// Exit scope before returning
self.leave_root_region();
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Ok(val);
} else if std::env::var("NYASH_JIT_STATS").ok().as_deref() == Some("1") ||
std::env::var("NYASH_JIT_TRAP_LOG").ok().as_deref() == Some("1") {
eprintln!("[JIT] fallback: VM path taken for {}", function.signature.name);
if jit_only {
self.leave_root_region();
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Err(VMError::InvalidInstruction(format!("JIT-only enabled and JIT trap occurred for {}", function.signature.name)));
}
}
} else if jit_only {
// Try to compile now and execute; if not possible, error out
if let Some(jm_mut) = self.jit_manager.as_mut() { let _ = jm_mut.maybe_compile(&function.signature.name, function); }
if self.jit_manager.as_ref().map(|jm| jm.is_compiled(&function.signature.name)).unwrap_or(false) {
crate::runtime::host_api::set_current_vm(self as *mut _);
let jit_val = if let Some(jm_mut) = self.jit_manager.as_mut() { jm_mut.execute_compiled(&function.signature.name, &function.signature.return_type, &args_vec) } else { None };
crate::runtime::host_api::clear_current_vm();
if let Some(val) = jit_val {
self.leave_root_region();
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Ok(val);
} else {
self.leave_root_region();
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Err(VMError::InvalidInstruction(format!("JIT-only enabled and JIT execution failed for {}", function.signature.name)));
}
} else {
self.leave_root_region();
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Err(VMError::InvalidInstruction(format!("JIT-only enabled but function not compiled: {}", function.signature.name)));
}
}
}
// Leave root region if not compiled or after fallback
self.leave_root_region();
} else {
if let Some(jm_mut) = &mut self.jit_manager {
let argc = function.params.len();
let _would = jm_mut.maybe_dispatch(&function.signature.name, argc);
}
}
// Start at entry block
let mut current_block = function.entry_block;
loop {
let block = function.get_block(current_block)
.ok_or_else(|| VMError::InvalidBasicBlock(format!("Block {} not found", current_block)))?;
self.frame.current_block = Some(current_block);
self.frame.pc = 0;
let mut next_block = None;
let mut should_return = None;
// Execute instructions in this block (including terminator)
let all_instructions: Vec<_> = block.all_instructions().collect();
for (index, instruction) in all_instructions.iter().enumerate() {
self.frame.pc = index;
match self.execute_instruction(instruction)? {
ControlFlow::Continue => continue,
ControlFlow::Jump(target) => {
next_block = Some(target);
break;
},
ControlFlow::Return(value) => {
should_return = Some(value);
break;
},
}
}
// Handle control flow
if let Some(return_value) = should_return {
// Exit scope before returning
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Ok(return_value);
} else if let Some(target) = next_block {
// Update previous block before jumping and record transition via control_flow helper
control_flow::record_transition(&mut self.previous_block, &mut self.loop_executor, current_block, target).ok();
current_block = target;
} else {
// Block ended without terminator - this shouldn't happen in well-formed MIR
// but let's handle it gracefully by returning void
// Exit scope before returning
self.scope_tracker.pop_scope();
crate::runtime::global_hooks::pop_task_scope();
return Ok(VMValue::Void);
}
}
}
/// Execute a single instruction (old placeholder; moved to vm_exec.rs)
fn execute_instruction_old(&mut self, _instruction: &MirInstruction) -> Result<ControlFlow, VMError> { unreachable!("moved") }
@ -565,49 +284,11 @@ impl VM {
/// Phase 9.78a: Unified method dispatch for all Box types
fn call_unified_method(&self, box_value: Box<dyn NyashBox>, method: &str, args: Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, VMError> {
// For now, we use the simplified method dispatch
// In a full implementation, this would check for InstanceBox and dispatch appropriately
self.call_box_method_impl(box_value, method, args)
}
/// Call a method on a Box - simplified version of interpreter method dispatch
pub(super) fn call_box_method(&self, box_value: Box<dyn NyashBox>, method: &str, mut _args: Vec<Box<dyn NyashBox>>) -> Result<Box<dyn NyashBox>, VMError> {
// For now, implement basic methods for common box types
// This is a simplified version - real implementation would need full method dispatch
// 🌟 Universal methods pre-dispatch (non-invasive)
match method {
"toString" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: toString() expects 0 arguments, got {}", _args.len()))));
}
return Ok(Box::new(StringBox::new(box_value.to_string_box().value)));
}
"type" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: type() expects 0 arguments, got {}", _args.len()))));
}
return Ok(Box::new(StringBox::new(box_value.type_name())));
}
"equals" => {
if _args.len() != 1 {
return Ok(Box::new(StringBox::new(format!("Error: equals() expects 1 argument, got {}", _args.len()))));
}
let rhs = _args.remove(0);
let eq = box_value.equals(&*rhs);
return Ok(Box::new(eq));
}
"clone" => {
if !_args.is_empty() {
return Ok(Box::new(StringBox::new(format!("Error: clone() expects 0 arguments, got {}", _args.len()))));
}
return Ok(box_value.clone_box());
}
_ => {}
}
// Call a method on a Box - moved to vm_methods.rs (wrapper now in vm_methods)
// removed: old inline implementation
/*
// ResultBox (NyashResultBox - new)
if let Some(result_box) = box_value.as_any().downcast_ref::<crate::boxes::result::NyashResultBox>() {
match method {
@ -1004,10 +685,7 @@ impl VM {
}
return Ok(Box::new(VoidBox::new()));
}
// Default: return void for any unrecognized box type or method
Ok(Box::new(VoidBox::new()))
}
*/
}
/// RAII guard for GC root regions
@ -1024,7 +702,7 @@ impl Default for VM {
#[cfg(test)]
mod tests {
use super::*;
use crate::mir::{MirModule, MirFunction, FunctionSignature, MirType, EffectMask, BasicBlock};
use crate::mir::{MirModule, MirFunction, FunctionSignature, MirType, EffectMask, BasicBlock, BinaryOp};
use crate::parser::NyashParser;
use crate::runtime::NyashRuntime;
use crate::core::model::BoxDeclaration as CoreBoxDecl;