Files
hakorune/docs/development/proposals/nyash.link/builtin-stdlib-architecture.md

456 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 組み込みnyashstd名前空間アーキテクチャ設計
## 🏗️ 技術的実装アーキテクチャ
### 📊 現在のインタープリター構造分析
#### **NyashInterpreter構造**
```rust
pub struct NyashInterpreter {
pub(super) shared: SharedState, // 共有状態
pub(super) local_vars: HashMap<String, SharedNyashBox>,
pub(super) outbox_vars: HashMap<String, SharedNyashBox>,
// その他の制御フロー状態...
}
```
#### **設計判断SharedStateに組み込み**
- **理由**: 標準ライブラリは不変・全インタープリターで共有可能
- **利点**: メモリ効率、パフォーマンス向上
- **実装**: SharedStateに`builtin_stdlib`フィールド追加
## 🌟 最適化されたアーキテクチャ設計
### 1. SharedState拡張
#### **src/interpreter/core.rs**
```rust
#[derive(Clone)]
pub struct SharedState {
// 既存フィールド...
pub global_vars: Arc<RwLock<HashMap<String, SharedNyashBox>>>,
pub functions: Arc<RwLock<HashMap<String, Function>>>,
pub box_definitions: Arc<RwLock<HashMap<String, Box<UserDefinedBoxDefinition>>>>,
pub loop_counter: Arc<AtomicU64>,
pub included_files: Arc<RwLock<HashSet<String>>>,
// 🌟 新規追加: 組み込み標準ライブラリ
pub builtin_stdlib: Arc<BuiltinStdlib>,
pub using_imports: Arc<RwLock<HashMap<String, UsingContext>>>, // ファイル別インポート管理
}
#[derive(Debug, Clone)]
pub struct UsingContext {
pub imported_namespaces: Vec<String>, // ["nyashstd"]
pub file_id: String, // インポート元ファイル識別
}
```
### 2. BuiltinStdlib効率化設計
#### **新ファイル: src/stdlib/builtin.rs**
```rust
//! 🚀 高性能組み込み標準ライブラリ
//!
//! 設計方針:
//! - Zero-allocation関数実行
//! - 高速名前解決
//! - 既存Box実装の最大活用
use crate::boxes::*;
use std::collections::HashMap;
/// 組み込み標準ライブラリのメイン構造体
#[derive(Debug)]
pub struct BuiltinStdlib {
/// 高速アクセス用:フラットな関数マップ
/// "string.upper" -> BuiltinFunction
pub flat_functions: HashMap<String, BuiltinFunction>,
/// IDE補完用階層構造
/// "nyashstd" -> { "string" -> ["upper", "lower", ...] }
pub hierarchical_map: HashMap<String, HashMap<String, Vec<String>>>,
}
/// 組み込み関数の実装
pub struct BuiltinFunction {
pub namespace: &'static str, // "nyashstd"
pub box_name: &'static str, // "string"
pub method_name: &'static str, // "upper"
pub implementation: BuiltinMethodImpl,
pub arg_count: Option<usize>, // None = 可変長
pub description: &'static str, // エラーメッセージ・ヘルプ用
}
/// 高性能関数実装
pub type BuiltinMethodImpl = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
impl BuiltinStdlib {
/// 🚀 標準ライブラリ初期化起動時1回のみ
pub fn new() -> Self {
let mut stdlib = BuiltinStdlib {
flat_functions: HashMap::new(),
hierarchical_map: HashMap::new(),
};
// 標準関数登録
stdlib.register_all_functions();
stdlib
}
/// ⚡ 高速関数解決
pub fn get_function(&self, qualified_name: &str) -> Option<&BuiltinFunction> {
// "string.upper" で直接アクセス
self.flat_functions.get(qualified_name)
}
/// 🔍 IDE補完用利用可能関数一覧取得
pub fn get_available_methods(&self, namespace: &str, box_name: &str) -> Option<&Vec<String>> {
self.hierarchical_map.get(namespace)?.get(box_name)
}
/// 📋 全名前空間取得IDE補完用
pub fn get_all_namespaces(&self) -> Vec<&String> {
self.hierarchical_map.keys().collect()
}
}
```
### 3. 標準関数実装(高性能版)
#### **文字列関数実装**
```rust
impl BuiltinStdlib {
fn register_all_functions(&mut self) {
// === nyashstd.string.* ===
self.register_function("string.upper", BuiltinFunction {
namespace: "nyashstd",
box_name: "string",
method_name: "upper",
implementation: |args| {
if args.len() != 1 {
return Err(RuntimeError::InvalidArguments(
"string.upper(str) takes exactly 1 argument".to_string()
));
}
// 🚀 既存StringBox実装活用
let input_str = args[0].to_string_box().value;
let result = StringBox::new(&input_str.to_uppercase());
Ok(Box::new(result))
},
arg_count: Some(1),
description: "Convert string to uppercase",
});
self.register_function("string.lower", BuiltinFunction {
namespace: "nyashstd",
box_name: "string",
method_name: "lower",
implementation: |args| {
if args.len() != 1 {
return Err(RuntimeError::InvalidArguments(
"string.lower(str) takes exactly 1 argument".to_string()
));
}
let input_str = args[0].to_string_box().value;
let result = StringBox::new(&input_str.to_lowercase());
Ok(Box::new(result))
},
arg_count: Some(1),
description: "Convert string to lowercase",
});
self.register_function("string.split", BuiltinFunction {
namespace: "nyashstd",
box_name: "string",
method_name: "split",
implementation: |args| {
if args.len() != 2 {
return Err(RuntimeError::InvalidArguments(
"string.split(str, separator) takes exactly 2 arguments".to_string()
));
}
// 🚀 既存StringBox.split()メソッド活用
let string_box = StringBox::new(&args[0].to_string_box().value);
let separator = &args[1].to_string_box().value;
string_box.split(separator)
},
arg_count: Some(2),
description: "Split string by separator into array",
});
// === nyashstd.math.* ===
self.register_function("math.sin", BuiltinFunction {
namespace: "nyashstd",
box_name: "math",
method_name: "sin",
implementation: |args| {
if args.len() != 1 {
return Err(RuntimeError::InvalidArguments(
"math.sin(x) takes exactly 1 argument".to_string()
));
}
// 🚀 既存MathBox実装活用
let math_box = MathBox::new();
let x = args[0].to_integer_box().value as f64;
let result = math_box.sin(x)?;
Ok(result)
},
arg_count: Some(1),
description: "Calculate sine of x (in radians)",
});
// 階層マップも同時構築
self.build_hierarchical_map();
}
fn register_function(&mut self, qualified_name: &str, function: BuiltinFunction) {
self.flat_functions.insert(qualified_name.to_string(), function);
}
fn build_hierarchical_map(&mut self) {
for (qualified_name, function) in &self.flat_functions {
let namespace_map = self.hierarchical_map
.entry(function.namespace.to_string())
.or_insert_with(HashMap::new);
let method_list = namespace_map
.entry(function.box_name.to_string())
.or_insert_with(Vec::new);
method_list.push(function.method_name.to_string());
}
// ソートして一貫性確保
for namespace_map in self.hierarchical_map.values_mut() {
for method_list in namespace_map.values_mut() {
method_list.sort();
}
}
}
}
```
### 4. インタープリター統合
#### **NyashInterpreter拡張**
```rust
impl NyashInterpreter {
/// using文実行
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
// 組み込み名前空間存在チェック
if !self.shared.builtin_stdlib.hierarchical_map.contains_key(namespace_name) {
return Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()));
}
// 現在ファイルのusingコンテキスト更新
let file_id = self.get_current_file_id();
let mut using_imports = self.shared.using_imports.write().unwrap();
let context = using_imports.entry(file_id.clone()).or_insert(UsingContext {
imported_namespaces: Vec::new(),
file_id: file_id.clone(),
});
if !context.imported_namespaces.contains(&namespace_name.to_string()) {
context.imported_namespaces.push(namespace_name.to_string());
}
Ok(())
}
/// ⚡ 高速名前解決string.upper() → nyashstd.string.upper()
pub fn resolve_qualified_call(&self, path: &[String]) -> Option<String> {
if path.len() != 2 {
return None; // Phase 0では2段階のみ対応
}
let box_name = &path[0];
let method_name = &path[1];
let file_id = self.get_current_file_id();
// 現在ファイルのusingインポート確認
if let Ok(using_imports) = self.shared.using_imports.read() {
if let Some(context) = using_imports.get(&file_id) {
for namespace in &context.imported_namespaces {
let qualified_name = format!("{}.{}", box_name, method_name);
// 実際に関数が存在するかチェック
if self.shared.builtin_stdlib.get_function(&qualified_name).is_some() {
return Some(qualified_name);
}
}
}
}
None
}
/// 🚀 組み込み関数実行
pub fn call_builtin_function(&self, qualified_name: &str, args: Vec<Box<dyn NyashBox>>)
-> Result<Box<dyn NyashBox>, RuntimeError> {
if let Some(function) = self.shared.builtin_stdlib.get_function(qualified_name) {
// 引数数チェック
if let Some(expected_count) = function.arg_count {
if args.len() != expected_count {
return Err(RuntimeError::InvalidArguments(
format!("{}.{}() takes exactly {} arguments, got {}",
function.box_name, function.method_name,
expected_count, args.len())
));
}
}
// 関数実行
(function.implementation)(&args)
} else {
Err(RuntimeError::UndefinedMethod(qualified_name.to_string()))
}
}
}
```
### 5. 式実行統合
#### **src/interpreter/expressions.rs修正**
```rust
impl NyashInterpreter {
pub fn execute_expression(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
match node {
// 既存のケース...
// メソッド呼び出し処理修正
ASTNode::MethodCall { object, method, args, .. } => {
// オブジェクトが単純な識別子かチェック
if let ASTNode::Variable { name: box_name, .. } = object.as_ref() {
// using経由での短縮呼び出しチェック
let path = vec![box_name.clone(), method.clone()];
if let Some(qualified_name) = self.resolve_qualified_call(&path) {
// 引数評価
let evaluated_args = self.evaluate_arguments(args)?;
// 組み込み関数実行
return self.call_builtin_function(&qualified_name, evaluated_args);
}
}
// 既存のメソッド呼び出し処理
// ...
}
// using文実行
ASTNode::UsingStatement { namespace_name, .. } => {
self.execute_using(namespace_name)?;
Ok(Box::new(VoidBox::new()))
}
// 他の既存ケース...
}
}
}
```
## 📊 パフォーマンス特性
### ⚡ 最適化ポイント
#### **1. Zero-Allocation関数解決**
```rust
// ❌ 遅い:毎回文字列生成
let qualified = format!("{}.{}", box_name, method_name);
// ✅ 高速:事前計算済みマップ
if let Some(func) = stdlib.flat_functions.get(&qualified_name) { ... }
```
#### **2. 高速名前解決**
```rust
// O(1)アクセスHashMap直接ルックアップ
// "string.upper" -> BuiltinFunction
```
#### **3. 既存Box実装活用**
```rust
// 既存の最適化済みStringBox.split()を直接使用
string_box.split(separator) // 新規実装不要
```
## 🧪 テストカバレッジ
### Phase 0必須テスト
#### **基本機能テスト**
```nyash
# test_builtin_stdlib_basic.hako
using nyashstd
# 文字列操作
assert(string.upper("hello") == "HELLO")
assert(string.lower("WORLD") == "world")
assert(string.split("a,b,c", ",").length() == 3)
# 数学関数
assert(math.sin(0) == 0)
assert(math.cos(0) == 1)
# 配列操作
local arr = [1, 2, 3]
assert(array.length(arr) == 3)
assert(array.get(arr, 1) == 2)
```
#### **エラーハンドリング**
```nyash
# test_builtin_stdlib_errors.hako
using nyashstd
# 引数数エラー
try {
string.upper("hello", "extra") # 2引数でエラー
assert(false, "Should have thrown error")
} catch e {
assert(e.contains("takes exactly 1 argument"))
}
# 未定義名前空間
try {
using nonexistent
assert(false, "Should have thrown error")
} catch e {
assert(e.contains("UndefinedNamespace"))
}
```
#### **IDE補完サポート**
```rust
// テスト:補完候補取得
let methods = stdlib.get_available_methods("nyashstd", "string");
assert!(methods.unwrap().contains(&"upper".to_string()));
assert!(methods.unwrap().contains(&"lower".to_string()));
```
## 🎯 実装順序
### 🚨 Critical即時実装
1. **BuiltinStdlib基盤** - src/stdlib/builtin.rs作成
2. **SharedState統合** - builtin_stdlibフィールド追加
3. **using文パーサー** - ASTNode::UsingStatement
### ⚡ High今週中
4. **string関数4種** - upper, lower, split, join
5. **基本テスト** - using nyashstd動作確認
6. **エラーハンドリング** - 適切なエラーメッセージ
### 📝 Medium来週
7. **math関数5種** - sin, cos, sqrt, floor, random
8. **array関数4種** - length, get, push, slice
9. **io関数3種** - print, println, debug
---
**⚡ この高性能アーキテクチャで、複雑なファイル依存関係なしに即座に実用的なnamespace/usingが実現できるにゃ🚀**