# BID×usingシステム統合:技術実装詳細 ## 🎯 統合設計の核心 ### 📊 既存システムとの整合性 - ✅ **MIR ExternCall**: 既にFFI-ABI対応実装済み - ✅ **WASM RuntimeImports**: BID→WASM自動生成基盤あり - ✅ **VM ExternStub**: スタブ実行環境実装済み - 🔧 **統合課題**: usingシステムとBIDの橋渡し実装 ### 🚀 統合アーキテクチャ概要 ``` User Code (using statements) ↓ UniversalNamespaceRegistry ↓ CallTarget Resolution ↓ ↓ ↓ Builtin FFI-ABI NyashModule ↓ ↓ ↓ MIR Generation (BuiltinCall/ExternCall/ModuleCall) ↓ Backend Execution (VM/WASM/AOT) ``` ## 🏗️ 詳細技術実装 ### 1. BID定義システム #### **BIDファイル構造拡張** ```yaml # apis/enhanced_canvas.yaml version: 1 metadata: name: "Enhanced Canvas API" description: "Extended Canvas API with batch operations" target_environments: ["browser", "node-canvas", "skia"] nyash_namespace: "canvas_api" # usingで使用する名前空間 interfaces: - name: canvas_api.canvas box: Canvas methods: # 基本描画 - name: fillRect params: - {string: canvas_id, description: "Canvas element ID"} - {i32: x, description: "X coordinate"} - {i32: y, description: "Y coordinate"} - {i32: width, description: "Rectangle width"} - {i32: height, description: "Rectangle height"} - {string: color, description: "Fill color (CSS format)"} returns: void effect: io optimization_hints: batch_compatible: true # バッチ処理可能 gpu_accelerated: true # GPU加速対応 # バッチ描画(最適化版) - name: fillRectBatch params: - {string: canvas_id} - {array_of_rect: rects, element_type: "CanvasRect"} returns: void effect: io optimization_hints: prefer_over: ["fillRect"] # 複数fillRectの代替 min_batch_size: 3 # テキスト描画 - name: fillText params: - {string: canvas_id} - {string: text} - {i32: x} - {i32: y} - {string: font} - {string: color} returns: void effect: io # カスタム型定義 custom_types: - name: CanvasRect fields: - {i32: x} - {i32: y} - {i32: width} - {i32: height} - {string: color} ``` #### **BID読み込み・検証システム** ```rust // 新ファイル: src/bid/mod.rs use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BidDefinition { pub version: u32, pub metadata: BidMetadata, pub interfaces: Vec, pub custom_types: Option>, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BidMetadata { pub name: String, pub description: String, pub target_environments: Vec, pub nyash_namespace: String, // using文で使用する名前空間名 } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BidInterface { pub name: String, // "canvas_api.canvas" pub box_name: String, // "Canvas" pub methods: Vec, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BidMethod { pub name: String, pub params: Vec, pub returns: BidType, pub effect: BidEffect, pub optimization_hints: Option, pub description: Option, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BidOptimizationHints { pub batch_compatible: Option, pub gpu_accelerated: Option, pub prefer_over: Option>, pub min_batch_size: Option, } impl BidDefinition { pub fn load_from_file(path: &Path) -> Result { let content = std::fs::read_to_string(path)?; let bid: BidDefinition = serde_yaml::from_str(&content)?; // バリデーション bid.validate()?; Ok(bid) } pub fn validate(&self) -> Result<(), BidError> { // バージョン確認 if self.version > 1 { return Err(BidError::UnsupportedVersion(self.version)); } // 名前空間重複チェック let mut interface_names = HashSet::new(); for interface in &self.interfaces { if interface_names.contains(&interface.name) { return Err(BidError::DuplicateInterface(interface.name.clone())); } interface_names.insert(interface.name.clone()); } // パラメータ型確認 for interface in &self.interfaces { for method in &interface.methods { for param in &method.params { self.validate_type(¶m.param_type)?; } self.validate_type(&method.returns)?; } } Ok(()) } pub fn resolve_method(&self, box_name: &str, method_name: &str) -> Option<&BidMethod> { for interface in &self.interfaces { // インターフェース名から最後の部分を取得 // "canvas_api.canvas" → "canvas" let interface_box_name = interface.name.split('.').last().unwrap_or(&interface.name); if interface_box_name == box_name { for method in &interface.methods { if method.name == method_name { return Some(method); } } } } None } } ``` ### 2. 統合名前空間レジストリ詳細 #### **UniversalNamespaceRegistry実装** ```rust // src/registry/universal.rs use crate::stdlib::BuiltinStdlib; use crate::bid::BidDefinition; use crate::module::ExternalModule; use crate::mir::Effect; pub struct UniversalNamespaceRegistry { /// 組み込み標準ライブラリ builtin_stdlib: Arc, /// FFI-ABI定義(BID) bid_definitions: HashMap>, /// Nyashモジュール(従来) nyash_modules: HashMap>, /// ファイル別usingコンテキスト using_contexts: Arc>>, /// 最適化情報キャッシュ optimization_cache: Arc>, } #[derive(Debug, Clone)] pub struct UsingContext { pub file_id: String, pub builtin_namespaces: Vec, // ["nyashstd"] pub bid_namespaces: Vec, // ["canvas_api", "console_api"] pub module_namespaces: Vec, // ["mylib", "utils"] } impl UniversalNamespaceRegistry { pub fn new() -> Self { UniversalNamespaceRegistry { builtin_stdlib: Arc::new(BuiltinStdlib::new()), bid_definitions: HashMap::new(), nyash_modules: HashMap::new(), using_contexts: Arc::new(RwLock::new(HashMap::new())), optimization_cache: Arc::new(RwLock::new(OptimizationCache::new())), } } pub fn load_from_nyash_link(&mut self, nyash_link: &NyashLink) -> Result<(), RegistryError> { // BID依存関係読み込み for (namespace_name, dependency) in &nyash_link.dependencies { match dependency { Dependency::Bid { bid_path, .. } => { let bid = BidDefinition::load_from_file(Path::new(bid_path))?; self.bid_definitions.insert(namespace_name.clone(), Arc::new(bid)); }, Dependency::Path { path } => { let module = ExternalModule::load_from_file(Path::new(path))?; self.hako_modules.insert(namespace_name.clone(), Arc::new(module)); }, Dependency::Builtin { .. } => { // 組み込みライブラリは既に初期化済み }, } } Ok(()) } /// 統合using処理 pub fn process_using(&mut self, namespace_name: &str, file_id: &str) -> Result<(), RuntimeError> { let mut contexts = self.using_contexts.write().unwrap(); let context = contexts.entry(file_id.to_string()).or_insert_with(|| { UsingContext { file_id: file_id.to_string(), builtin_namespaces: Vec::new(), bid_namespaces: Vec::new(), module_namespaces: Vec::new(), } }); // 組み込み標準ライブラリチェック if self.builtin_stdlib.has_namespace(namespace_name) { if !context.builtin_namespaces.contains(&namespace_name.to_string()) { context.builtin_namespaces.push(namespace_name.to_string()); } return Ok(()); } // BID定義チェック if let Some(bid) = self.bid_definitions.get(namespace_name) { if !context.bid_namespaces.contains(&namespace_name.to_string()) { context.bid_namespaces.push(namespace_name.to_string()); } return Ok(()); } // Nyashモジュールチェック if let Some(_module) = self.hako_modules.get(namespace_name) { if !context.module_namespaces.contains(&namespace_name.to_string()) { context.module_namespaces.push(namespace_name.to_string()); } return Ok(()); } Err(RuntimeError::UndefinedNamespace(namespace_name.to_string())) } /// 統合関数解決 pub fn resolve_call(&self, file_id: &str, call_path: &[String]) -> Result { if call_path.len() != 2 { return Err(RuntimeError::InvalidCallPath(call_path.join("."))); } let box_name = &call_path[0]; let method_name = &call_path[1]; let contexts = self.using_contexts.read().unwrap(); if let Some(context) = contexts.get(file_id) { // 1. 組み込み標準ライブラリ解決 for namespace in &context.builtin_namespaces { if let Some(method) = self.builtin_stdlib.resolve_method(namespace, box_name, method_name) { return Ok(ResolvedCall::Builtin { namespace: namespace.clone(), box_name: box_name.clone(), method_name: method_name.clone(), method_info: method, }); } } // 2. BID定義解決 for namespace in &context.bid_namespaces { if let Some(bid) = self.bid_definitions.get(namespace) { if let Some(method) = bid.resolve_method(box_name, method_name) { return Ok(ResolvedCall::BidCall { namespace: namespace.clone(), interface_name: format!("{}.{}", namespace, box_name), method_name: method_name.clone(), method_info: method.clone(), bid_definition: bid.clone(), }); } } } // 3. Nyashモジュール解決 for namespace in &context.module_namespaces { if let Some(module) = self.hako_modules.get(namespace) { if let Some(function) = module.resolve_function(box_name, method_name) { return Ok(ResolvedCall::ModuleCall { namespace: namespace.clone(), module_name: namespace.clone(), function_name: format!("{}.{}", box_name, method_name), function_info: function, }); } } } } Err(RuntimeError::UndefinedMethod(format!("{}.{}", box_name, method_name))) } } #[derive(Debug, Clone)] pub enum ResolvedCall { Builtin { namespace: String, box_name: String, method_name: String, method_info: BuiltinMethodInfo, }, BidCall { namespace: String, interface_name: String, method_name: String, method_info: BidMethod, bid_definition: Arc, }, ModuleCall { namespace: String, module_name: String, function_name: String, function_info: ModuleFunctionInfo, }, } ``` ### 3. MIR生成統合 #### **統合MIR Builder** ```rust // src/mir/builder.rs拡張 impl MirBuilder { pub fn build_unified_method_call(&mut self, resolved_call: ResolvedCall, args: Vec) -> Result, MirError> { match resolved_call { ResolvedCall::Builtin { method_info, .. } => { let result = self.new_value_id(); self.emit(MirInstruction::BuiltinCall { qualified_name: method_info.qualified_name(), args, result, effect: method_info.effect(), }); Ok(Some(result)) }, ResolvedCall::BidCall { interface_name, method_name, method_info, .. } => { let result = if method_info.returns == BidType::Void { None } else { Some(self.new_value_id()) }; self.emit(MirInstruction::ExternCall { interface: interface_name, method: method_name, args, result, effect: self.bid_effect_to_mir_effect(&method_info.effect), bid_signature: BidSignature::from_method(&method_info), }); Ok(result) }, ResolvedCall::ModuleCall { module_name, function_name, function_info, .. } => { let result = self.new_value_id(); self.emit(MirInstruction::ModuleCall { module: module_name, function: function_name, args, result, effect: Effect::Io, // Nyashモジュールはデフォルトでio }); Ok(Some(result)) }, } } fn bid_effect_to_mir_effect(&self, bid_effect: &BidEffect) -> Effect { match bid_effect { BidEffect::Pure => Effect::Pure, BidEffect::Mut => Effect::Mut, BidEffect::Io => Effect::Io, BidEffect::Control => Effect::Control, } } } ``` ### 4. バックエンド統合 #### **WASM生成統合** ```rust // src/backend/wasm/codegen.rs拡張 impl WasmCodegen { pub fn generate_unified_call(&mut self, instruction: &MirInstruction) -> Result<(), WasmError> { match instruction { MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => { // BIDから自動生成されたWASM import名 let wasm_import_name = self.bid_to_wasm_import_name(interface, method); // 引数の型変換・マーシャリング let marshalled_args = self.marshal_args_for_wasm(args, &bid_signature.params)?; // WASM関数呼び出し生成 self.emit_call(&wasm_import_name, &marshalled_args)?; // 戻り値のアンマーシャリング if bid_signature.returns != BidType::Void { self.unmarshal_return_value(&bid_signature.returns)?; } Ok(()) }, // 他の命令は既存実装 _ => self.generate_instruction_legacy(instruction), } } fn bid_to_wasm_import_name(&self, interface: &str, method: &str) -> String { // "canvas_api.canvas" + "fillRect" → "canvas_api_canvas_fillRect" format!("{}_{}", interface.replace(".", "_"), method) } fn marshal_args_for_wasm(&mut self, args: &[ValueId], params: &[BidParam]) -> Result, WasmError> { let mut marshalled = Vec::new(); for (i, param) in params.iter().enumerate() { let arg_value = self.get_value(args[i])?; match ¶m.param_type { BidType::String => { // 文字列を (ptr, len) にマーシャル let (ptr, len) = self.string_to_wasm_memory(&arg_value)?; marshalled.push(WasmValue::I32(ptr)); marshalled.push(WasmValue::I32(len)); }, BidType::I32 => { marshalled.push(WasmValue::I32(arg_value.to_i32()?)); }, BidType::F64 => { marshalled.push(WasmValue::F64(arg_value.to_f64()?)); }, // その他の型... } } Ok(marshalled) } } ``` #### **VM実行統合** ```rust // src/backend/vm.rs拡張 impl VmBackend { pub fn execute_unified_instruction(&mut self, instruction: &MirInstruction) -> Result<(), VmError> { match instruction { MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => { // VM環境ではスタブまたはネイティブ呼び出し let evaluated_args = self.evaluate_args(args)?; if let Some(native_impl) = self.find_native_implementation(interface, method) { // ネイティブ実装がある場合(例:ファイルI/O) let result = native_impl.call(evaluated_args, bid_signature)?; if let Some(result_id) = &instruction.result { self.set_value(*result_id, result); } } else { // スタブ実装(ログ出力等) self.execute_stub_call(interface, method, evaluated_args, bid_signature)?; } Ok(()) }, // 他の命令は既存実装 _ => self.execute_instruction_legacy(instruction), } } fn find_native_implementation(&self, interface: &str, method: &str) -> Option<&dyn NativeImplementation> { // VM環境で利用可能なネイティブ実装を検索 match (interface, method) { ("env.console", "log") => Some(&self.console_impl), ("env.filesystem", "read") => Some(&self.filesystem_impl), ("env.filesystem", "write") => Some(&self.filesystem_impl), _ => None, } } } ``` ## 🧪 統合テスト戦略 ### Phase別テスト実装 #### **Phase 0: 基本統合テスト** ```nyash # test_basic_integration.hako using nyashstd # 組み込み標準ライブラリのみ assert(string.upper("test") == "TEST") assert(math.sin(0) == 0) ``` #### **Phase 1: BID統合テスト** ```nyash # test_bid_integration.hako using nyashstd using console_api # 組み込み + FFI-ABI string.upper("hello") # 組み込み console.log("Testing") # FFI-ABI ``` #### **Phase 2: 完全統合テスト** ```nyash # test_full_integration.hako using nyashstd using console_api using mylib # 3種類すべて string.upper("test") # 組み込み console.log("Integration") # FFI-ABI mylib.process("data") # Nyashモジュール ``` ### エラーハンドリングテスト ```nyash # test_error_handling.hako try { using nonexistent_api } catch error { assert(error.type == "UndefinedNamespace") } try { console.nonexistent_method("test") } catch error { assert(error.type == "UndefinedMethod") assert(error.message.contains("Available methods:")) } ``` ## 📊 実装マイルストーン ### ✅ Phase 0完了条件 - [ ] UniversalNamespaceRegistry基盤実装 - [ ] 組み込み標準ライブラリ統合 - [ ] 基本using文処理 - [ ] MIR BuiltinCall生成 ### ✅ Phase 1完了条件 - [ ] BID定義読み込み・検証 - [ ] BID→MIR ExternCall統合 - [ ] WASM RuntimeImports自動生成 - [ ] VM スタブ実行 ### ✅ Phase 2完了条件 - [ ] Nyashモジュール統合 - [ ] 統合エラーハンドリング - [ ] 最適化キャッシュ - [ ] 全バックエンド対応 --- **🎯 この詳細実装により、BIDとusingシステムの完全統合が実現でき、「なんでもAPI計画」の技術基盤が完成するにゃ!🚀🐱**