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

435 lines
12 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.

# 最小実装標準関数優先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が実現できるにゃ🐱**