Files
hakorune/docs/development/proposals/nyash.link/minimal-stdlib-first.md

435 lines
12 KiB
Markdown
Raw Normal View History

# 最小実装標準関数優先namespace/usingシステム
## 🎯 基本戦略nyash.link前の段階的実装
### 📊 現状分析
- **既存Box型**: 25種類以上の豊富なBox実装
- **include使用**: 限定的text_adventure例のみ
- **using実装**: 完全未実装→新規作成可能
- **最優先課題**: 複雑なファイル依存関係システムより、まず標準関数のIDE補完
### 🌟 段階的実装アプローチ
#### **Phase 0: 組み込みnyashstd最小実装**
```
ファイル読み込み一切なし → インタープリターに直接組み込み
```
#### **Phase 1: using構文**
```nyash
using nyashstd
string.upper("hello") # ✅ 動作
```
#### **Phase 2: 将来のnyash.link対応**
```
外部ファイル・依存関係システム(後日実装)
```
## 🏗️ 組み込みnyashstd設計
### 優先順位別Box分類
#### 🚨 **Tier 1: 最優先基本機能**
```rust
// 使用頻度最高・IDE補完必須
- string_box.rs → nyashstd.string.*
- math_box.rs → nyashstd.math.*
- array/mod.rs → nyashstd.array.*
- console_box.rs → nyashstd.io.*
```
#### ⚡ **Tier 2: 重要機能**
```rust
// 標準的な機能
- time_box.rs → nyashstd.time.*
- random_box.rs → nyashstd.random.*
- map_box.rs → nyashstd.map.*
```
#### 📝 **Tier 3: 特殊用途**
```rust
// 特定用途・後で追加
- debug_box.rs → nyashstd.debug.*
- http_server_box.rs → nyashstd.http.*
- p2p_box.rs → nyashstd.p2p.*
```
### 最小実装スコープPhase 0
#### **nyashstd.string機能**
```nyash
using nyashstd
string.upper("hello") # "HELLO"
string.lower("WORLD") # "world"
string.split("a,b,c", ",") # ["a", "b", "c"]
string.join(["a","b"], "-") # "a-b"
string.length("test") # 4
```
#### **nyashstd.math機能**
```nyash
using nyashstd
math.sin(3.14159) # 0.0 (approximately)
math.cos(0) # 1.0
math.sqrt(16) # 4.0
math.floor(3.7) # 3
math.random() # 0.0-1.0のランダム値
```
#### **nyashstd.array機能**
```nyash
using nyashstd
array.length([1,2,3]) # 3
array.push([1,2], 3) # [1,2,3]
array.get([1,2,3], 1) # 2
array.slice([1,2,3,4], 1, 3) # [2,3]
```
#### **nyashstd.io機能**
```nyash
using nyashstd
io.print("Hello") # コンソール出力
io.println("World") # 改行付き出力
io.debug("Debug info") # デバッグ出力
```
## 💻 技術実装戦略
### 1. インタープリター組み込み方式
#### **新ファイル: `src/stdlib/mod.rs`**
```rust
//! 組み込み標準ライブラリ
//! nyash.linkなしで動作する基本的な標準関数群
use crate::boxes::*;
use std::collections::HashMap;
pub struct BuiltinStdlib {
pub namespaces: HashMap<String, BuiltinNamespace>,
}
pub struct BuiltinNamespace {
pub name: String,
pub static_boxes: HashMap<String, BuiltinStaticBox>,
}
pub struct BuiltinStaticBox {
pub name: String,
pub methods: HashMap<String, BuiltinMethod>,
}
pub type BuiltinMethod = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
impl BuiltinStdlib {
pub fn new() -> Self {
let mut stdlib = BuiltinStdlib {
namespaces: HashMap::new(),
};
// nyashstd名前空間登録
stdlib.register_nyashstd();
stdlib
}
fn register_nyashstd(&mut self) {
let mut nyashstd = BuiltinNamespace {
name: "nyashstd".to_string(),
static_boxes: HashMap::new(),
};
// string static box
nyashstd.static_boxes.insert("string".to_string(), self.create_string_box());
// math static box
nyashstd.static_boxes.insert("math".to_string(), self.create_math_box());
// array static box
nyashstd.static_boxes.insert("array".to_string(), self.create_array_box());
// io static box
nyashstd.static_boxes.insert("io".to_string(), self.create_io_box());
self.namespaces.insert("nyashstd".to_string(), nyashstd);
}
}
```
#### **文字列関数実装例**
```rust
impl BuiltinStdlib {
fn create_string_box(&self) -> BuiltinStaticBox {
let mut string_box = BuiltinStaticBox {
name: "string".to_string(),
methods: HashMap::new(),
};
// string.upper(str) -> String
string_box.methods.insert("upper".to_string(), |args| {
if args.len() != 1 {
return Err(RuntimeError::InvalidArguments(
"string.upper() takes exactly 1 argument".to_string()
));
}
let string_arg = args[0].to_string_box();
let result = StringBox::new(&string_arg.value.to_uppercase());
Ok(Box::new(result))
});
// string.lower(str) -> String
string_box.methods.insert("lower".to_string(), |args| {
if args.len() != 1 {
return Err(RuntimeError::InvalidArguments(
"string.lower() takes exactly 1 argument".to_string()
));
}
let string_arg = args[0].to_string_box();
let result = StringBox::new(&string_arg.value.to_lowercase());
Ok(Box::new(result))
});
// string.split(str, separator) -> Array
string_box.methods.insert("split".to_string(), |args| {
if args.len() != 2 {
return Err(RuntimeError::InvalidArguments(
"string.split() takes exactly 2 arguments".to_string()
));
}
let string_arg = args[0].to_string_box();
let sep_arg = args[1].to_string_box();
let string_box = StringBox::new(&string_arg.value);
let result = string_box.split(&sep_arg.value)?;
Ok(result)
});
string_box
}
}
```
### 2. インタープリター統合
#### **インタープリター拡張: `src/interpreter/core.rs`**
```rust
use crate::stdlib::BuiltinStdlib;
pub struct NyashInterpreter {
// 既存フィールド...
pub builtin_stdlib: BuiltinStdlib,
pub using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
}
impl NyashInterpreter {
pub fn new() -> Self {
NyashInterpreter {
// 既存初期化...
builtin_stdlib: BuiltinStdlib::new(),
using_imports: HashMap::new(),
}
}
// using文実行
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
// 組み込み名前空間かチェック
if self.builtin_stdlib.namespaces.contains_key(namespace_name) {
// 現在ファイルのインポートリストに追加
self.using_imports
.entry(self.current_file_id.clone())
.or_insert_with(Vec::new)
.push(namespace_name.to_string());
Ok(())
} else {
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
}
}
// 短縮名解決: string.upper() -> nyashstd.string.upper()
pub fn resolve_short_call(&self, box_name: &str, method_name: &str)
-> Option<(&str, &str, &str)> { // (namespace, box, method)
if let Some(imports) = self.using_imports.get(&self.current_file_id) {
for namespace_name in imports {
if let Some(namespace) = self.builtin_stdlib.namespaces.get(namespace_name) {
if namespace.static_boxes.contains_key(box_name) {
return Some((namespace_name, box_name, method_name));
}
}
}
}
None
}
// 組み込み関数呼び出し
pub fn call_builtin_method(&self, namespace: &str, box_name: &str, method_name: &str, args: Vec<Box<dyn NyashBox>>)
-> Result<Box<dyn NyashBox>, RuntimeError> {
if let Some(ns) = self.builtin_stdlib.namespaces.get(namespace) {
if let Some(static_box) = ns.static_boxes.get(box_name) {
if let Some(method) = static_box.methods.get(method_name) {
return method(&args);
}
}
}
Err(RuntimeError::UndefinedMethod(
format!("{}.{}.{}", namespace, box_name, method_name)
))
}
}
```
### 3. パーサー最小拡張
#### **トークナイザー: `src/tokenizer.rs`**
```rust
pub enum TokenType {
// 既存...
USING, // using キーワード
// NAMESPACE は後のPhaseで追加
}
```
#### **AST最小拡張: `src/ast.rs`**
```rust
pub enum ASTNode {
// 既存...
UsingStatement {
namespace_name: String, // "nyashstd" のみ対応
span: Span,
},
// QualifiedCall は後のPhaseで追加
}
```
#### **パーサー: `src/parser/statements.rs`**
```rust
impl NyashParser {
pub fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
self.advance(); // consume 'using'
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
let name = namespace_name.clone();
self.advance();
// Phase 0では "nyashstd" のみ許可
if name != "nyashstd" {
return Err(ParseError::UnsupportedNamespace(name));
}
Ok(ASTNode::UsingStatement {
namespace_name: name,
span: self.current_span(),
})
} else {
Err(ParseError::ExpectedIdentifier)
}
}
}
```
## 🧪 テスト戦略
### Phase 0テストケース
#### **基本using文テスト**
```nyash
# test_using_basic.hako
using nyashstd
local result = string.upper("hello")
assert(result == "HELLO")
local lower = string.lower("WORLD")
assert(lower == "world")
```
#### **数学関数テスト**
```nyash
# test_math_basic.hako
using nyashstd
local sin_result = math.sin(0)
assert(sin_result == 0)
local sqrt_result = math.sqrt(16)
assert(sqrt_result == 4)
```
#### **配列操作テスト**
```nyash
# test_array_basic.hako
using nyashstd
local arr = [1, 2, 3]
local length = array.length(arr)
assert(length == 3)
local item = array.get(arr, 1)
assert(item == 2)
```
## 📊 実装マイルストーン
### ✅ Phase 0完了条件
- [ ] USING トークン認識
- [ ] using nyashstd 構文解析
- [ ] 組み込みnyashstd.string実装
- [ ] 組み込みnyashstd.math実装
- [ ] 組み込みnyashstd.array実装
- [ ] 組み込みnyashstd.io実装
- [ ] 基本テストケース全通過
### 🔮 将来の発展
#### **Phase 1: 完全修飾名対応**
```nyash
# using不要でも使える
nyashstd.string.upper("hello")
```
#### **Phase 2: namespace構文対応**
```nyash
# 組み込み以外の名前空間
namespace mylib {
static box utils {
static process(data) { ... }
}
}
```
#### **Phase 3: nyash.link統合**
```toml
# nyash.link
[dependencies]
mylib = { path = "./mylib.hako" }
```
## 🎯 実装優先順位
### 🚨 Critical今すぐ
1. **USINGトークナイザー** - Token::USING追加
2. **using文パーサー** - "using nyashstd"解析
3. **BuiltinStdlib基盤** - src/stdlib/mod.rs作成
### ⚡ High今週中
4. **string関数実装** - upper, lower, split, join
5. **math関数実装** - sin, cos, sqrt, floor
6. **基本テスト** - using nyashstd動作確認
### 📝 Medium来週
7. **array関数実装** - length, get, push, slice
8. **io関数実装** - print, println, debug
9. **エラーハンドリング** - 適切なエラーメッセージ
---
**🎉 この戦略なら複雑なファイル依存関係システムなしで、すぐに実用的なnamespace/usingが実現できるにゃ🐱**