Phase 21.2 Complete: VM Adapter正規実装 + devブリッジ完全撤去

## 🎉 Phase 21.2完全達成

###  実装完了
- VM static box 永続化(singleton infrastructure)
- devブリッジ完全撤去(adapter_dev.rs削除、by-name dispatch削除)
- .hako正規実装(MirCallV1Handler, AbiAdapterRegistry等)
- text-merge経路完全動作
- 全phase2120 adapter reps PASS(7テスト)

### 🐛 バグ修正
1. strip_local_decl修正
   - トップレベルのみlocal削除、メソッド内は保持
   - src/runner/modes/common_util/hako.rs:29

2. static box フィールド永続化
   - MirInterpreter singleton storage実装
   - me parameter binding修正(1:1マッピング)
   - getField/setField string→singleton解決
   - src/backend/mir_interpreter/{mod,exec,handlers/boxes_object_fields}.rs

3. Map.len alias rc=0修正
   - [map/missing]パターン検出でnull扱い(4箇所)
   - lang/src/vm/boxes/mir_call_v1_handler.hako:91-93,131-133,151-153,199-201

### 📁 主要変更ファイル

#### Rust(VM Runtime)
- src/backend/mir_interpreter/mod.rs - static box singleton storage
- src/backend/mir_interpreter/exec.rs - parameter binding fix
- src/backend/mir_interpreter/handlers/boxes_object_fields.rs - singleton resolution
- src/backend/mir_interpreter/handlers/calls.rs - dev bridge removal
- src/backend/mir_interpreter/utils/mod.rs - adapter_dev module removal
- src/backend/mir_interpreter/utils/adapter_dev.rs - DELETED (7555 bytes)
- src/runner/modes/vm.rs - static box declaration collection
- src/runner/modes/common_util/hako.rs - strip_local_decl fix
- src/instance_v2.rs - Clone implementation

#### Hako (.hako実装)
- lang/src/vm/boxes/mir_call_v1_handler.hako - [map/missing] detection
- lang/src/vm/boxes/abi_adapter_registry.hako - NEW (adapter registry)
- lang/src/vm/helpers/method_alias_policy.hako - method alias support

#### テスト
- tools/smokes/v2/profiles/quick/core/phase2120/s3_vm_adapter_*.sh - 7 new tests

### 🎯 テスト結果
```
 s3_vm_adapter_array_len_canary_vm.sh
 s3_vm_adapter_array_len_per_recv_canary_vm.sh
 s3_vm_adapter_array_length_alias_canary_vm.sh
 s3_vm_adapter_array_size_alias_canary_vm.sh
 s3_vm_adapter_map_len_alias_state_canary_vm.sh
 s3_vm_adapter_map_length_alias_state_canary_vm.sh
 s3_vm_adapter_map_size_struct_canary_vm.sh
```

環境フラグ: HAKO_ABI_ADAPTER=1 HAKO_ABI_ADAPTER_DEV=0

### 🏆 設計品質
-  ハードコード禁止(AGENTS.md 5.1)完全準拠
-  構造的・一般化設計(特定Box名のif分岐なし)
-  後方互換性保持(既存コード破壊ゼロ)
-  text-merge経路(.hako依存関係正しくマージ)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-07 19:32:44 +09:00
parent 8d1e580ab4
commit 301b1d212a
62 changed files with 3867 additions and 462 deletions

View File

@ -54,32 +54,67 @@ impl NyashParser {
})
}
/// Parse using statement: using namespace_name
/// Parse using statement
/// Accepts forms:
/// - using "module.path" (as Alias)?
/// - using module.path (as Alias)?
/// Alias (if present) is currently ignored by the core parser and handled by runner-side resolution.
pub(super) fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
self.advance(); // consume 'using'
// Get namespace name
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
let name = namespace_name.clone();
self.advance();
// Phase 0 only allows "nyashstd"
if name != "nyashstd" {
return Err(ParseError::UnsupportedNamespace {
name,
line: self.current_token().line,
});
// Parse target: string literal or dotted identifiers
let namespace = match &self.current_token().token_type {
TokenType::STRING(s) => {
let v = s.clone();
self.advance();
v
}
TokenType::IDENTIFIER(first) => {
let mut parts = vec![first.clone()];
self.advance();
while let TokenType::DOT = self.current_token().token_type {
// consume '.' and the following IDENTIFIER
self.advance();
if let TokenType::IDENTIFIER(seg) = &self.current_token().token_type {
parts.push(seg.clone());
self.advance();
} else {
return Err(ParseError::UnexpectedToken {
found: self.current_token().token_type.clone(),
expected: "identifier after '.'".to_string(),
line: self.current_token().line,
});
}
}
parts.join(".")
}
other => {
return Err(ParseError::UnexpectedToken {
found: other.clone(),
expected: "string or identifier".to_string(),
line: self.current_token().line,
})
}
};
Ok(ASTNode::UsingStatement {
namespace_name: name,
span: Span::unknown(),
})
} else {
Err(ParseError::ExpectedIdentifier {
line: self.current_token().line,
})
// Optional: 'as' Alias — runner handles alias; parser skips if present
if let TokenType::IDENTIFIER(w) = &self.current_token().token_type {
if w == "as" {
self.advance();
// consume alias identifier (single segment)
if let TokenType::IDENTIFIER(_alias) = &self.current_token().token_type {
self.advance();
} else {
return Err(ParseError::UnexpectedToken {
found: self.current_token().token_type.clone(),
expected: "alias name".to_string(),
line: self.current_token().line,
});
}
}
}
Ok(ASTNode::UsingStatement { namespace_name: namespace, span: Span::unknown() })
}
/// Parse from statement: from Parent.method(args)
@ -92,4 +127,4 @@ impl NyashParser {
// Example: from Animal.constructor() (return value unused)
Ok(from_call_expr)
}
}
}