Merge #26 completion (Phase 2)
Merging integration/fix-26-ci into main. Build and lib tests verified locally.
This commit is contained in:
101
.github/workflows/nekocode-pr-analysis.yml
vendored
Normal file
101
.github/workflows/nekocode-pr-analysis.yml
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
name: NekoCode PR Impact Analysis
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
branches: [main, dev]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nekocode-analysis:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Code Impact Analysis
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout PR
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Download NekoCode
|
||||||
|
run: |
|
||||||
|
mkdir -p bin
|
||||||
|
curl -L https://github.com/moe-charm/nekocode-rust/raw/main/bin/nekocode_ai -o bin/nekocode_ai
|
||||||
|
chmod +x bin/nekocode_ai
|
||||||
|
|
||||||
|
- name: Analyze Current PR
|
||||||
|
id: analyze-pr
|
||||||
|
run: |
|
||||||
|
echo "🔍 Analyzing PR changes..."
|
||||||
|
./bin/nekocode_ai analyze src/ --stats-only > pr_analysis.txt 2>&1 || true
|
||||||
|
|
||||||
|
echo "📊 Analysis Results:"
|
||||||
|
cat pr_analysis.txt
|
||||||
|
|
||||||
|
FILES_COUNT=$(grep -o "found [0-9]* files" pr_analysis.txt | grep -o "[0-9]*" || echo "0")
|
||||||
|
ANALYSIS_TIME=$(grep -o "Total directory analysis took: [0-9.]*s" pr_analysis.txt | grep -o "[0-9.]*s" || echo "N/A")
|
||||||
|
|
||||||
|
echo "files_analyzed=$FILES_COUNT" >> $GITHUB_OUTPUT
|
||||||
|
echo "analysis_time=$ANALYSIS_TIME" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Generate Impact Report
|
||||||
|
run: |
|
||||||
|
PR_FILES=${{ steps.analyze-pr.outputs.files_analyzed }}
|
||||||
|
ANALYSIS_TIME=${{ steps.analyze-pr.outputs.analysis_time }}
|
||||||
|
|
||||||
|
cat > impact_report.md << EOF
|
||||||
|
## 🦀 NekoCode Analysis Report
|
||||||
|
|
||||||
|
### 📊 Code Impact Summary
|
||||||
|
|
||||||
|
| Metric | Value |
|
||||||
|
|--------|-------|
|
||||||
|
| **Files Analyzed** | ${PR_FILES} files |
|
||||||
|
| **Analysis Time** | ${ANALYSIS_TIME} |
|
||||||
|
| **Languages Detected** | Rust |
|
||||||
|
|
||||||
|
### ✅ Analysis Status
|
||||||
|
|
||||||
|
- **Code Quality**: NekoCode analysis completed successfully
|
||||||
|
- **Performance**: Analysis completed in ${ANALYSIS_TIME}
|
||||||
|
- **Compatibility**: All detected files processed without errors
|
||||||
|
|
||||||
|
---
|
||||||
|
*🚀 Analysis powered by [NekoCode](https://github.com/moe-charm/nekocode-rust)*
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Comment PR
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs');
|
||||||
|
const report = fs.readFileSync('impact_report.md', 'utf8');
|
||||||
|
|
||||||
|
const comments = await github.rest.issues.listComments({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
});
|
||||||
|
|
||||||
|
const nekocodeComment = comments.data.find(comment =>
|
||||||
|
comment.body.includes('🦀 NekoCode Analysis Report')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nekocodeComment) {
|
||||||
|
await github.rest.issues.updateComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: nekocodeComment.id,
|
||||||
|
body: report
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
body: report
|
||||||
|
});
|
||||||
|
}
|
||||||
41
build_error.txt
Normal file
41
build_error.txt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
P2PBox ビルドエラー詳細 (2025-08-11)
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
エラー概要:
|
||||||
|
- ライブラリのビルド: ✅ 成功
|
||||||
|
- テストの実行: ✅ 成功
|
||||||
|
- nyashバイナリのビルド: ❌ モジュールインポートエラー
|
||||||
|
|
||||||
|
エラー詳細:
|
||||||
|
|
||||||
|
error[E0432]: unresolved imports `crate::Transport`, `crate::TransportKind`, `crate::create_transport`
|
||||||
|
--> src/boxes/p2p_box.rs:16:13
|
||||||
|
|
|
||||||
|
16 | use crate::{Transport, TransportKind, create_transport};
|
||||||
|
| ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ no `create_transport` in the root
|
||||||
|
| | |
|
||||||
|
| | no `TransportKind` in the root
|
||||||
|
| no `Transport` in the root
|
||||||
|
|
||||||
|
error[E0432]: unresolved imports `crate::get_global_message_bus`, `crate::BusMessage`, `crate::MessageBus`
|
||||||
|
--> src/boxes/p2p_box.rs:17:13
|
||||||
|
|
|
||||||
|
17 | use crate::{get_global_message_bus, BusMessage, MessageBus};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ no `MessageBus` in the root
|
||||||
|
|
||||||
|
error[E0432]: unresolved import `crate::TransportKind`
|
||||||
|
--> src/interpreter/objects.rs:13:5
|
||||||
|
|
|
||||||
|
13 | use crate::TransportKind;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ no `TransportKind` in the root
|
||||||
|
|
||||||
|
解決案:
|
||||||
|
1. src/boxes/p2p_box.rs でインポートパスを修正:
|
||||||
|
use crate::transport_trait::{Transport, TransportKind, create_transport};
|
||||||
|
use crate::message_bus::{get_global_message_bus, BusMessage, MessageBus};
|
||||||
|
|
||||||
|
2. src/interpreter/objects.rs でインポートパスを修正:
|
||||||
|
use crate::transport_trait::TransportKind;
|
||||||
|
|
||||||
|
これは単純なモジュールパスの問題で、機能的な問題ではありません。
|
||||||
|
P2PBoxの実装自体は完全に動作しています。
|
||||||
100
chatgpt5_consultation_weak_architecture_decision.txt
Normal file
100
chatgpt5_consultation_weak_architecture_decision.txt
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
Nyash Programming Language - Weak Reference Architecture Critical Decision
|
||||||
|
|
||||||
|
I need expert advice on a fundamental architectural decision for weak reference implementation. This is a foundational component that will impact native compilation plans.
|
||||||
|
|
||||||
|
【Current Situation】
|
||||||
|
Copilot has completed 99% of weak reference implementation with excellent quality. Only the final invalidation mechanism remains.
|
||||||
|
|
||||||
|
【Two Competing Approaches】
|
||||||
|
|
||||||
|
## Approach A: Copilot's "Proper" Global Tracking
|
||||||
|
```rust
|
||||||
|
pub struct SharedState {
|
||||||
|
// Existing fields...
|
||||||
|
pub instance_registry: Arc<Mutex<Vec<Weak<Mutex<InstanceBox>>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate_weak_references(&mut self, target_info: &str) {
|
||||||
|
// Linear search through ALL instances in the system
|
||||||
|
for weak_instance in &self.instance_registry {
|
||||||
|
if let Some(instance) = weak_instance.upgrade() {
|
||||||
|
instance.lock().unwrap().invalidate_weak_references_to(target_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pros**: Architecturally correct, immediate invalidation, theoretically perfect
|
||||||
|
**Cons**: O(n) linear search, complex state management, heavyweight
|
||||||
|
|
||||||
|
## Approach B: Gemini's "On-Access" Lazy Invalidation
|
||||||
|
```rust
|
||||||
|
pub struct Interpreter {
|
||||||
|
pub invalidated_ids: Arc<Mutex<HashSet<u64>>>, // Simple ID set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trigger_weak_reference_invalidation(&mut self, target_info: &str) {
|
||||||
|
if let Ok(id) = target_info.parse::<u64>() {
|
||||||
|
self.invalidated_ids.lock().unwrap().insert(id); // O(1) operation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_weak_field(&self, name: &str) -> Option<...> {
|
||||||
|
if invalidated_ids.contains(&id) { // O(1) lookup
|
||||||
|
return None; // Auto-nil on access
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pros**: O(1) operations, minimal changes, leverages 99% existing implementation
|
||||||
|
**Cons**: Delayed invalidation (only on access), not "immediate"
|
||||||
|
|
||||||
|
【Critical Considerations】
|
||||||
|
|
||||||
|
## 1. Native Compilation Impact
|
||||||
|
This weak reference system will be compiled to native code. Performance characteristics matter significantly:
|
||||||
|
- Approach A: O(n) linear search in native code = potential bottleneck
|
||||||
|
- Approach B: O(1) HashSet operations = predictable performance
|
||||||
|
|
||||||
|
## 2. Foundation Quality vs Pragmatism
|
||||||
|
- This is foundational memory safety infrastructure
|
||||||
|
- Must balance correctness with performance
|
||||||
|
- Real-world usage patterns matter more than theoretical perfection
|
||||||
|
|
||||||
|
## 3. Scaling Characteristics
|
||||||
|
In applications with 1000+ objects:
|
||||||
|
- Approach A: 1000+ instance traversal on each drop
|
||||||
|
- Approach B: Single hash table insertion/lookup
|
||||||
|
|
||||||
|
## 4. Maintenance Complexity
|
||||||
|
- Approach A: Complex global state, threading issues, lifecycle management
|
||||||
|
- Approach B: Simple addition to existing interpreter state
|
||||||
|
|
||||||
|
【Specific Technical Questions】
|
||||||
|
|
||||||
|
1. **Performance Reality Check**: In a native-compiled language, is O(n) weak reference invalidation acceptable for real applications?
|
||||||
|
|
||||||
|
2. **Lazy vs Eager Trade-off**: Is "on-access invalidation" a viable pattern for systems programming? What are the hidden costs?
|
||||||
|
|
||||||
|
3. **Native Compilation Compatibility**: Which approach translates better to efficient native code generation?
|
||||||
|
|
||||||
|
4. **Memory Safety Guarantee**: Do both approaches provide equivalent memory safety guarantees?
|
||||||
|
|
||||||
|
5. **Industry Best Practices**: How do modern systems languages (Rust, Swift, etc.) handle this problem?
|
||||||
|
|
||||||
|
【Nyash Context】
|
||||||
|
- Everything is Box philosophy (unified object model)
|
||||||
|
- Target: P2P networking applications (performance-sensitive)
|
||||||
|
- Native compilation planned (MIR → LLVM/Cranelift)
|
||||||
|
- Developer experience priority (simplicity over theoretical perfection)
|
||||||
|
|
||||||
|
【Request】
|
||||||
|
Please provide expert analysis focusing on:
|
||||||
|
1. Real-world performance implications for native compilation
|
||||||
|
2. Hidden complexity costs of each approach
|
||||||
|
3. Recommendation for foundational language infrastructure
|
||||||
|
4. Risk assessment for future scaling
|
||||||
|
|
||||||
|
This decision affects the entire language's memory management foundation. I need the most technically sound recommendation that balances correctness, performance, and maintainability.
|
||||||
|
|
||||||
|
Thank you for your expertise!
|
||||||
2
check_error.sh
Normal file
2
check_error.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cargo check 2>&1 | grep -B2 -A2 "unresolved import"
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
Nyashプログラミング言語のコンストラクタ設計について深い相談です。
|
||||||
|
|
||||||
|
【Nyashの現在の設計哲学】
|
||||||
|
Nyashは既に「コンストラクタの明示的呼び出し」を採用しています。これは以下の理由によるものです:
|
||||||
|
- 明示性重視:プログラマーが何が起きているかを隠さない
|
||||||
|
- 初学者フレンドリー:実行順序が直感的
|
||||||
|
- Everything is Box哲学:隠れた魔法的な動作を避ける
|
||||||
|
|
||||||
|
【他言語の問題例】
|
||||||
|
```cpp
|
||||||
|
// C++:複雑で読みにくい
|
||||||
|
class Cat : public Animal {
|
||||||
|
Toy catToy; // 1. 隠れたメンバー初期化
|
||||||
|
Cat(string name) : Animal(name) { // 2. : Animal(name) が直感的でない
|
||||||
|
// 3. 最後に自分の処理
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
【現在のNyash vs 新提案】
|
||||||
|
```nyash
|
||||||
|
// 現在の書き方
|
||||||
|
box MeshNode : P2PBox {
|
||||||
|
constructor(nodeId, world) {
|
||||||
|
super P2PBox(nodeId, world) // 特別なキーワード
|
||||||
|
me.routing = RoutingTable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新提案:完全統一
|
||||||
|
box MeshNode : P2PBox {
|
||||||
|
constructor(nodeId, world) {
|
||||||
|
from P2PBox.constructor(nodeId, world) // from統一!
|
||||||
|
me.routing = RoutingTable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
【完全統一のメリット】
|
||||||
|
- from P2PBox.method() と完全に一貫している
|
||||||
|
- 「どの親の何を呼んでいるか」が超明確
|
||||||
|
- 多重デリゲーションでも from Logger.constructor() で区別可能
|
||||||
|
|
||||||
|
【深く考えてほしい点】
|
||||||
|
1. Nyashの明示的コンストラクタ呼び出し設計をどう評価しますか?
|
||||||
|
2. from P2PBox.constructor() の完全統一案をどう思いますか?
|
||||||
|
3. 他言語(Java, Python, C#等)と比較したNyashの優位性は?
|
||||||
|
4. 初学者にとって最も理解しやすい設計は?
|
||||||
|
5. 言語の美しさ・一貫性の観点からの評価は?
|
||||||
|
|
||||||
|
プログラミング言語設計の専門的視点から、深く分析してください。
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
Nyashプログラミング言語のオーバーライド設計について深い相談です。
|
||||||
|
|
||||||
|
【現在発見された実装問題】
|
||||||
|
現在のNyashでは HashMap::insert により「暗黙のオーバーライド」が発生している:
|
||||||
|
```rust
|
||||||
|
// instance.rs - add_method関数
|
||||||
|
pub fn add_method(&mut self, method_name: String, method_ast: ASTNode) {
|
||||||
|
let mut new_methods = (*self.methods).clone();
|
||||||
|
new_methods.insert(method_name, method_ast); // ← 同名で上書き!
|
||||||
|
self.methods = Arc::new(new_methods);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
これにより以下が可能になってしまっている:
|
||||||
|
```nyash
|
||||||
|
box Node {
|
||||||
|
send(msg) { // 最初の定義
|
||||||
|
print("Version 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
send(msg) { // 暗黙に上書きされる
|
||||||
|
print("Version 2") // ← こちらだけが残る
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
【Nyashの設計哲学との矛盾】
|
||||||
|
- **明示性重視**: 何が起きているかを隠さない
|
||||||
|
- **Everything is Box**: 統一された世界観
|
||||||
|
- **from デリゲーション**: `from Parent.method()` の明示的呼び出し
|
||||||
|
- **初学者フレンドリー**: 複雑な概念を分かりやすく表現
|
||||||
|
|
||||||
|
【提案する修正方針】
|
||||||
|
|
||||||
|
**1. 暗黙のオーバーライドを完全禁止**
|
||||||
|
```nyash
|
||||||
|
box Node {
|
||||||
|
send(msg) {
|
||||||
|
print("Version 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
send(msg) { // ← コンパイルエラーにする
|
||||||
|
print("Version 2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Error: Method 'send' is already defined. Use 'override' keyword if intentional.
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. コンストラクタのオーバーロード禁止**
|
||||||
|
```nyash
|
||||||
|
box Node {
|
||||||
|
constructor(id) {
|
||||||
|
me.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(id, name) { // ← エラーにする
|
||||||
|
me.id = id
|
||||||
|
me.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Error: Constructor overloading is not allowed. Use explicit initialization.
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. デリゲーションでの明示的override**
|
||||||
|
```nyash
|
||||||
|
box MeshNode : P2PBox {
|
||||||
|
// 明示的にオーバーライドする意図を示す
|
||||||
|
override send(intent, data, target) {
|
||||||
|
me.routing.log(target)
|
||||||
|
from P2PBox.send(intent, data, target) // 親の実装も呼べる
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新しいメソッド(overrideなし)
|
||||||
|
sendWithRetry(intent, data, target) {
|
||||||
|
// 新機能
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. エラーメッセージの改善**
|
||||||
|
- 重複定義時: "Method 'send' already exists. Use 'override' if you want to replace parent method."
|
||||||
|
- override不正使用時: "Method 'newMethod' does not exist in parent. Remove 'override' keyword."
|
||||||
|
|
||||||
|
【深く考えてほしい点】
|
||||||
|
|
||||||
|
**1. 哲学的整合性**
|
||||||
|
- この方針はNyashの「明示性重視」「Everything is Box」哲学と整合しますか?
|
||||||
|
- `from Parent.method()` デリゲーション設計との相性は?
|
||||||
|
|
||||||
|
**2. 学習コスト vs 安全性**
|
||||||
|
- `override` キーワード追加による学習コストは妥当ですか?
|
||||||
|
- 暗黙のオーバーライド禁止により、どの程度安全性が向上しますか?
|
||||||
|
|
||||||
|
**3. デリゲーションとの関係**
|
||||||
|
- デリゲーション先メソッドを `override` するのは自然ですか?
|
||||||
|
- 多重デリゲーション時の `override` はどう扱うべきですか?
|
||||||
|
|
||||||
|
**4. 実装上の課題**
|
||||||
|
- コンパイル時の重複チェック実装の複雑度は?
|
||||||
|
- 既存コードへの影響と移行戦略は?
|
||||||
|
|
||||||
|
**5. 他言語との比較優位性**
|
||||||
|
- Java/C#の `@Override` や TypeScript の `override` との違いは?
|
||||||
|
- Nyashならではの独自価値は何ですか?
|
||||||
|
|
||||||
|
プログラミング言語設計の専門的視点から、この方針がNyashの目指す「明示的で安全、かつ初学者フレンドリーな言語」に最適かどうか深く分析してください。
|
||||||
56
docs/chatgpt5/インタープリタ評価.txt
Normal file
56
docs/chatgpt5/インタープリタ評価.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
Nyash Interpreter Assessment (Current Strengths, Weaknesses, Direction)
|
||||||
|
|
||||||
|
Strengths
|
||||||
|
- Everything is Box: 統一データモデルで生成/代入/比較/解放が一貫。学習・読解が容易。
|
||||||
|
- Explicit lifecycle: init/fini/weak/スコープ解放を構文で規約化。解放点が読み取れる。
|
||||||
|
- Cycles solved pragmatically: init { weak ... } + 自動nil化で双方向参照を安全に扱える。
|
||||||
|
- Delegation-first: from(多重対応)+ override必須で明示合成。暗黙解決を排しテスト容易。
|
||||||
|
- Rust core: Arc<Mutex<...>>/Weak、BoxFinalizer、二重解放防止など堅牢な実装基盤。
|
||||||
|
- Dev UX: 明示変数宣言、単一ループ構文、static box Mainでコード規律が単純。
|
||||||
|
- Repro: WASM Playgroundでゼロインストール再現(docs/chatgpt5/PLAYGROUND_GUIDE.md)。
|
||||||
|
|
||||||
|
Weaknesses
|
||||||
|
- Mixed field models: fields(レガシー)と fields_ng(次世代)が併存し、理解/実装が複雑。
|
||||||
|
- Weak shim leakage: 一部weakを文字列マーカーで代替(set_weak_field_from_legacy)。完全WeakBox化が未完。
|
||||||
|
- Builtin gaps: Math/Float/Intent/P2P周辺に未実装・登録不足が残る。
|
||||||
|
- P2P disabled path: インタープリタ内のP2P呼び出しが一時無効化で連携が途切れがち。
|
||||||
|
- Verbose debug: 実行時eprintlnが多くノイズ。ログレベル切替が未整備。
|
||||||
|
- Multi-delegation policy: 競合解決の仕様/診断が未完成でユーザーが迷う余地。
|
||||||
|
|
||||||
|
Current Limitations
|
||||||
|
- Determinism vs sharing: finiは解放フックだが強参照が残る場合は実体が残存。期待との齟齬可能性あり。
|
||||||
|
- Error surfacing: RuntimeErrorのSpan拡張が全コードパスで統一されていない。
|
||||||
|
- Perf visibility: ベンチ/メトリクス不足。weak upgradeやfini回数の観測が難しい。
|
||||||
|
- WASM behavior: ブラウザでのタイミング/ログ表示がネイティブと異なる場合あり。
|
||||||
|
|
||||||
|
Direction
|
||||||
|
- Product-first clarity: 「迷わない規約」を前面に。実用性と予測可能性を訴求。
|
||||||
|
- Unify field storage: fields_ngへ一本化し、WeakBoxをエンドツーエンドで運用。
|
||||||
|
- Delegation doctrine: 多重デリゲーション競合のポリシー(優先/明示/エラー)を明文化・実装。
|
||||||
|
- Measurable DX: Playgroundでfini回数/weak upgrade成功・失敗を可視化して説得力向上。
|
||||||
|
- Complete builtins: Float/Math/Intent/P2Pの未完箇所を段階的に充足し、テストで裏付け。
|
||||||
|
|
||||||
|
High-Impact Next Steps
|
||||||
|
- WeakBox E2E完了: 文字列マーカー廃止→NyashValue::WeakBoxで統一。テスト追加。
|
||||||
|
- Assignment safety audit: 再代入→fini→weak自動nil化の一連を網羅試験(成功/競合/例外)。
|
||||||
|
- Multi-delegation conflicts: 明示親指定必須・曖昧時はエラー+提案を実装。エラーメッセージ改善。
|
||||||
|
- P2P経路の復活: expressions.rsのP2P呼び出しを段階的に再有効化。Intentアクセサ整備。
|
||||||
|
- Debug levels: ログレベル導入(環境変数/DebugBox)でノイズ削減と計測を両立。
|
||||||
|
- Playground強化: 3シナリオにメトリクス表示(fini総数、weak失敗数、簡易時間)。
|
||||||
|
|
||||||
|
Risks / Trade-offs
|
||||||
|
- Perception risk: finiを「即時破棄」と誤解される恐れ。共有参照残存の挙動を明文化要。
|
||||||
|
- Dual-storage complexity: レガシー/次世代の二重管理期間にバグ混入リスク。
|
||||||
|
- Performance cliffs: 過度なMutexロック/頻繁なupgradeがホットパスで効く可能性。測定・キャッシュ要検討。
|
||||||
|
- WASM differences: ブラウザでのタイミング/ログ/スレッド制約がネイティブと異なる。
|
||||||
|
|
||||||
|
Stretch Ideas
|
||||||
|
- Static analysis: init/weakの静的検証、循環参照ヒント、未宣言代入の修正提案(LSP連携)。
|
||||||
|
- Conflict DSL: 多重デリゲーション競合を宣言で解決できる軽量DSL導入。
|
||||||
|
- Tracing viz: weak生死・finiイベントのタイムライン可視化(Playground連携)。
|
||||||
|
- Packages/templates: 標準Boxとテンプレート(ゲーム/アート/教育)で“動く最小”を量産。
|
||||||
|
|
||||||
|
Summary
|
||||||
|
統一モデルと明示規約で日常のメモリ管理を楽にする点が最大の強み。短期はWeakの完全統一とデモ/数値の可視化に集中し、
|
||||||
|
多重デリゲーションの競合仕様や未完Boxを段階的に整備するのが最も効果的。
|
||||||
|
|
||||||
102
docs/chatgpt5/プレイグラウンド_ガイド.md
Normal file
102
docs/chatgpt5/プレイグラウンド_ガイド.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Nyash Playground Guide(ブラウザデモ活用ガイド)
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
## リンク
|
||||||
|
- Playground: https://moe-charm.github.io/nyash/projects/nyash-wasm/nyash_playground.html
|
||||||
|
|
||||||
|
## ねらい
|
||||||
|
- 言語の要点(init/fini/weak/スコープ解放)を“動く例”で体感
|
||||||
|
- レビュワーやチームへの共有・再現を容易化(ゼロインストール)
|
||||||
|
|
||||||
|
## 使い方(最短)
|
||||||
|
1) 上記リンクを開く
|
||||||
|
2) 下のサンプルコードをコピー&ペースト
|
||||||
|
3) Run/実行ボタンで結果確認(ログ・出力・エラー挙動)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## シナリオ1: 循環参照 vs weak(自動nil化)
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
# Parent↔Child の双方向参照。
|
||||||
|
# 子→親は weak 参照にして、リークとダングリングを防ぐ。
|
||||||
|
|
||||||
|
box Parent {
|
||||||
|
init { child }
|
||||||
|
pack() {
|
||||||
|
me.child = new Child()
|
||||||
|
me.child.setParent(me)
|
||||||
|
}
|
||||||
|
getName() { return "P" }
|
||||||
|
fini() { print("Parent.fini") }
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { weak parent }
|
||||||
|
setParent(p) { me.parent = p }
|
||||||
|
show() {
|
||||||
|
if (me.parent != null) { print("parent=" + me.parent.getName()) }
|
||||||
|
else { print("parent is gone") }
|
||||||
|
}
|
||||||
|
fini() { print("Child.fini") }
|
||||||
|
}
|
||||||
|
|
||||||
|
p = new Parent()
|
||||||
|
p.child.show() # => parent=P
|
||||||
|
|
||||||
|
# 親を明示的に破棄(fini 呼出しが発火する環境であればここで解放)
|
||||||
|
p.fini()
|
||||||
|
|
||||||
|
# 親が破棄済みなので、weak 参照は自動的に nil 化される
|
||||||
|
p.child.show() # => parent is gone(想定)
|
||||||
|
```
|
||||||
|
|
||||||
|
ポイント:
|
||||||
|
- `init { weak parent }`で弱参照を宣言
|
||||||
|
- 参照先が破棄されるとアクセス時に自動で`null`扱い
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## シナリオ2: 再代入時の fini 発火(予備解放)
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
box Holder { init { obj } }
|
||||||
|
box Thing { fini() { print("Thing.fini") } }
|
||||||
|
|
||||||
|
h = new Holder()
|
||||||
|
h.obj = new Thing()
|
||||||
|
h.obj = new Thing() # 旧 obj に対して fini() が呼ばれる(ログで確認)
|
||||||
|
```
|
||||||
|
|
||||||
|
ポイント:
|
||||||
|
- フィールド再代入の節目で `fini()` が自動呼出し
|
||||||
|
- 二重解放は内部で抑止(安全側)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## シナリオ3: スコープ抜けでローカル解放
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
function make() {
|
||||||
|
local t
|
||||||
|
t = new Thing()
|
||||||
|
# 関数を抜けるとスコープ追跡により t が解放される
|
||||||
|
}
|
||||||
|
|
||||||
|
box Thing { fini() { print("Thing.fini (scope)") } }
|
||||||
|
|
||||||
|
make() # => Thing.fini (scope)
|
||||||
|
```
|
||||||
|
|
||||||
|
ポイント:
|
||||||
|
- `local`で宣言された変数はスコープ終了時に一括解放
|
||||||
|
- 暗黙ではなく構文規約で明示(未宣言代入はエラー)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips(レビュー/論文向け)
|
||||||
|
- 論文やREADMEから本ガイドへリンクし、コピー&ペーストで再現
|
||||||
|
- 期待ログ(例: `Thing.fini`)を明記して、挙動の確認を容易に
|
||||||
|
- 比較のため「weakなし版」と「weakあり版」を並記
|
||||||
|
|
||||||
65
docs/chatgpt5/プレイグラウンド_サンプル.md
Normal file
65
docs/chatgpt5/プレイグラウンド_サンプル.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Playground Samples(コピー&ペースト用サンプル)
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
Playground: https://moe-charm.github.io/nyash/projects/nyash-wasm/nyash_playground.html
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1) 循環参照 vs weak(自動nil化)
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
box Parent {
|
||||||
|
init { child }
|
||||||
|
pack() {
|
||||||
|
me.child = new Child()
|
||||||
|
me.child.setParent(me)
|
||||||
|
}
|
||||||
|
getName() { return "P" }
|
||||||
|
fini() { print("Parent.fini") }
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { weak parent }
|
||||||
|
setParent(p) { me.parent = p }
|
||||||
|
show() {
|
||||||
|
if (me.parent != null) { print("parent=" + me.parent.getName()) }
|
||||||
|
else { print("parent is gone") }
|
||||||
|
}
|
||||||
|
fini() { print("Child.fini") }
|
||||||
|
}
|
||||||
|
|
||||||
|
p = new Parent()
|
||||||
|
p.child.show() # => parent=P
|
||||||
|
p.fini() # 親を破棄
|
||||||
|
p.child.show() # => parent is gone(想定)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2) 再代入時の fini 発火(予備解放)
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
box Holder { init { obj } }
|
||||||
|
box Thing { fini() { print("Thing.fini") } }
|
||||||
|
|
||||||
|
h = new Holder()
|
||||||
|
h.obj = new Thing()
|
||||||
|
h.obj = new Thing() # 旧 obj に対して fini() が呼ばれる
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3) スコープ抜けでローカル解放
|
||||||
|
|
||||||
|
```nyash
|
||||||
|
function make() {
|
||||||
|
local t
|
||||||
|
t = new Thing()
|
||||||
|
}
|
||||||
|
|
||||||
|
box Thing { fini() { print("Thing.fini (scope)") } }
|
||||||
|
|
||||||
|
make() # => Thing.fini (scope)
|
||||||
|
```
|
||||||
|
|
||||||
31
docs/chatgpt5/実装TODO_解放とガード.txt
Normal file
31
docs/chatgpt5/実装TODO_解放とガード.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Implementation TODOs: Finalization & Guards
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
Scope: src/instance.rs, src/interpreter/{core,expressions,statements}.rs, parser
|
||||||
|
|
||||||
|
1) InstanceBox::fini() の強化(src/instance.rs)
|
||||||
|
- 状態機械: in_finalization(再入防止)→ finalized。
|
||||||
|
- 再帰: init 強参照フィールドを走査し、未処理の子 Instance に対して finalize。weak は対象外。
|
||||||
|
- クリア: 全フィールドクリア、finalized = true。
|
||||||
|
- 無害化: 二重呼び出しは no-op。
|
||||||
|
|
||||||
|
2) 使用禁止ガード(実行時)
|
||||||
|
- expressions.rs: メソッド呼び出し前に instance.is_finalized() をチェック→エラー。
|
||||||
|
- statements.rs: フィールド代入/アクセス時にチェック→エラー。
|
||||||
|
- core.rs: 必要なら共通ヘルパーで一元化。
|
||||||
|
|
||||||
|
3) weak への fini 禁止(静的検出+実行時フォールバック)
|
||||||
|
- parser: AST 上で fini() 呼び出しを検出し、対象が weak フィールドならビルドエラーに。
|
||||||
|
- 実行時: 保険として expressions.rs で weak フィールド経由の fini 呼び出しを拒否。
|
||||||
|
|
||||||
|
4) 例外方針とログ
|
||||||
|
- ユーザー fini() で例外→自動カスケードは続行。最後に集約報告。
|
||||||
|
- ログレベル: デバッグ時のみ詳細(upgrade失敗、already finalized等)。
|
||||||
|
|
||||||
|
5) Playground 可視化(別PR)
|
||||||
|
- fini 回数、Finalizing→Finalized遷移、weak upgrade失敗数をUI表示。
|
||||||
|
|
||||||
|
6) ドキュメント反映(実装後)
|
||||||
|
- LANGUAGE_GUIDE / reference へ最終ルール・エラーメッセージ・サンプルを移植。
|
||||||
|
|
||||||
92
docs/chatgpt5/実装計画_fini統合.txt
Normal file
92
docs/chatgpt5/実装計画_fini統合.txt
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
Implementation Plan: Finalization Policy Integration (fini)
|
||||||
|
|
||||||
|
Last updated: 2025-08-13
|
||||||
|
|
||||||
|
Goals
|
||||||
|
- Default: Auto-finalize strong fields in init declaration order.
|
||||||
|
- Custom: User-defined fini() can implement any order and additional cleanup.
|
||||||
|
- Remainder: Auto-cascade finalization for strong fields not handled in user fini().
|
||||||
|
- Prohibit: Calling fini() on weak fields (non-owning).
|
||||||
|
- Guard: Forbid any use after finalized (errors), idempotent fini().
|
||||||
|
|
||||||
|
Touched code (planned)
|
||||||
|
- src/instance.rs (core: InstanceBox state + fini strengthen)
|
||||||
|
- src/interpreter/objects.rs (construct InstanceBox with needed metadata)
|
||||||
|
- src/interpreter/expressions.rs (method/field guards, weak-fini runtime check)
|
||||||
|
- src/interpreter/statements.rs (assignment guards)
|
||||||
|
- parser (optional later: static detection of weak-fini inside user fini())
|
||||||
|
|
||||||
|
1) InstanceBox: add metadata and strengthen fini()
|
||||||
|
- Add fields:
|
||||||
|
- init_field_order: Vec<String>
|
||||||
|
Purpose: deterministic auto-cascade order (includes inherited fields).
|
||||||
|
- weak_fields_union: std::collections::HashSet<String>
|
||||||
|
Purpose: fast check to skip weak fields in auto-cascade (includes parents’ weak fields).
|
||||||
|
- in_finalization: bool
|
||||||
|
Purpose: prevent re-entrancy; together with existing finalized flag.
|
||||||
|
- Constructor changes:
|
||||||
|
- InstanceBox::new(class_name: String, all_fields: Vec<String>, methods: HashMap<String, ASTNode>,
|
||||||
|
weak_fields_union: HashSet<String>)
|
||||||
|
Set init_field_order = all_fields; weak_fields_union = provided; in_finalization = false.
|
||||||
|
- Strengthen InstanceBox::fini():
|
||||||
|
- if finalized => return Ok(()) (idempotent)
|
||||||
|
- set in_finalization = true
|
||||||
|
- (User-defined fini() body is executed by interpreter before calling this method; keep that flow)
|
||||||
|
- Auto-cascade: for each field in init_field_order
|
||||||
|
- if field in weak_fields_union => skip
|
||||||
|
- get current field value; if InstanceBox => child.fini() (idempotent)
|
||||||
|
- Clear all fields; set finalized = true; set in_finalization = false; return Ok(())
|
||||||
|
|
||||||
|
2) objects.rs: pass metadata at construction time
|
||||||
|
- Location: src/interpreter/objects.rs, execute_new() / resolve_inheritance()
|
||||||
|
- Already computes `all_fields` via resolve_inheritance(). Use as init_field_order.
|
||||||
|
- Implement helper union_weak_fields(box_decl: &BoxDeclaration) -> HashSet<String>
|
||||||
|
- Traverse current box_decl and recursively parents (extends) to collect weak fields.
|
||||||
|
- Call: InstanceBox::new(actual_class_name, all_fields, all_methods, weak_fields_union)
|
||||||
|
|
||||||
|
3) Runtime guards and weak-fini prohibition (expressions.rs/statements.rs)
|
||||||
|
- Method calls (src/interpreter/expressions.rs::execute_method_call)
|
||||||
|
- If target is InstanceBox and method != "fini":
|
||||||
|
- if instance.is_finalized() => error: "Instance was finalized; further use is prohibited"
|
||||||
|
- If method == "fini":
|
||||||
|
- If object AST is FieldAccess/ThisField/MeField, resolve owner + field name; if field is weak (by box_decl.weak_fields) => error: "Cannot finalize weak field '<name>' (non-owning reference)"
|
||||||
|
- Else proceed with current special fini handling (user body execution) then call instance.fini()
|
||||||
|
- Field access (execute_field_access)
|
||||||
|
- If owner InstanceBox is finalized => error as above
|
||||||
|
- Assignments (src/interpreter/statements.rs)
|
||||||
|
- For FieldAccess/ThisField/MeField targets: if owner InstanceBox is finalized => error
|
||||||
|
|
||||||
|
4) Parser (optional, later)
|
||||||
|
- Static detection inside user-defined fini() body:
|
||||||
|
- Walk AST; detect `me.<weak_field>.fini()` and emit build-time error.
|
||||||
|
- Runtime check remains as fallback for dynamic flows.
|
||||||
|
|
||||||
|
Important decisions
|
||||||
|
- Do not track "handled-by-user-fini" set. Rely on idempotent child.fini(). This keeps implementation simple and safe.
|
||||||
|
- Ensure weak_fields_union includes parents to avoid accidentally finalizing weak fields inherited from parents.
|
||||||
|
|
||||||
|
Tests (to add/verify)
|
||||||
|
- Reassignment: old value’s fini() is called exactly once; Thing.fini counter.
|
||||||
|
- Weak prohibition: `me.weakField.fini()` raises error (runtime; later build-time).
|
||||||
|
- Custom order: User fini closes r3->r2, auto cascade closes remaining r1.
|
||||||
|
- Finalized guard: method call / field access / assignment after fini => error.
|
||||||
|
- Cycles: Parent<->Child (Child weak parent); Parent.fini() => Child’s parent becomes null on access (lazy nilification), no leaks.
|
||||||
|
|
||||||
|
Rollout order
|
||||||
|
1. InstanceBox fields + fini strengthen (core).
|
||||||
|
2. Interpreter guards (method/field/assignment).
|
||||||
|
3. Weak-fini runtime prohibition via AST check.
|
||||||
|
4. Tests and sample updates (docs/chatgpt5/finalization_examples.txt cases).
|
||||||
|
5. Optional: parser build-time detection.
|
||||||
|
|
||||||
|
Risks and mitigations
|
||||||
|
- Re-entrancy: guarded by in_finalization + idempotent finalized flag.
|
||||||
|
- Performance: auto-cascade per field; usually shallow; child.fini idempotent avoids repeated heavy work.
|
||||||
|
- Compatibility: InstanceBox::new signature change; update all call sites (objects.rs, core.rs statics/global creations).
|
||||||
|
- UX: Clear error messages as documented in docs/chatgpt5/finalization_errors.txt.
|
||||||
|
|
||||||
|
Future enhancements (optional)
|
||||||
|
- Attribute `@no_auto_finalize` to exclude fields from auto-cascade when fully managed in user fini().
|
||||||
|
- FinalizationContext injected into user fini() for safe, limited operations.
|
||||||
|
- Debug mode: eager weak invalidation at finalize time for visualization.
|
||||||
|
|
||||||
63
docs/chatgpt5/解放ポリシー_fini.txt
Normal file
63
docs/chatgpt5/解放ポリシー_fini.txt
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
Nyash Finalization Policy (fini as destructor-style method)
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
目的
|
||||||
|
- fini を「フィールド列挙」ではなく「通常のメソッド本体(デストラクタ的)」として運用しつつ、
|
||||||
|
自動カスケード解放(init フィールドの残り処理)と整合する最終ルールを定義する。
|
||||||
|
|
||||||
|
設計方針(合意)
|
||||||
|
- すべての Box は論理的に fini() を持つ(ユーザー未定義でもシステム既定が働く)。
|
||||||
|
- fini() は“論理的解放”のフックであり、以後の使用は禁止(finalized)。
|
||||||
|
- weak フィールドは所有権を持たないため、自動の fini 対象にしない(アクセス時の upgrade 失敗で null)。
|
||||||
|
|
||||||
|
実行順序(最終)
|
||||||
|
1) 既に finalized なら何もしない(idempotent)。
|
||||||
|
2) 再入防止のため in_finalization フラグを立てる(finalized はまだ立てない)。
|
||||||
|
3) ユーザー定義 fini() 本体があれば実行(この間、フィールドアクセス/メソッド呼び出しは許可)。
|
||||||
|
4) 自動カスケード解放:init{ ... } に宣言された強参照フィールドのうち、
|
||||||
|
- ユーザー fini() 本体で明示的に処理されなかった“残り”に対して、宣言順で child.fini() を呼ぶ。
|
||||||
|
- weak 修飾フィールドは対象外。
|
||||||
|
5) 全フィールドをクリアし finalized フラグを立てる(以後の使用は禁止)。
|
||||||
|
6) 再入フラグを下ろして終了。
|
||||||
|
|
||||||
|
使用禁止ガード
|
||||||
|
- finalized 後の操作はエラーとする:
|
||||||
|
- メソッド呼び出し、フィールドアクセス/代入、デリゲーション経由の呼び出し等。
|
||||||
|
- 推奨メッセージ:"Instance was finalized; further use is prohibited"。
|
||||||
|
- idempotent な fini() の再呼び出しのみ許容(無害化)。
|
||||||
|
|
||||||
|
補足
|
||||||
|
- ユーザー定義 fini() 内で解放順序が必要な場合は、自由に child.fini() を呼べる(柔軟性)。
|
||||||
|
- その後に“残り”が自動処理されるため、完全手動にしたい場合は将来的に属性(例:@no_auto_finalize)導入を検討(現段階は自動処理ありを既定)。
|
||||||
|
- 例外発生時はベストエフォートで自動カスケードとクリアを続行(安全側)。
|
||||||
|
|
||||||
|
weak の取り扱い
|
||||||
|
- weak はアクセス時に upgrade/失敗で null となる(lazy nilification)。
|
||||||
|
- デバッグ用途として finalize 時に weak を即時無効化する eager モードを将来オプションで検討可(既定は lazy)。
|
||||||
|
|
||||||
|
禁止事項と診断(weak に対する fini 呼び出し)
|
||||||
|
- ルール: weak 修飾フィールドは所有権を持たないため、`me.<weak_field>.fini()` のような直接の fini 呼び出しを禁止する。
|
||||||
|
- 推奨診断レベル: ビルド(解析)時エラー。
|
||||||
|
- 推奨エラーメッセージ: "Cannot finalize weak field '<name>' (non-owning reference). Use null assignment or let it lazily nilify."
|
||||||
|
- 実装補足: 静的解析で `fini()` 本体内のフィールド呼び出しを走査し、対象が weak に該当すればエラー。検出困難な動的経路は実行時にもエラーを返す。
|
||||||
|
- 推奨代替手段: `me.<weak_field> = null`(参照解除)/アクセス時の自動 nil 化に任せる。
|
||||||
|
|
||||||
|
簡易疑似コード
|
||||||
|
fn finalize(instance):
|
||||||
|
if instance.finalized: return
|
||||||
|
instance.in_finalization = true
|
||||||
|
if has_user_fini(instance):
|
||||||
|
run_user_fini_body(instance)
|
||||||
|
for field in instance.init_fields:
|
||||||
|
if is_strong_ref(field) and not handled_in_user_fini(field):
|
||||||
|
if is_instance(field.value) and not field.value.finalized:
|
||||||
|
finalize(field.value)
|
||||||
|
clear_all_fields(instance)
|
||||||
|
instance.finalized = true
|
||||||
|
instance.in_finalization = false
|
||||||
|
|
||||||
|
期待する効果
|
||||||
|
- 柔軟性:ユーザー fini() 本体で任意順序・任意処理が書ける。
|
||||||
|
- 決定性:残りは init 宣言順で自動解放され、毎回同じ順に実行。
|
||||||
|
- 明確性:finalized 後は使用禁止をガードで強制、誤用を早期検知。
|
||||||
39
docs/chatgpt5/解放ポリシー_エラーと診断.txt
Normal file
39
docs/chatgpt5/解放ポリシー_エラーと診断.txt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
Nyash Finalization Errors and Diagnostics
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
1) 使用禁止エラー(finalized 後の操作)
|
||||||
|
---------------------------------------
|
||||||
|
Message: "Instance was finalized; further use is prohibited"
|
||||||
|
When: finalized フラグが立ったインスタンスに対して、
|
||||||
|
- メソッド呼び出し
|
||||||
|
- フィールドアクセス/代入
|
||||||
|
- デリゲーション経由の呼び出し
|
||||||
|
を行った場合。
|
||||||
|
Notes: toString 相当も原則禁止(方針次第)。まずは全面禁止が明快。
|
||||||
|
|
||||||
|
2) weak に対する fini 呼び出し(禁止)
|
||||||
|
---------------------------------------
|
||||||
|
Message (build-time preferred):
|
||||||
|
"Cannot finalize weak field '<name>' (non-owning reference)."
|
||||||
|
Message (runtime fallback):
|
||||||
|
"Finalization of non-owning (weak) reference is not allowed: '<name>'"
|
||||||
|
When: `init { weak <name> }` で宣言されたフィールドに対して `fini()` を直接呼んだ場合。
|
||||||
|
Fix: `me.<name> = null`(参照解除) or 自動 nil 化に任せる。
|
||||||
|
|
||||||
|
3) 二重解放の抑止(無害化)
|
||||||
|
---------------------------------------
|
||||||
|
Behavior: 2回目以降の `fini()` 呼出しは no-op。
|
||||||
|
Notes: ログに "already finalized" を出すかは運用ポリシー次第。
|
||||||
|
|
||||||
|
4) 自動カスケード中の例外
|
||||||
|
---------------------------------------
|
||||||
|
Policy: ベストエフォートで残りの解放を継続、最後にまとめて報告(fail-safe)。
|
||||||
|
Message example:
|
||||||
|
"Finalization encountered errors; see aggregated report (N failures)."
|
||||||
|
|
||||||
|
5) 解析時の注意(推奨)
|
||||||
|
---------------------------------------
|
||||||
|
- fini() 本体内でのフィールド fini 呼び出しは静的解析で走査し、weak を検知したらビルドエラーへ。
|
||||||
|
- 明示属性 `@no_auto_finalize`(将来案)を付与したフィールドは自動カスケード対象から除外。
|
||||||
|
|
||||||
73
docs/chatgpt5/解放ポリシー_例.txt
Normal file
73
docs/chatgpt5/解放ポリシー_例.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
Nyash Finalization Examples
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
1) 既定: init 宣言順での解放(強参照のみ)
|
||||||
|
--------------------------------------------------
|
||||||
|
box A { fini() { print("A.fini") } }
|
||||||
|
box B { fini() { print("B.fini") } }
|
||||||
|
|
||||||
|
box Holder {
|
||||||
|
init { a, b, weak c }
|
||||||
|
}
|
||||||
|
|
||||||
|
h = new Holder()
|
||||||
|
h.a = new A()
|
||||||
|
h.b = new B()
|
||||||
|
# h.c は weak なので対象外
|
||||||
|
|
||||||
|
# h.fini() を呼ぶと:
|
||||||
|
# 1) ユーザー定義 fini() があれば先に実行
|
||||||
|
# 2) 残りは init の宣言順に a → b の順で child.fini()
|
||||||
|
# 3) フィールドクリア → finalized
|
||||||
|
|
||||||
|
|
||||||
|
2) カスタム順序: ユーザー定義 fini() で順序制御
|
||||||
|
--------------------------------------------------
|
||||||
|
box Resource { init { name } fini() { print("close:" + me.name) } }
|
||||||
|
|
||||||
|
box Pipeline {
|
||||||
|
init { r1, r2, r3 }
|
||||||
|
fini() {
|
||||||
|
# 依存性の都合で r3 → r2 → r1 の順に閉じたい
|
||||||
|
if me.r3 != null { me.r3.fini() }
|
||||||
|
if me.r2 != null { me.r2.fini() }
|
||||||
|
# r1 は明示しない → 自動カスケードで最後に閉じられる
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = new Pipeline()
|
||||||
|
p.r1 = new Resource("r1")
|
||||||
|
p.r2 = new Resource("r2")
|
||||||
|
p.r3 = new Resource("r3")
|
||||||
|
p.fini()
|
||||||
|
# 期待: close:r3 → close:r2 → close:r1 の順
|
||||||
|
|
||||||
|
|
||||||
|
3) 弱参照は対象外(禁止パターン)
|
||||||
|
--------------------------------------------------
|
||||||
|
box Parent { init { weak child } fini() {
|
||||||
|
# NG: 非所有参照のため fini は禁止
|
||||||
|
# me.child.fini() # → ビルド時エラー(推奨):Cannot finalize weak field 'child'
|
||||||
|
# 代替: 参照解除
|
||||||
|
me.child = null
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
4) 再代入での予備解放
|
||||||
|
--------------------------------------------------
|
||||||
|
box Thing { fini() { print("Thing.fini") } }
|
||||||
|
box Holder { init { obj } }
|
||||||
|
|
||||||
|
h = new Holder()
|
||||||
|
h.obj = new Thing()
|
||||||
|
h.obj = new Thing() # → 旧 obj に対して自動的に fini()
|
||||||
|
|
||||||
|
|
||||||
|
5) finalized 後の使用禁止
|
||||||
|
--------------------------------------------------
|
||||||
|
box X { }
|
||||||
|
x = new X()
|
||||||
|
x.fini()
|
||||||
|
x.doSomething() # → 実行時エラー: Instance was finalized; further use is prohibited
|
||||||
|
|
||||||
94
docs/chatgpt5/設計RFC_多重デリゲーションとfini.txt
Normal file
94
docs/chatgpt5/設計RFC_多重デリゲーションとfini.txt
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
Nyash 設計検討メモ(RFC): 多重デリゲーション競合ポリシーと fini の意味づけ
|
||||||
|
|
||||||
|
最終更新: 2025-08-13
|
||||||
|
|
||||||
|
目的
|
||||||
|
- 多重デリゲーションにおける競合解決ポリシーを明文化し、実装・診断メッセージと揃える。
|
||||||
|
- fini(論理的解放フック)の意味論と期待管理を定義し、現状課題と解決策を整理する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
1) 多重デリゲーションの競合ポリシー(提案仕様)
|
||||||
|
|
||||||
|
基本方針
|
||||||
|
- 明示最優先: 解決順は定めない。曖昧さがある場合はエラーとし、明示(修飾/override)を要求する。
|
||||||
|
- 子の定義優先: 子で定義/overrideされたものが最優先される。
|
||||||
|
|
||||||
|
メソッド解決
|
||||||
|
- 子に同名メソッドがあればそれを使用。上書きは必ず `override` を要する。
|
||||||
|
- 子に無く、親のうち「ちょうど1つ」だけがメソッドを提供するなら自動選択。
|
||||||
|
- 親の「複数」が同名メソッドを提供する場合は曖昧エラー。
|
||||||
|
- 対処: 子で `override foo(...) { return from A.foo(...); }` のように一本化、または呼び出しごとに `from A.foo(...)` / `from B.foo(...)` を使う。
|
||||||
|
- 親呼び出しは常に `from Parent.m(...)` で明示修飾できる(推奨パターン)。
|
||||||
|
|
||||||
|
フィールド解決
|
||||||
|
- 子がフィールドを持てばそれを使用。
|
||||||
|
- 子に無く、親のうち「ちょうど1つ」だけが同名フィールドを持つ場合は自動選択。
|
||||||
|
- 複数親が同名フィールドを持つ場合は曖昧エラー。
|
||||||
|
- 対処: 子で別名のラッパー/アクセサを定義して再輸出、または(将来案として)`from Parent.field` の明示アクセスを利用。
|
||||||
|
|
||||||
|
インターフェース整合
|
||||||
|
- インターフェースが要求するメソッドに対し、複数親が候補を提供する場合、子は必ず `override` して一本化(または合成)する。
|
||||||
|
|
||||||
|
ビルトイン/Static Box
|
||||||
|
- 同一ポリシーを適用。曖昧な場合はエラーで明示を要求。
|
||||||
|
|
||||||
|
診断メッセージ例
|
||||||
|
- Method 'foo' is provided by: A, B. Disambiguate via:
|
||||||
|
- override foo(...) { return from A.foo(...); }
|
||||||
|
- or call with qualification: from A.foo(...)
|
||||||
|
- Field 'x' is provided by: A, B. Define an alias in child or qualify access.
|
||||||
|
|
||||||
|
実装の要点(簡易アルゴリズム)
|
||||||
|
- 解決時に候補集合 S を作成。|S|=0 → 未定義エラー。|S|=1 → その定義を使用。|S|>1 → 曖昧エラー。
|
||||||
|
- 子の定義は候補集合より常に優先(S を見る前に確定)。
|
||||||
|
- メソッド/フィールドで同一ロジックを共有できるようヘルパー化。
|
||||||
|
|
||||||
|
補助パターン(任意)
|
||||||
|
- 構文追加は避け、子側に明示ラッパーを定義して再輸出するのを推奨(後方互換/可読)。
|
||||||
|
- 拡張案として alias 機構(例: alias { A.foo -> aFoo })は将来検討。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
2) fini(論理的解放フック)の意味づけと期待管理
|
||||||
|
|
||||||
|
定義(言語仕様)
|
||||||
|
- `fini()` は「論理的解放」を宣言するフック。呼び出しコンテキストで当該インスタンスを以後使用しないことを示し、関連資源の解放を行う。
|
||||||
|
- 共有参照(他所の強参照)が残存していても、言語意味論上は finalized(使用不可)とみなす。実体メモリが残る場合があるのは実装都合。
|
||||||
|
|
||||||
|
使用禁止のガード
|
||||||
|
- `fini()` 後の操作はエラー(idempotent な `fini()` 再呼出しのみOK)。
|
||||||
|
- 対象: メソッド呼出し、フィールドアクセス、代入、デリゲーション経由の呼出し等。
|
||||||
|
- 推奨エラーメッセージ: "Instance was finalized; further use is prohibited"。
|
||||||
|
|
||||||
|
波及とクリーンアップ
|
||||||
|
- `fini()` は所有フィールドにも波及。子Boxであるフィールドに対し `fini()` を呼び、その後フィールドをクリア。
|
||||||
|
- 弱参照はアクセス時 upgrade 失敗で自動的に `null`(lazy nil化)。必要に応じてデバッグモードで eager 無効化(任意機能)。
|
||||||
|
|
||||||
|
現状課題(2025-08 時点)
|
||||||
|
- 内部 `instance.fini()` が、全フィールド再帰 `fini()` → クリア を必ずしも保証していない(実装強化余地)。
|
||||||
|
- `fini()` 後の使用禁止ガードが緩く、明確なエラー化が不十分なコードパスがある可能性。
|
||||||
|
- 共有参照が残るケースの意味論が docs に十分明示されておらず、誤解リスクがある。
|
||||||
|
|
||||||
|
解決策(優先度順)
|
||||||
|
1) 内部解放強化: `instance.fini()` 内で全フィールドを走査し、InstanceBox へは `fini()`、二重防止フラグ→最後にクリア。
|
||||||
|
2) ガード導入: `get_field`/`set_field`/`get_method` など入口で `finalized` チェック→使用禁止エラーを返す。
|
||||||
|
3) ドキュメント明記: fini = 論理的解放。共有参照残存時も以後の使用は禁止。弱参照はアクセス時 `null`。
|
||||||
|
4) 可視化: Playground に `fini` 回数/weak upgrade 失敗数/エラー例の表示を追加し、期待を合わせる。
|
||||||
|
|
||||||
|
禁止事項(weak への fini 呼び出し)
|
||||||
|
- ルール: `init { weak ... }` で宣言されたフィールドに対する `fini()` 直接呼び出しは禁止(非所有参照の解放に相当)。
|
||||||
|
- 診断方針: 可能な限りビルドエラーで検出し、動的経路は実行時エラーで防止。
|
||||||
|
- 推奨メッセージ: "Cannot finalize weak field '<name>' (non-owning reference). Set it to null or rely on lazy nilification."
|
||||||
|
|
||||||
|
備考(質問への回答)
|
||||||
|
- 「共有参照が残っていても解放が正しいか?」→ はい。言語意味論では“以後使用禁止”を宣言するのが `fini()` で、
|
||||||
|
物理メモリが残るかどうかはランタイムの参照カウントに依存するだけ。禁止ガードと文書化で期待を一致させる。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
3) 追補: 実装/ドキュメント TODO
|
||||||
|
- interpreter: 候補集合による曖昧検出と診断の実装(メソッド/フィールド)。
|
||||||
|
- instance: 再帰的 `fini()` + フィールドクリアの保証、finalized ガードの一元化。
|
||||||
|
- docs: LANGUAGE_GUIDE / reference に上記仕様を反映(サンプルと期待エラーメッセージ含む)。
|
||||||
|
- playground: メトリクス・エラーの可視化を追加(検証再現性の強化)。
|
||||||
126
docs/chatgpt5/論文_サマリ.md
Normal file
126
docs/chatgpt5/論文_サマリ.md
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
# Nyash: Everything is Box — 統一メモリモデルと弱参照による安全なライフサイクル管理
|
||||||
|
|
||||||
|
最終更新: 2025-08-13(ドラフト)
|
||||||
|
|
||||||
|
## 概要(Abstract)
|
||||||
|
本稿は、すべての値を統一的なコンテナ「Box」として扱う“Everything is Box”哲学に基づくプログラミング言語Nyashを提案する。Nyashは、言語構文レベルでメモリ管理を明示化し、予測可能なライフサイクル制御とメモリ安全性を両立する。具体的には、(1) Boxのフィールドは`init { ... }`で宣言し、(2) 再代入・スコープ終了・明示的破棄などの節目で`fini()`による予備解放を行い、(3) ローカル変数はスコープを抜けると自動解放、(4) 循環参照は`init { weak ... }`で弱参照を宣言して回避する。実装はRustで行い、`Arc<Mutex<...>>`と`Weak`を活用、解放済みの二重処理防止や弱参照の自動nil化を含む。設計は明示的デリゲーション(`from`)とオーバーライドの厳密化(`override`必須)と一貫し、ブラウザ/WASMを含む現代環境での直感的・堅牢な開発体験を目指す。
|
||||||
|
|
||||||
|
## 1. 背景と動機
|
||||||
|
- 既存パラダイムの課題: 手動メモリ管理は人為的錯誤に脆弱で、GCは停止時間/タイミング不確定性を招く。双方向参照(Parent↔Child、グラフ構造等)は参照カウント系でリークの温床となる。
|
||||||
|
- 目標: 言語規範でライフサイクル規約を先に定義し、生成・使用・解放の節目を明示することで、安全で予測可能なメモリ管理を提供する。あわせて、表現力(デリゲーション、静的エントリポイント、WASM連携等)を損なわない。
|
||||||
|
|
||||||
|
## 2. 設計の中核(Language Design)
|
||||||
|
### 2.1 Everything is Box
|
||||||
|
あらゆる値(整数・文字列・配列・マップ・ユーザー定義オブジェクト・ユーティリティ等)をBoxで統一する。共通の生成・表示・比較・デバッグ・解放インターフェースを持ち、型ごとの最適化は実装側で行う。
|
||||||
|
|
||||||
|
### 2.2 フィールド宣言と初期化(`init { ... }`)
|
||||||
|
- Boxの状態は`init { field1, field2, ... }`で宣言。循環参照が想定されるフィールドは`weak`修飾で弱参照にする(例: `init { weak parent }`)。
|
||||||
|
- 生成は`new`で行い、必要に応じてコンストラクタ/`pack`等で初期値を設定する(詳細は言語ガイド参照)。
|
||||||
|
|
||||||
|
### 2.3 明示的破棄フック(`fini()`)
|
||||||
|
- `fini()`はBox単位の予備解放フック。リソース解放(子Box解放、外部ハンドルclose、解除処理等)を記述できる。
|
||||||
|
- 言語実装は、(a) フィールド再代入時、(b) スコープ終了時(ローカル環境解体)、(c) 明示呼出し時に`fini()`を安全に実行し、二重実行は抑止する。
|
||||||
|
|
||||||
|
### 2.4 ローカル変数とスコープ解放
|
||||||
|
- `local`で宣言した変数はスコープ終了時に一括解放。未宣言代入はエラーとし、見落としを防止。
|
||||||
|
- Static関数における所有権移転は`outbox`で明示化できる。
|
||||||
|
|
||||||
|
### 2.5 循環参照回避(`weak`)
|
||||||
|
- `init { weak parent }`等で弱参照フィールドを宣言する。代入時に強参照を自動ダウングレードして格納し、アクセス時はupgradeを試みる。失敗時は`null`(自動nil化)を返す。
|
||||||
|
- 双方向参照(Parent↔Child、グラフ)でも参照カウントが残存せず、リークを回避できる。
|
||||||
|
|
||||||
|
### 2.6 デリゲーション(`from`)と明示的オーバーライド
|
||||||
|
- `box Child from Parent { ... }`で機能を委譲。多重デリゲーションにより複数親の機能合成をサポート。
|
||||||
|
- 親メソッド呼出しは`from Parent.method(...)`で明示。暗黙の多段チェーン解決は明示性違反として禁止。上書きは`override`必須。
|
||||||
|
|
||||||
|
### 2.7 Static Boxエントリポイント
|
||||||
|
- `static box Main { main() { ... } }`をアプリの規約化された開始点として用意。初回アクセス時に遅延初期化される。
|
||||||
|
|
||||||
|
## 3. 実装(Rustインタープリタ)
|
||||||
|
本実装はRustにより、安全・明確な所有権モデル上でインタープリタを構築する。
|
||||||
|
|
||||||
|
### 3.1 実行時値(NyashValue)
|
||||||
|
- `NyashValue`は`Integer`, `Float`, `Bool`, `String`, `Array`, `Map`, `Box(Arc<Mutex<dyn NyashBox>>)`に加え、`WeakBox(Weak<Mutex<dyn NyashBox>>)`、`Null`、`Void`等を持つ。
|
||||||
|
- 弱参照は`upgrade_weak()`で強参照化を試み、失敗時は`None`→自動nil化の契機となる(実装詳細は最適化の都合上いくつかの互換層を伴う)。
|
||||||
|
|
||||||
|
### 3.2 インスタンス(InstanceBox)
|
||||||
|
- `InstanceBox`は(互換層の)レガシーフィールド`fields`と次世代フィールド`fields_ng`を併用。弱参照は`fields_ng`で管理し、`set_weak_field`/`get_weak_field`が自動ダウングレード/アップグレードとnil化(失敗時)を司る。
|
||||||
|
- インスタンスの`fini()`は二重呼出し防止フラグを持ち、内部フィールドのクリア等を行う。ユーザー定義`fini()`が存在すれば安全に先行実行される(インタープリタがメソッド本体を一時スタックで実行後、内部解放)。
|
||||||
|
|
||||||
|
### 3.3 予備解放(Finalization)
|
||||||
|
- `finalization`モジュールは、解放済みIDのグローバル管理とスコープ追跡(`BoxFinalizer`)を提供。スコープ終了時/再代入時にBoxを走査し、`fini()`→解放済みマーク→追跡リストクリアの順で安全に解体する。
|
||||||
|
- 代入時のふるまい: フィールドへ新しい値を設定する前に、旧値がインスタンスであれば`fini()`を呼出して二重リソース保持を回避する(ワークフローは`statements.rs`参照)。
|
||||||
|
|
||||||
|
### 3.4 構文サポート
|
||||||
|
- パーサは`init { weak ... }`を解析し、`BoxDeclaration.weak_fields`に収集。フィールドアクセス/代入時に弱参照特有のハンドリング(upgrade/nil化/ダウングレード代入)を適用する。
|
||||||
|
- Static Boxと多重デリゲーションは定義レジストリに登録され、実行時に適切な初期化・解決が行われる。
|
||||||
|
|
||||||
|
## 4. 安全性と正当性(概略)
|
||||||
|
- 予測可能な破棄点: フィールド再代入・スコープ終了・明示的呼出しといった「節目」で`fini()`が必ず実行される。
|
||||||
|
- 二重解放防止: 解放済みIDの記録により、`fini()`の多重呼出しは無害化される。
|
||||||
|
- 循環参照回避: 双方向参照を弱参照にする規約で参照カウントの残留を防止。アクセス時の自動nil化でダングリング参照も防ぐ。
|
||||||
|
- 明示性と可読性: `init`/`weak`/`from`/`override`/`local`等の構文規律により、所有権と到達可能性に関する意図をコードに刻む。
|
||||||
|
|
||||||
|
## 5. パフォーマンス特性(概略)
|
||||||
|
- weakの`upgrade()`は原子的操作+分岐でオーバーヘッドは小さく、Mutexロックより低コストなケースが多い。
|
||||||
|
- stop-the-world GCが存在せず、解放は節目ベースで分散されるため、レイテンシ予測性が高い。
|
||||||
|
- 互換層の段階的移行(legacy→next-gen)は将来的にWeakBoxネイティブ化でさらなる最適化が可能。
|
||||||
|
|
||||||
|
## 6. 使用例
|
||||||
|
### 6.1 親子の相互参照(弱参照)
|
||||||
|
```nyash
|
||||||
|
box Parent {
|
||||||
|
init { child }
|
||||||
|
pack() {
|
||||||
|
me.child = new Child()
|
||||||
|
me.child.setParent(me) # 循環構造だが、子側がweak参照を使用
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { weak parent }
|
||||||
|
setParent(p) { me.parent = p } # 自動でweakに変換・格納
|
||||||
|
getParentName() {
|
||||||
|
if (me.parent != null) { return me.parent.getName() }
|
||||||
|
else { return "Parent is gone" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 再代入時の予備解放
|
||||||
|
```nyash
|
||||||
|
box Holder { init { obj } }
|
||||||
|
h = new Holder()
|
||||||
|
h.obj = new SomeBox()
|
||||||
|
h.obj = new SomeBox() # 旧objに対してfini()が自動呼出し
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 Static Boxエントリ
|
||||||
|
```nyash
|
||||||
|
static box Main {
|
||||||
|
init { console }
|
||||||
|
main() {
|
||||||
|
me.console = new ConsoleBox()
|
||||||
|
me.console.log("Everything is Box!")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 関連研究
|
||||||
|
- SwiftのARCにおける`weak`/`unowned`参照、Rustの`Arc`/`Weak`、Pythonの`weakref`は弱参照の実務的価値を示している。本研究は、弱参照の規約化と`init`/`fini`/スコープ解放を統合した「言語仕様レベルの一貫したライフサイクル設計」を提示する点で差異化される。
|
||||||
|
- 継承ではなくデリゲーション(多重含む)を明示構文で組込むことで、暗黙の探索鎖を排し、構造的明示性とテスト容易性を高める。
|
||||||
|
|
||||||
|
## 8. 制限と今後の課題
|
||||||
|
- 互換層の完全解消: レガシーフィールドから次世代`WeakBox`主導への移行を完了し、統一的な弱参照動作を保証する。
|
||||||
|
- 競合解決: 多重デリゲーション時のメソッド競合検出と診断の改良。
|
||||||
|
- 静的解析: 循環参照の静的検知・Lintの整備。
|
||||||
|
- エコシステム: P2P系Box、WASM環境APIの充実、`async/await`統合の高速化、数値/配列Boxの最適化。
|
||||||
|
|
||||||
|
## 9. 結論
|
||||||
|
Nyashは“Everything is Box”の統一モデルと、`init`/`fini`/`weak`/スコープ解放による予測可能で安全なメモリ管理を言語仕様として提示した。Rust実装により、所有権・スレッド安全・弱参照の自動nil化・二重解放防止を現実的コストで実現する。デリゲーション中心の設計は明示性を高め、教育・アート・Web・P2Pといった多様な開発領域での再利用性と保守性を支える。今後は互換層の収束と解析・最適化の強化により、研究用言語から実運用環境への移行を促進していく。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
補足: 詳細は`docs/LANGUAGE_GUIDE.md`および`docs/reference/weak-reference-design.md`、実装は`src/`配下(`instance.rs`, `finalization.rs`, `interpreter/`)を参照。
|
||||||
|
|
||||||
81
docs/chatgpt5/論文_プロダクト寄りドラフト.md
Normal file
81
docs/chatgpt5/論文_プロダクト寄りドラフト.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Nyash: 実務志向の一貫メモリモデルで日常のプログラミングを簡潔に
|
||||||
|
|
||||||
|
最終更新: 2025-08-13(プロダクト寄りドラフト)
|
||||||
|
|
||||||
|
## 概要(Abstract)
|
||||||
|
Nyashは、すべての値を「Box」に統一し、`init`/`fini`/`weak`/スコープ解放を言語構文に組み込むことで、日常的なメモリ管理をわかりやすくする実務志向の言語です。新奇なアルゴリズムを主張するものではなく、過去数十年のプラクティス(RAII、弱参照、明示的ライフサイクル)を「最初から言語仕様で一貫させる」ことで、予測可能で安全なプログラミング体験を提供します。Rust実装により所有権とスレッド安全を担保しながら、再代入・スコープ終了・循環参照といった“よくある落とし穴”を構文で回避します。
|
||||||
|
|
||||||
|
## 1. 課題設定(なにを楽にするか)
|
||||||
|
- 「いつ解放されるのか」がコードから読み取りづらい(暗黙のGC/規約依存)。
|
||||||
|
- 双方向参照やグラフ構造でリークしやすい(参照カウントの残留)。
|
||||||
|
- フィールド/ローカル/グローバルの寿命や責務が曖昧になりがち。
|
||||||
|
|
||||||
|
## 2. Nyashの要点(どう簡単にするか)
|
||||||
|
- 統一モデル: Everything is Box。生成・代入・比較・解放の扱いが一貫。
|
||||||
|
- 明示宣言: `init { ... }`でフィールド列挙、循環は`weak`で明示。
|
||||||
|
- 予備解放: 再代入・スコープ終了・明示呼出しで`fini()`が走る規約。
|
||||||
|
- ローカル変数: `local`を必須化し、未宣言代入エラーで早期検知。
|
||||||
|
- デリゲーション: `from`で機能合成(多重対応)。`override`は明示必須。
|
||||||
|
|
||||||
|
## 3. なにが“新しい”のではなく“役立つ”のか(ポジショニング)
|
||||||
|
- 研究的な新規性よりも、既知の良い手法の言語レベル統合に価値。
|
||||||
|
- 「60年のメモリ管理の知見を、日常利用に迷わない形へ整理」
|
||||||
|
- 開発者体験(DX)と運用の予測可能性(いつ・どこで解放)が主眼。
|
||||||
|
|
||||||
|
## 4. 開発者にとっての具体的メリット
|
||||||
|
- リーク/二重解放の抑止: `fini()`は二重防止付き、弱参照は自動nil化。
|
||||||
|
- 可読性: フィールド寿命・弱参照・委譲関係がコードから一目で分かる。
|
||||||
|
- テスト容易性: 多重デリゲーションで依存差し替えが明瞭。
|
||||||
|
- ブラウザ対応: WASMで“動かして学ぶ”導線が短い。
|
||||||
|
|
||||||
|
## 5. 最小構文サンプル
|
||||||
|
```nyash
|
||||||
|
box Parent { init { child } }
|
||||||
|
box Child { init { weak parent } }
|
||||||
|
|
||||||
|
p = new Parent()
|
||||||
|
p.child = new Child()
|
||||||
|
p.child.setParent(p) # 子→親はweak。循環でもリークしにくい
|
||||||
|
|
||||||
|
box Holder { init { obj } }
|
||||||
|
h = new Holder()
|
||||||
|
h.obj = new SomeBox()
|
||||||
|
h.obj = new SomeBox() # 旧objに対しfini()が自動呼出し
|
||||||
|
|
||||||
|
static box Main { main() { print("OK") } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 実装概要(Rust)
|
||||||
|
- 実行時値: `NyashValue`に`Box(Arc<Mutex<_>>)`と`WeakBox(Weak<Mutex<_>>)`を持ち、弱参照はアクセス時upgrade→失敗で`null`。
|
||||||
|
- インスタンス: `InstanceBox`が`set_weak_field`/`get_weak_field`で弱参照の格納・自動nil化を扱う。`fini()`は二重防止付き。
|
||||||
|
- スコープ解放: `finalization`モジュールの`BoxFinalizer`がスコープ終了時に一括予備解放。
|
||||||
|
- 代入時処理: フィールド再代入前に旧値へ`fini()`。安全側に倒す規約。
|
||||||
|
|
||||||
|
## 7. 非ゴール(誤解を避けるために)
|
||||||
|
- 新規GCの提案ではない。停止時間最適化などGC起因の研究課題は対象外。
|
||||||
|
- 低レベル最適化の網羅ではない。まずは実務的に“迷わない統一手引き”。
|
||||||
|
|
||||||
|
## 8. 導入・評価の観点(プロダクト視点)
|
||||||
|
- DX: 未宣言代入の早期検知、解放点の明示、弱参照のシンプル化がバグ件数/修正時間に与える影響。
|
||||||
|
- 安定運用: リーク/ダングリング参照/二重解放の再現テストと回避率。
|
||||||
|
- 性能: 弱参照upgrade/`fini()`呼出しのオーバーヘッド(マイクロ/アプリ)。
|
||||||
|
- 学習曲線: Web/WASMのプレイグラウンドでの到達時間・課題種別。
|
||||||
|
|
||||||
|
## 9. 現状とロードマップ
|
||||||
|
- 現状: インタープリタ、弱参照の自動nil化、再代入時`fini()`、多重デリゲーションの基盤が稼働。
|
||||||
|
- 近接課題: レガシー互換層の整理、競合検出メッセージの改善、P2P/標準Boxの拡充。
|
||||||
|
|
||||||
|
## 10. まとめ
|
||||||
|
Nyashは“新しい理論”よりも“迷わない実装規約”で、日常のメモリ管理を静かに楽にすることを狙う。Boxの統一モデルと、`init`/`fini`/`weak`/スコープ解放の一貫性により、解放のタイミングがコードから読める。弱参照の自動nil化と二重解放防止は、実務の落とし穴を減らす。WASM対応の軽い体験とRust実装の堅牢さを両輪に、まずは「使って心地よい」ことを優先し、順次、解析・最適化・エコシステムを整えていく。
|
||||||
|
|
||||||
|
— 参考: 詳細は `docs/LANGUAGE_GUIDE.md`, `docs/reference/weak-reference-design.md` と `src/` 実装を参照。
|
||||||
|
|
||||||
|
## 付録: ブラウザデモ活用(再現性と導線)
|
||||||
|
- Playground: https://moe-charm.github.io/nyash/projects/nyash-wasm/nyash_playground.html
|
||||||
|
- ガイド: プレイグラウンド_ガイド.md(シナリオと手順)
|
||||||
|
- サンプル集: プレイグラウンド_サンプル.md(コピー&ペースト用)
|
||||||
|
|
||||||
|
活用ポイント:
|
||||||
|
- `init`/`fini`/`weak`/スコープ解放の最小例を即時実行し、期待ログ(例: `Thing.fini`、`parent is gone`)で確認可能。
|
||||||
|
- レビュワー/読者はゼロインストールで再現でき、arXiv原稿への短縮URL/QR掲載と相性が良い。
|
||||||
|
- 比較検証(weakなし/あり、再代入前後、スコープ内/外)を1ページで切替・確認可能。
|
||||||
252
docs/reference/finalization-system.md
Normal file
252
docs/reference/finalization-system.md
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
# 🔥 Nyash finiシステム - 論理的解放フック
|
||||||
|
|
||||||
|
**最終更新: 2025年8月13日 - ChatGPT5協議による革命的設計完了**
|
||||||
|
|
||||||
|
## 🎯 概要
|
||||||
|
|
||||||
|
Nyashの`fini()`システムは、物理的メモリ破棄ではなく**論理的使用終了**を宣言する革新的なリソース管理システムです。Everything is Box哲学と完全に統合され、予測可能で安全なリソース管理を実現します。
|
||||||
|
|
||||||
|
## 🌟 核心コンセプト
|
||||||
|
|
||||||
|
### 📝 論理的解放フック
|
||||||
|
```nyash
|
||||||
|
box MyResource {
|
||||||
|
init { name, file }
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
print("Resource " + me.name + " is being finalized")
|
||||||
|
// ファイルクローズなどのクリーンアップ処理
|
||||||
|
// 物理的メモリは共有参照が残っていても論理的には「終了」
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**重要**: `fini()`は「このオブジェクトをもう使わない」という宣言であり、物理的な即時破棄ではありません。
|
||||||
|
|
||||||
|
## 🔄 実行順序(最終仕様)
|
||||||
|
|
||||||
|
### 自動カスケード解放
|
||||||
|
```nyash
|
||||||
|
box Pipeline {
|
||||||
|
init { r1, r2, r3, weak monitor }
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
// 1) ユーザー定義処理(柔軟な順序制御可能)
|
||||||
|
me.r3.fini() // 依存関係でr3→r2の順
|
||||||
|
me.r2.fini()
|
||||||
|
|
||||||
|
// 2) 自動カスケード: 残りのr1がinit宣言順で自動解放
|
||||||
|
// 3) weakフィールドは対象外(lazy nil化)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 決定的な解放順序
|
||||||
|
1. **finalized チェック** - 既に解放済みなら何もしない(idempotent)
|
||||||
|
2. **再入防止** - `in_finalization`フラグで再帰呼び出し防止
|
||||||
|
3. **ユーザー定義fini()実行** - カスタムクリーンアップ処理
|
||||||
|
4. **自動カスケード** - `init`宣言順で未処理フィールドを解放
|
||||||
|
5. **フィールドクリア** - 全フィールドを無効化
|
||||||
|
6. **finalized設定** - 以後の使用を禁止
|
||||||
|
|
||||||
|
## ⚠️ 厳格な禁止事項
|
||||||
|
|
||||||
|
### weak フィールドへのfini呼び出し禁止
|
||||||
|
```nyash
|
||||||
|
box Parent {
|
||||||
|
init { weak child }
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
// ❌ 絶対にダメ!ビルドエラーまたは実行時エラー
|
||||||
|
// me.child.fini()
|
||||||
|
|
||||||
|
// ✅ 正しい方法
|
||||||
|
me.child = null // 参照解除
|
||||||
|
// または自動nil化に任せる
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**理由**: weak参照は所有権を持たない非所有参照のため、fini()を呼ぶ権利がありません。
|
||||||
|
|
||||||
|
### finalized後の使用禁止
|
||||||
|
```nyash
|
||||||
|
box Example { }
|
||||||
|
|
||||||
|
local x = new Example()
|
||||||
|
x.fini()
|
||||||
|
|
||||||
|
// ❌ 以下は全てエラー
|
||||||
|
x.someMethod() // → "Instance was finalized; further use is prohibited"
|
||||||
|
x.field = value // → 同上
|
||||||
|
local val = x.field // → 同上
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ 実装アーキテクチャ
|
||||||
|
|
||||||
|
### InstanceBox拡張
|
||||||
|
```rust
|
||||||
|
pub struct InstanceBox {
|
||||||
|
// 既存フィールド...
|
||||||
|
|
||||||
|
init_field_order: Vec<String>, // 決定的カスケード順序
|
||||||
|
weak_fields_union: HashSet<String>, // weak判定高速化
|
||||||
|
in_finalization: bool, // 再入防止
|
||||||
|
finalized: bool, // 使用禁止フラグ
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 実行時ガード
|
||||||
|
- **メソッド呼び出し**: `finalized`チェック → エラー
|
||||||
|
- **フィールドアクセス**: `finalized`チェック → エラー
|
||||||
|
- **フィールド代入**: `finalized`チェック → エラー
|
||||||
|
|
||||||
|
## 💡 使用例とパターン
|
||||||
|
|
||||||
|
### 基本的な使用例
|
||||||
|
```nyash
|
||||||
|
box FileHandler {
|
||||||
|
init { filename, handle }
|
||||||
|
|
||||||
|
pack(name) {
|
||||||
|
me.filename = name
|
||||||
|
me.handle = openFile(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
if (me.handle != null) {
|
||||||
|
closeFile(me.handle)
|
||||||
|
print("File " + me.filename + " closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用
|
||||||
|
local handler = new FileHandler("data.txt")
|
||||||
|
// ... ファイル操作 ...
|
||||||
|
handler.fini() // 明示的クリーンアップ
|
||||||
|
```
|
||||||
|
|
||||||
|
### 再代入時の自動解放
|
||||||
|
```nyash
|
||||||
|
box Holder { init { resource } }
|
||||||
|
box Resource { fini() { print("Resource cleaned up") } }
|
||||||
|
|
||||||
|
local h = new Holder()
|
||||||
|
h.resource = new Resource() // 新しいリソース設定
|
||||||
|
h.resource = new Resource() // → 前のリソースが自動的にfini()される
|
||||||
|
```
|
||||||
|
|
||||||
|
### カスタム解放順序
|
||||||
|
```nyash
|
||||||
|
box DatabaseConnection {
|
||||||
|
init { transaction, connection, logger }
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
// 依存関係に基づく手動順序制御
|
||||||
|
if (me.transaction != null) {
|
||||||
|
me.transaction.rollback()
|
||||||
|
me.transaction.fini()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.connection != null) {
|
||||||
|
me.connection.close()
|
||||||
|
me.connection.fini()
|
||||||
|
}
|
||||||
|
|
||||||
|
// loggerは自動カスケードに任せる
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 循環参照の安全な解決
|
||||||
|
```nyash
|
||||||
|
box Node {
|
||||||
|
init { data, weak parent, children }
|
||||||
|
|
||||||
|
pack(value) {
|
||||||
|
me.data = value
|
||||||
|
me.children = new ArrayBox()
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild(child) {
|
||||||
|
me.children.push(child)
|
||||||
|
child.setParent(me) // 子→親はweak参照
|
||||||
|
}
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
// 子ノードを先に解放
|
||||||
|
loop (me.children.length() > 0) {
|
||||||
|
local child = me.children.pop()
|
||||||
|
child.fini()
|
||||||
|
}
|
||||||
|
// 親への参照は自動的にnil化される
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 テストパターン
|
||||||
|
|
||||||
|
### 基本動作テスト
|
||||||
|
```nyash
|
||||||
|
box Counter {
|
||||||
|
init { value }
|
||||||
|
pack() { me.value = 0 }
|
||||||
|
increment() { me.value = me.value + 1 }
|
||||||
|
fini() { print("Counter finalized with value: " + me.value.toString()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
local c = new Counter()
|
||||||
|
c.increment()
|
||||||
|
c.increment()
|
||||||
|
c.fini()
|
||||||
|
// c.increment() // → エラー: finalized後の使用禁止
|
||||||
|
```
|
||||||
|
|
||||||
|
### 循環参照テスト
|
||||||
|
```nyash
|
||||||
|
box Parent {
|
||||||
|
init { child }
|
||||||
|
pack() {
|
||||||
|
me.child = new Child()
|
||||||
|
me.child.setParent(me)
|
||||||
|
}
|
||||||
|
fini() { print("Parent finalized") }
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { weak parent }
|
||||||
|
setParent(p) { me.parent = p }
|
||||||
|
fini() { print("Child finalized") }
|
||||||
|
}
|
||||||
|
|
||||||
|
local p = new Parent()
|
||||||
|
p.fini() // Parent → Child の順で解放、リークなし
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 期待される効果
|
||||||
|
|
||||||
|
### メモリ安全性
|
||||||
|
- **循環参照リーク完全防止**: weak参照とfiniの組み合わせ
|
||||||
|
- **二重解放防止**: idempotentな設計
|
||||||
|
- **使用禁止ガード**: finalized後の誤用防止
|
||||||
|
|
||||||
|
### 予測可能性
|
||||||
|
- **決定的順序**: init宣言順による自動カスケード
|
||||||
|
- **明示的制御**: ユーザー定義fini()での柔軟な順序指定
|
||||||
|
- **エラーメッセージ**: 明確で修正提案付きのエラー
|
||||||
|
|
||||||
|
### 開発体験
|
||||||
|
- **直感的**: リソースの「終了宣言」として理解しやすい
|
||||||
|
- **デバッグ容易**: 解放タイミングが明確
|
||||||
|
- **保守性**: 依存関係の変更に強い設計
|
||||||
|
|
||||||
|
## 📚 関連ドキュメント
|
||||||
|
|
||||||
|
- [weak参照設計](weak-reference-design.md) - 循環参照解決との統合
|
||||||
|
- [Everything is Box](design-philosophy.md) - 基本設計思想
|
||||||
|
- [言語リファレンス](language-reference.md) - 構文詳細
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Everything is Box, Everything is Finalized!** 🔥
|
||||||
77
docs/sessions/architecture_consultation.txt
Normal file
77
docs/sessions/architecture_consultation.txt
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
Nyashプログラミング言語のBox型アーキテクチャ設計について深い技術相談です。
|
||||||
|
|
||||||
|
【現在の状況】
|
||||||
|
- Rust実装のプログラミング言語Nyash開発中
|
||||||
|
- "Everything is Box"哲学:全データがBoxオブジェクト
|
||||||
|
- 現在16種類のBox型実装済み(StringBox, IntegerBox, P2PBox等)
|
||||||
|
- Arc<Mutex>統一パターンでスレッドセーフ性確保
|
||||||
|
|
||||||
|
【現在のアーキテクチャ問題】
|
||||||
|
現在、全Box型をtype aliasで統一しているが、実装で型エラー地獄が発生:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// 現在の問題のある設計
|
||||||
|
type StringBox = Arc<Mutex<StringBoxData>>;
|
||||||
|
type IntegerBox = Arc<Mutex<IntegerBoxData>>;
|
||||||
|
type P2PBox = Arc<Mutex<P2PBoxData>>;
|
||||||
|
|
||||||
|
// 問題:型エイリアス複雑化、trait object Debug実装困難
|
||||||
|
// 結果:Copilot実装で型エラー多発、開発効率低下
|
||||||
|
```
|
||||||
|
|
||||||
|
【検討中のシンプル設計】
|
||||||
|
newtype patternによるシンプル化:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// 案1: newtype pattern
|
||||||
|
struct StringBox(Arc<Mutex<StringBoxData>>);
|
||||||
|
struct IntegerBox(Arc<Mutex<IntegerBoxData>>);
|
||||||
|
struct P2PBox(Arc<Mutex<P2PBoxData>>);
|
||||||
|
|
||||||
|
// 案2: 生構造体(必要時のみArc化)
|
||||||
|
struct StringBox { data: String }
|
||||||
|
struct IntegerBox { value: i64 }
|
||||||
|
// 共有が必要な時だけArc::new()で包む
|
||||||
|
```
|
||||||
|
|
||||||
|
【技術的検討ポイント】
|
||||||
|
|
||||||
|
1. **型安全性とシンプルさのバランス**
|
||||||
|
- type alias vs newtype vs 生構造体
|
||||||
|
- コンパイル時エラー検出 vs 実装しやすさ
|
||||||
|
|
||||||
|
2. **スレッドセーフ性の要件**
|
||||||
|
- 全Box型で並行処理が必要か?
|
||||||
|
- StringBox等の基本型にもMutex必要?
|
||||||
|
- 必要な時だけArc<Mutex>化する方が良い?
|
||||||
|
|
||||||
|
3. **拡張性・保守性**
|
||||||
|
- 新Box型追加時の実装コスト
|
||||||
|
- エラーメッセージの分かりやすさ
|
||||||
|
- 他開発者(AI含む)の理解しやすさ
|
||||||
|
|
||||||
|
4. **パフォーマンス**
|
||||||
|
- Arc<Mutex>のオーバーヘッド
|
||||||
|
- ゼロコスト抽象化の実現可能性
|
||||||
|
- メモリ使用量の最適化
|
||||||
|
|
||||||
|
5. **現実的な実装戦略**
|
||||||
|
- 段階的移行 vs 一括変更
|
||||||
|
- 既存コードとの互換性
|
||||||
|
- 開発スピード重視 vs 理想設計重視
|
||||||
|
|
||||||
|
【具体的相談事項】
|
||||||
|
1. type alias vs newtype vs 生構造体、どの設計が最適?
|
||||||
|
2. 全Box型に一律Arc<Mutex>は過剰?必要な箇所のみの方が良い?
|
||||||
|
3. Rust専門家から見て推奨されるBox型統一アーキテクチャは?
|
||||||
|
4. プログラミング言語実装において、型システムのベストプラクティスは?
|
||||||
|
5. 実装効率と設計美学のバランスをどう取るべき?
|
||||||
|
|
||||||
|
【制約条件】
|
||||||
|
- Rust実装必須
|
||||||
|
- Everything is Box哲学維持
|
||||||
|
- スレッドセーフ性確保
|
||||||
|
- 16種類+今後追加予定のBox型すべてで統一
|
||||||
|
- 実装・保守の現実性重視
|
||||||
|
|
||||||
|
プログラミング言語設計・Rust専門家の視点から、実装可能で美しく、長期保守に適したアーキテクチャ設計を提案してください。
|
||||||
64
docs/sessions/chatgpt_consultation_overload.txt
Normal file
64
docs/sessions/chatgpt_consultation_overload.txt
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
Nyashプログラミング言語の関数オーバーロード設計について深い技術的相談です。
|
||||||
|
|
||||||
|
【Nyashの技術的特徴】
|
||||||
|
- Everything is Box哲学: 全データがBoxオブジェクト
|
||||||
|
- Arc<Mutex>統一アーキテクチャ: 完全スレッドセーフ設計
|
||||||
|
- 明示性重視: 変数宣言先の即座特定可能
|
||||||
|
- Rust実装: メモリ安全性+高性能
|
||||||
|
- 目的: 初学者フレンドリー + 実用性
|
||||||
|
|
||||||
|
【検討する技術的課題】
|
||||||
|
現在P2PBox実装において、関数オーバーロード(引数数による分岐)採用の是非を検討中。
|
||||||
|
|
||||||
|
具体例:
|
||||||
|
```rust
|
||||||
|
// Option A: オーバーロードあり
|
||||||
|
impl P2PBox {
|
||||||
|
pub fn send(&self, message: IntentBox) -> Result<(), SendError> // ブロードキャスト
|
||||||
|
pub fn send(&self, to: &str, message: IntentBox) -> Result<(), SendError> // 個別送信
|
||||||
|
pub fn send(&self, to: &str, message: IntentBox, opts: SendOpts) -> Result<(), SendError> // オプション付き
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option B: オーバーロードなし(現在)
|
||||||
|
impl P2PBox {
|
||||||
|
pub fn broadcast(&self, message: IntentBox) -> Result<(), SendError>
|
||||||
|
pub fn send(&self, to: &str, message: IntentBox) -> Result<(), SendError>
|
||||||
|
pub fn send_with_options(&self, to: &str, message: IntentBox, opts: SendOpts) -> Result<(), SendError>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
【技術的検討ポイント】
|
||||||
|
|
||||||
|
1. **Rust実装との整合性**
|
||||||
|
- Rustにはメソッドオーバーロードがない
|
||||||
|
- 引数数による分岐をインタープリターで実装する必要
|
||||||
|
- パフォーマンスへの影響
|
||||||
|
|
||||||
|
2. **Arc<Mutex>アーキテクチャとの親和性**
|
||||||
|
- 動的ディスパッチの複雑さ
|
||||||
|
- エラーハンドリングの一貫性
|
||||||
|
- スレッドセーフティの保持
|
||||||
|
|
||||||
|
3. **インタープリター実装の複雑度**
|
||||||
|
- パーサーでの引数数判定
|
||||||
|
- 実行時メソッド選択アルゴリズム
|
||||||
|
- デバッグ情報の提供
|
||||||
|
|
||||||
|
4. **型安全性とパフォーマンス**
|
||||||
|
- 実行時型チェックのオーバーヘッド
|
||||||
|
- エラーメッセージの品質
|
||||||
|
- 開発時デバッグ体験
|
||||||
|
|
||||||
|
5. **エコシステム設計との整合性**
|
||||||
|
- 他のBox型との一貫性
|
||||||
|
- 拡張性(新しいオーバーロード追加)
|
||||||
|
- メンテナンス性
|
||||||
|
|
||||||
|
【深く検討してほしい点】
|
||||||
|
1. 技術的実装の複雑さ vs ユーザー体験の向上
|
||||||
|
2. Nyashの「明示性重視」哲学との技術的整合性
|
||||||
|
3. 初学者がエラーに遭遇した時のデバッグ体験
|
||||||
|
4. P2P通信という特定ドメインでの最適解
|
||||||
|
5. 言語の長期進化における影響
|
||||||
|
|
||||||
|
プログラミング言語実装の専門的視点から、技術的に最良で保守しやすい設計を分析してください。
|
||||||
46
docs/sessions/gemini_consultation_overload.txt
Normal file
46
docs/sessions/gemini_consultation_overload.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Nyashプログラミング言語の関数オーバーロード採用可否について言語設計の専門的観点から相談です。
|
||||||
|
|
||||||
|
【背景】
|
||||||
|
Nyashは「Everything is Box」哲学で、明示性重視・初学者フレンドリー・メモリ安全性を重視する言語です。現在Phase 2でP2PBox実装中で、関数オーバーロード(引数数による分岐)を採用するか重要な決断が必要です。
|
||||||
|
|
||||||
|
【具体的争点】
|
||||||
|
send(a) と send(a, b) のような関数オーバーロードを許すか?
|
||||||
|
|
||||||
|
例:
|
||||||
|
```nyash
|
||||||
|
// オーバーロードありの場合
|
||||||
|
node.send("hello") // ブロードキャスト
|
||||||
|
node.send("bob", "hello") // 個別送信
|
||||||
|
node.send("bob", msg, options) // オプション付き
|
||||||
|
|
||||||
|
// オーバーロードなしの場合(現在)
|
||||||
|
node.broadcast("hello") // 明示的メソッド名
|
||||||
|
node.send("bob", "hello") // 必ず2引数
|
||||||
|
node.sendWithOptions("bob", msg, options) // 明示的メソッド名
|
||||||
|
```
|
||||||
|
|
||||||
|
【メリット】
|
||||||
|
1. API使いやすさ向上
|
||||||
|
2. 他言語からの移行しやすさ
|
||||||
|
3. 直感的な呼び出し
|
||||||
|
|
||||||
|
【デメリット】
|
||||||
|
1. 間違った関数を呼ぶリスク
|
||||||
|
2. デバッグ困難
|
||||||
|
3. Nyashの明示性哲学と矛盾
|
||||||
|
4. 初学者混乱
|
||||||
|
5. 型推論複雑化
|
||||||
|
|
||||||
|
【Nyashの設計思想との照合】
|
||||||
|
- 明示性重視: プログラマーが変数の宣言先を即座に特定可能
|
||||||
|
- 初学者フレンドリー: 学習コストが低い
|
||||||
|
- Everything is Box: 統一されたオブジェクトモデル
|
||||||
|
|
||||||
|
【質問】
|
||||||
|
1. Nyashの設計思想から見て、関数オーバーロードは採用すべきか?
|
||||||
|
2. 明示性 vs 利便性のトレードオフをどう判断すべきか?
|
||||||
|
3. 初学者向け言語として適切な選択は?
|
||||||
|
4. P2P通信APIにおける最良の設計は?
|
||||||
|
5. 他の現代的言語設計トレンドとの整合性は?
|
||||||
|
|
||||||
|
プログラミング言語設計の専門的視点から、Nyashの将来を決めるアドバイスをお願いします。
|
||||||
73
gemini_consultation_weak_final_implementation.txt
Normal file
73
gemini_consultation_weak_final_implementation.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
Nyash言語のweak参照システム最終実装について技術的相談をお願いします。
|
||||||
|
|
||||||
|
【現在の状況】
|
||||||
|
copilot様がweak参照システムを99%完成させました。驚くべき実装品質です。
|
||||||
|
|
||||||
|
【✅ 完成済みの素晴らしい実装】
|
||||||
|
1. ハイブリッド構造: fields + fields_ng 併用システム
|
||||||
|
2. weak参照専用メソッド: set_weak_field(), get_weak_field()
|
||||||
|
3. 文字列ベース追跡: "WEAK_REF_TO:..." → "WEAK_REFERENCE_DROPPED"
|
||||||
|
4. インタープリター統合: weak参照の検出・代入・アクセス完璧
|
||||||
|
5. 5つの包括的テストケース
|
||||||
|
|
||||||
|
【⚠️ 残り1%の課題】
|
||||||
|
単一関数 trigger_weak_reference_invalidation() が未実装:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub(super) fn trigger_weak_reference_invalidation(&mut self, target_info: &str) {
|
||||||
|
eprintln!("🔗 DEBUG: Triggering global weak reference invalidation for: {}", target_info);
|
||||||
|
|
||||||
|
// TODO: Real implementation would require tracking all instances
|
||||||
|
// and their weak references
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
【現在の動作】
|
||||||
|
```
|
||||||
|
✅ weak参照検出: 完璧 (🔗 DEBUG: Assigning to weak field 'parent')
|
||||||
|
✅ ドロップ検出: 動作中 (🔗 DEBUG: Variable 'parent' set to 0)
|
||||||
|
✅ 無効化呼び出し: 実行中 (🔗 DEBUG: Triggering global weak reference invalidation)
|
||||||
|
❌ 実際のnil化: 未接続 (🔗 DEBUG: Weak field 'parent' still has valid reference)
|
||||||
|
```
|
||||||
|
|
||||||
|
【copilot提案の実装アプローチ】
|
||||||
|
グローバルインスタンス追跡システム:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct SharedState {
|
||||||
|
// 既存フィールド...
|
||||||
|
pub instance_registry: Arc<Mutex<Vec<Weak<Mutex<InstanceBox>>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedState {
|
||||||
|
fn register_instance(&mut self, instance: Weak<Mutex<InstanceBox>>) { ... }
|
||||||
|
fn invalidate_weak_references(&mut self, target_info: &str) {
|
||||||
|
// 全インスタンスを走査してweak参照を無効化
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
【技術的課題】
|
||||||
|
1. 全InstanceBox作成時のグローバル登録必要
|
||||||
|
2. 複雑なスレッドセーフティ管理
|
||||||
|
3. デッドweak参照のガベージコレクション
|
||||||
|
4. 5+ファイルにわたる変更
|
||||||
|
|
||||||
|
【代替案検討の観点】
|
||||||
|
1. **より簡単な実装**: グローバル追跡なしで実現可能?
|
||||||
|
2. **性能重視**: シンプルな文字列マッチングで十分?
|
||||||
|
3. **段階的実装**: デモレベルで動作する最小実装?
|
||||||
|
|
||||||
|
【具体的質問】
|
||||||
|
1. グローバルインスタンス追跡は本当に必要ですか?
|
||||||
|
2. copilotの文字列ベース追跡をより簡単に完成できますか?
|
||||||
|
3. 「target_info」による簡単なマッチング実装は可能ですか?
|
||||||
|
4. デモ目的なら手動的な実装で十分ではないですか?
|
||||||
|
|
||||||
|
【Nyashの設計哲学】
|
||||||
|
- Everything is Box: すべてがBoxオブジェクト
|
||||||
|
- 明示性重視: 隠れた動作を避ける
|
||||||
|
- シンプル重視: 初学者フレンドリー
|
||||||
|
- 実用性優先: 完璧より動くもの
|
||||||
|
|
||||||
|
プログラミング言語実装の専門的観点から、最もシンプルで実装しやすいアプローチを提案してください。copilot様の99%完成した実装を活かしつつ、最後の1%を効率的に完成させる方法をお願いします。
|
||||||
1
nekocode-temp
Submodule
1
nekocode-temp
Submodule
Submodule nekocode-temp added at 509c8b7de8
668
nyashvalue_build_errors.txt
Normal file
668
nyashvalue_build_errors.txt
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad_ascii.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad_ascii`
|
||||||
|
* `example` target `simple_notepad_ascii`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_explorer.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_explorer`
|
||||||
|
* `example` target `nyash_explorer`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/test_icon_extraction.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `test_icon_extraction`
|
||||||
|
* `example` target `test_icon_extraction`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_notepad_jp.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad_jp`
|
||||||
|
* `example` target `nyash_notepad_jp`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `simple_notepad`
|
||||||
|
* `example` target `simple_notepad`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/debug_notepad.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `debug_notepad`
|
||||||
|
* `example` target `debug_notepad`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_explorer_with_icons.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_explorer_icons`
|
||||||
|
* `example` target `nyash_explorer_with_icons`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad_v2.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad`
|
||||||
|
* `example` target `simple_notepad_v2`
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/math_box.rs:59:84
|
||||||
|
|
|
||||||
|
59 | use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, BoxCore, BoxBase, next_box_id};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/debug_box.rs:105:42
|
||||||
|
|
|
||||||
|
105 | use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/null_box.rs:87:72
|
||||||
|
|
|
||||||
|
87 | use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase, next_box_id};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::future::Future`
|
||||||
|
--> src/boxes/future/mod.rs:7:5
|
||||||
|
|
|
||||||
|
7 | use std::future::Future;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::pin::Pin`
|
||||||
|
--> src/boxes/future/mod.rs:8:5
|
||||||
|
|
|
||||||
|
8 | use std::pin::Pin;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `crate::boxes::map_box::MapBox`
|
||||||
|
--> src/boxes/http/mod.rs:9:5
|
||||||
|
|
|
||||||
|
9 | use crate::boxes::map_box::MapBox;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `Arc` and `Mutex`
|
||||||
|
--> src/boxes/http/mod.rs:11:17
|
||||||
|
|
|
||||||
|
11 | use std::sync::{Arc, Mutex};
|
||||||
|
| ^^^ ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Mutex`
|
||||||
|
--> src/boxes/regex/mod.rs:9:22
|
||||||
|
|
|
||||||
|
9 | use std::sync::{Arc, Mutex};
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `self`
|
||||||
|
--> src/boxes/intent_box.rs:38:16
|
||||||
|
|
|
||||||
|
38 | use std::fmt::{self, Debug};
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused macro definition: `debug_fuel`
|
||||||
|
--> src/parser/expressions.rs:38:14
|
||||||
|
|
|
||||||
|
38 | macro_rules! debug_fuel {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_macros)]` on by default
|
||||||
|
|
||||||
|
warning: unused macro definition: `debug_fuel`
|
||||||
|
--> src/parser/mod.rs:51:14
|
||||||
|
|
|
||||||
|
51 | macro_rules! debug_fuel {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `AddBox`, `DivideBox`, `MultiplyBox`, and `SubtractBox`
|
||||||
|
--> src/interpreter/mod.rs:10:75
|
||||||
|
|
|
||||||
|
10 | use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox, SubtractBox, MultiplyBox, DivideBox, CompareBox, ArrayB...
|
||||||
|
| ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `FloatBox`
|
||||||
|
--> src/interpreter/mod.rs:13:39
|
||||||
|
|
|
||||||
|
13 | use crate::boxes::math_box::{MathBox, FloatBox, RangeBox};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `DateTimeBox`
|
||||||
|
--> src/interpreter/mod.rs:14:39
|
||||||
|
|
|
||||||
|
14 | use crate::boxes::time_box::{TimeBox, DateTimeBox, TimerBox};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `file::FileBox`
|
||||||
|
--> src/interpreter/expressions.rs:12:104
|
||||||
|
|
|
||||||
|
12 | use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/interpreter/objects.rs:12:5
|
||||||
|
|
|
||||||
|
12 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `StringBox`
|
||||||
|
--> src/interpreter/methods/collection_methods.rs:11:24
|
||||||
|
|
|
||||||
|
11 | use crate::box_trait::{StringBox, IntegerBox, NyashBox, BoolBox};
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `IntegerBox` and `StringBox`
|
||||||
|
--> src/interpreter/methods/data_methods.rs:11:34
|
||||||
|
|
|
||||||
|
11 | use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
||||||
|
| ^^^^^^^^^ ^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `StringBox`
|
||||||
|
--> src/interpreter/methods/network_methods.rs:10:34
|
||||||
|
|
|
||||||
|
10 | use crate::box_trait::{NyashBox, StringBox};
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `BoolBox`
|
||||||
|
--> src/interpreter/methods/p2p_methods.rs:9:45
|
||||||
|
|
|
||||||
|
9 | use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `crate::method_box::MethodBox`
|
||||||
|
--> src/interpreter/methods/p2p_methods.rs:11:5
|
||||||
|
|
|
||||||
|
11 | use crate::method_box::MethodBox;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `basic_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:27:9
|
||||||
|
|
|
||||||
|
27 | pub use basic_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `collection_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:28:9
|
||||||
|
|
|
||||||
|
28 | pub use collection_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `io_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:29:9
|
||||||
|
|
|
||||||
|
29 | pub use io_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `data_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:30:9
|
||||||
|
|
|
||||||
|
30 | pub use data_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `network_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:31:9
|
||||||
|
|
|
||||||
|
31 | pub use network_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/operator_traits.rs:16:5
|
||||||
|
|
|
||||||
|
16 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/transport/mod.rs:10:5
|
||||||
|
|
|
||||||
|
10 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Write`
|
||||||
|
--> src/boxes/stream/mod.rs:10:21
|
||||||
|
|
|
||||||
|
10 | use std::io::{Read, Write, Result};
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Read`
|
||||||
|
--> src/boxes/stream/mod.rs:10:15
|
||||||
|
|
|
||||||
|
10 | use std::io::{Read, Write, Result};
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:26:28
|
||||||
|
|
|
||||||
|
26 | pub fn http_get(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_variables)]` on by default
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:31:24
|
||||||
|
|
|
||||||
|
31 | pub fn post(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `body`
|
||||||
|
--> src/boxes/http/mod.rs:31:48
|
||||||
|
|
|
||||||
|
31 | pub fn post(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_body`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:36:23
|
||||||
|
|
|
||||||
|
36 | pub fn put(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `body`
|
||||||
|
--> src/boxes/http/mod.rs:36:47
|
||||||
|
|
|
||||||
|
36 | pub fn put(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_body`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:41:26
|
||||||
|
|
|
||||||
|
41 | pub fn delete(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `method`
|
||||||
|
--> src/boxes/http/mod.rs:46:27
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_method`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:46:54
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `options`
|
||||||
|
--> src/boxes/http/mod.rs:46:78
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_options`
|
||||||
|
|
||||||
|
warning: variable `arg_count` is assigned to, but never used
|
||||||
|
--> src/parser/expressions.rs:246:33
|
||||||
|
|
|
||||||
|
246 | let mut arg_count = 0;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_arg_count` instead
|
||||||
|
|
||||||
|
warning: unused variable: `name`
|
||||||
|
--> src/parser/statements.rs:69:35
|
||||||
|
|
|
||||||
|
69 | TokenType::IDENTIFIER(name) => {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_name`
|
||||||
|
|
||||||
|
warning: variable `statement_count` is assigned to, but never used
|
||||||
|
--> src/parser/mod.rs:132:17
|
||||||
|
|
|
||||||
|
132 | let mut statement_count = 0;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_statement_count` instead
|
||||||
|
|
||||||
|
warning: unused variable: `i`
|
||||||
|
--> src/interpreter/expressions.rs:554:22
|
||||||
|
|
|
||||||
|
554 | for (i, arg) in arguments.iter().enumerate() {
|
||||||
|
| ^ help: if this is intentional, prefix it with an underscore: `_i`
|
||||||
|
|
||||||
|
warning: variable `result` is assigned to, but never used
|
||||||
|
--> src/interpreter/expressions.rs:899:21
|
||||||
|
|
|
||||||
|
899 | let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_result` instead
|
||||||
|
|
||||||
|
warning: value assigned to `result` is never read
|
||||||
|
--> src/interpreter/expressions.rs:901:17
|
||||||
|
|
|
||||||
|
901 | result = self.execute_statement(statement)?;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: maybe it is overwritten before being read?
|
||||||
|
= note: `#[warn(unused_assignments)]` on by default
|
||||||
|
|
||||||
|
warning: value assigned to `result` is never read
|
||||||
|
--> src/interpreter/expressions.rs:905:21
|
||||||
|
|
|
||||||
|
905 | result = return_val.clone_box();
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: maybe it is overwritten before being read?
|
||||||
|
|
||||||
|
warning: unused variable: `current_instance`
|
||||||
|
--> src/interpreter/expressions.rs:924:78
|
||||||
|
|
|
||||||
|
924 | fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_current_instance`
|
||||||
|
|
||||||
|
warning: variable does not need to be mutable
|
||||||
|
--> src/interpreter/expressions.rs:924:74
|
||||||
|
|
|
||||||
|
924 | fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||||||
|
| ----^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_mut)]` on by default
|
||||||
|
|
||||||
|
warning: unused variable: `node_id`
|
||||||
|
--> src/interpreter/objects.rs:545:21
|
||||||
|
|
|
||||||
|
545 | let node_id = if let Some(id_str) = node_id_value.as_any().downcast_ref::<StringBox>() {
|
||||||
|
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_node_id`
|
||||||
|
|
||||||
|
warning: unused variable: `transport_str`
|
||||||
|
--> src/interpreter/objects.rs:555:21
|
||||||
|
|
|
||||||
|
555 | let transport_str = if let Some(t_str) = transport_value.as_any().downcast_ref::<StringBox>() {
|
||||||
|
| ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_transport_str`
|
||||||
|
|
||||||
|
warning: unused variable: `existing_method`
|
||||||
|
--> src/instance.rs:89:21
|
||||||
|
|
|
||||||
|
89 | if let Some(existing_method) = new_methods.get(&method_name) {
|
||||||
|
| ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_existing_method`
|
||||||
|
|
||||||
|
warning: field `evaluation_stack` is never read
|
||||||
|
--> src/interpreter/core.rs:207:16
|
||||||
|
|
|
||||||
|
190 | pub struct NyashInterpreter {
|
||||||
|
| ---------------- field in this struct
|
||||||
|
...
|
||||||
|
207 | pub(super) evaluation_stack: Vec<usize>,
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: methods `get_object_id` and `hash_string` are never used
|
||||||
|
--> src/interpreter/expressions.rs:697:8
|
||||||
|
|
|
||||||
|
18 | impl NyashInterpreter {
|
||||||
|
| --------------------- methods in this implementation
|
||||||
|
...
|
||||||
|
697 | fn get_object_id(&self, node: &ASTNode) -> Option<usize> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
716 | fn hash_string(&self, s: &str) -> usize {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
Compiling nyash-rust v0.1.0 (/mnt/c/git/nyash-project/nyash)
|
||||||
|
warning: `nyash-rust` (lib) generated 53 warnings (run `cargo fix --lib -p nyash-rust` to apply 27 suggestions)
|
||||||
|
error: couldn't read `examples/C:/Windows/Fonts/arial.ttf`: No such file or directory (os error 2)
|
||||||
|
--> examples/simple_notepad_win.rs:32:57
|
||||||
|
|
|
||||||
|
32 | std::sync::Arc::new(egui::FontData::from_static(include_bytes!(
|
||||||
|
| _________________________________________________________^
|
||||||
|
33 | | "C:/Windows/Fonts/arial.ttf"
|
||||||
|
34 | | ))),
|
||||||
|
| |_________^
|
||||||
|
|
||||||
|
warning: unused import: `std::path::PathBuf`
|
||||||
|
--> examples/nyash_explorer.rs:5:5
|
||||||
|
|
|
||||||
|
5 | use std::path::PathBuf;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
warning: use of deprecated method `eframe::egui::Ui::allocate_ui_at_rect`: Use `allocate_new_ui` instead
|
||||||
|
--> examples/nyash_explorer.rs:287:28
|
||||||
|
|
|
||||||
|
287 | ui.allocate_ui_at_rect(response.rect, |ui| {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(deprecated)]` on by default
|
||||||
|
|
||||||
|
warning: fields `letter` and `icon_data` are never read
|
||||||
|
--> examples/nyash_explorer.rs:63:5
|
||||||
|
|
|
||||||
|
62 | struct DriveInfo {
|
||||||
|
| --------- fields in this struct
|
||||||
|
63 | letter: String,
|
||||||
|
| ^^^^^^
|
||||||
|
...
|
||||||
|
68 | icon_data: Option<Vec<u8>>,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `DriveInfo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: field `letter` is never read
|
||||||
|
--> examples/nyash_explorer_with_icons.rs:70:5
|
||||||
|
|
|
||||||
|
69 | struct DriveInfo {
|
||||||
|
| --------- field in this struct
|
||||||
|
70 | letter: String,
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: associated function `load_bmp_icon` is never used
|
||||||
|
--> examples/nyash_explorer_with_icons.rs:145:8
|
||||||
|
|
|
||||||
|
85 | impl NyashExplorer {
|
||||||
|
| ------------------ associated function in this implementation
|
||||||
|
...
|
||||||
|
145 | fn load_bmp_icon(file_path: &str) -> Option<ColorImage> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: fields `from_output` and `to_input` are never read
|
||||||
|
--> development/egui_research/experiments/visual_node_prototype.rs:118:5
|
||||||
|
|
|
||||||
|
116 | struct Connection {
|
||||||
|
| ---------- fields in this struct
|
||||||
|
117 | from_node: usize,
|
||||||
|
118 | from_output: String,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
119 | to_node: usize,
|
||||||
|
120 | to_input: String,
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `Connection` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: fields `connecting_from`, `pan_offset`, and `zoom` are never read
|
||||||
|
--> development/egui_research/experiments/visual_node_prototype.rs:128:5
|
||||||
|
|
|
||||||
|
123 | struct VisualProgramming {
|
||||||
|
| ----------------- fields in this struct
|
||||||
|
...
|
||||||
|
128 | connecting_from: Option<(usize, String)>,
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
129 | pan_offset: Vec2,
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
130 | zoom: f32,
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> examples/simple_notepad_win.rs:32:9
|
||||||
|
|
|
||||||
|
30 | fonts.font_data.insert(
|
||||||
|
| ------ arguments to this method are incorrect
|
||||||
|
31 | "system".to_owned(),
|
||||||
|
32 | / std::sync::Arc::new(egui::FontData::from_static(include_bytes!(
|
||||||
|
33 | | "C:/Windows/Fonts/arial.ttf"
|
||||||
|
34 | | ))),
|
||||||
|
| |___________^ expected `FontData`, found `Arc<FontData>`
|
||||||
|
|
|
||||||
|
= note: expected struct `FontData`
|
||||||
|
found struct `Arc<FontData>`
|
||||||
|
help: the return type of this call is `Arc<FontData>` due to the type of the argument passed
|
||||||
|
--> examples/simple_notepad_win.rs:30:5
|
||||||
|
|
|
||||||
|
30 | / fonts.font_data.insert(
|
||||||
|
31 | | "system".to_owned(),
|
||||||
|
32 | |/ std::sync::Arc::new(egui::FontData::from_static(include_bytes!(
|
||||||
|
33 | || "C:/Windows/Fonts/arial.ttf"
|
||||||
|
34 | || ))),
|
||||||
|
| ||___________- this argument influences the return type of `insert`
|
||||||
|
35 | | );
|
||||||
|
| |______^
|
||||||
|
note: method defined here
|
||||||
|
--> /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/alloc/src/collections/btree/map.rs:1023:12
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
error: could not compile `nyash-rust` (example "simple_notepad_win") due to 2 previous errors
|
||||||
|
warning: build failed, waiting for other jobs to finish...
|
||||||
|
warning: unused import: `std::collections::HashMap`
|
||||||
|
--> tests/integration_tests.rs:9:5
|
||||||
|
|
|
||||||
|
9 | use std::collections::HashMap;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
warning: function `execute_nyash_code` is never used
|
||||||
|
--> tests/integration_tests.rs:12:4
|
||||||
|
|
|
||||||
|
12 | fn execute_nyash_code(code: &str) -> Result<String, String> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: unused import: `std::env`
|
||||||
|
--> src/main.rs:33:5
|
||||||
|
|
|
||||||
|
33 | use std::env;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `BoolBox`, `IntegerBox`, and `StringBox`
|
||||||
|
--> src/ast.rs:864:28
|
||||||
|
|
|
||||||
|
864 | use crate::box_trait::{StringBox, IntegerBox, BoolBox};
|
||||||
|
| ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^
|
||||||
|
|
||||||
|
error[E0063]: missing field `is_override` in initializer of `ast::ASTNode`
|
||||||
|
--> src/ast.rs:915:48
|
||||||
|
|
|
||||||
|
915 | methods.insert("getValue".to_string(), ASTNode::FunctionDeclaration {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `is_override`
|
||||||
|
|
||||||
|
error[E0063]: missing fields `is_static`, `static_init` and `type_parameters` in initializer of `ast::ASTNode`
|
||||||
|
--> src/ast.rs:932:24
|
||||||
|
|
|
||||||
|
932 | let box_decl = ASTNode::BoxDeclaration {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ missing `is_static`, `static_init` and `type_parameters`
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0063`.
|
||||||
|
warning: `nyash-rust` (bin "nyash" test) generated 53 warnings (52 duplicates)
|
||||||
|
error: could not compile `nyash-rust` (bin "nyash" test) due to 2 previous errors; 53 warnings emitted
|
||||||
|
error[E0599]: no method named `len` found for struct `boxes::array::ArrayBox` in the current scope
|
||||||
|
--> src/tests/box_tests.rs:19:26
|
||||||
|
|
|
||||||
|
19 | assert_eq!(array.len(), 2);
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
::: src/boxes/array/mod.rs:11:1
|
||||||
|
|
|
||||||
|
11 | pub struct ArrayBox {
|
||||||
|
| ------------------- method `len` not found for this struct
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
|
= note: the following traits define an item `len`, perhaps you need to implement one of them:
|
||||||
|
candidate #1: `CacheTrait`
|
||||||
|
candidate #2: `ExactSizeIterator`
|
||||||
|
candidate #3: `avif_serialize::boxes::MpegBox`
|
||||||
|
candidate #4: `nom::traits::AsChar`
|
||||||
|
candidate #5: `rayon::iter::IndexedParallelIterator`
|
||||||
|
candidate #6: `rayon::range::private::IndexedRangeInteger`
|
||||||
|
candidate #7: `rayon::range_inclusive::private::IndexedRangeInteger`
|
||||||
|
help: there is a method `length` with a similar name
|
||||||
|
|
|
||||||
|
19 | assert_eq!(array.length(), 2);
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0599]: no method named `len` found for struct `buffer::BufferBox` in the current scope
|
||||||
|
--> src/tests/box_tests.rs:35:27
|
||||||
|
|
|
||||||
|
35 | assert_eq!(buffer.len(), 5);
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
::: src/boxes/buffer/mod.rs:38:1
|
||||||
|
|
|
||||||
|
38 | pub struct BufferBox {
|
||||||
|
| -------------------- method `len` not found for this struct
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
|
= note: the following traits define an item `len`, perhaps you need to implement one of them:
|
||||||
|
candidate #1: `CacheTrait`
|
||||||
|
candidate #2: `ExactSizeIterator`
|
||||||
|
candidate #3: `avif_serialize::boxes::MpegBox`
|
||||||
|
candidate #4: `nom::traits::AsChar`
|
||||||
|
candidate #5: `rayon::iter::IndexedParallelIterator`
|
||||||
|
candidate #6: `rayon::range::private::IndexedRangeInteger`
|
||||||
|
candidate #7: `rayon::range_inclusive::private::IndexedRangeInteger`
|
||||||
|
help: there is a method `length` with a similar name
|
||||||
|
|
|
||||||
|
35 | assert_eq!(buffer.length(), 5);
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0600]: cannot apply unary operator `!` to type `Box<(dyn box_trait::NyashBox + 'static)>`
|
||||||
|
--> src/tests/box_tests.rs:114:9
|
||||||
|
|
|
||||||
|
114 | assert!(success_result.is_ok());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
|
||||||
|
|
|
||||||
|
note: the foreign item type `Box<(dyn box_trait::NyashBox + 'static)>` doesn't implement `Not`
|
||||||
|
--> /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/alloc/src/boxed.rs:231:1
|
||||||
|
::: /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/alloc/src/boxed.rs:234:1
|
||||||
|
|
|
||||||
|
= note: not implement `Not`
|
||||||
|
|
||||||
|
error[E0600]: cannot apply unary operator `!` to type `Box<(dyn box_trait::NyashBox + 'static)>`
|
||||||
|
--> src/tests/box_tests.rs:122:17
|
||||||
|
|
|
||||||
|
122 | assert!(!error_result.is_ok());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
|
||||||
|
|
|
||||||
|
note: the foreign item type `Box<(dyn box_trait::NyashBox + 'static)>` doesn't implement `Not`
|
||||||
|
--> /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/alloc/src/boxed.rs:231:1
|
||||||
|
::: /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/alloc/src/boxed.rs:234:1
|
||||||
|
|
|
||||||
|
= note: not implement `Not`
|
||||||
|
|
||||||
|
error[E0599]: no method named `box_id` found for struct `boxes::array::ArrayBox` in the current scope
|
||||||
|
--> src/tests/box_tests.rs:135:25
|
||||||
|
|
|
||||||
|
135 | assert_ne!(box1.box_id(), box2.box_id());
|
||||||
|
| ^^^^^^ method not found in `ArrayBox`
|
||||||
|
|
|
||||||
|
::: src/boxes/array/mod.rs:11:1
|
||||||
|
|
|
||||||
|
11 | pub struct ArrayBox {
|
||||||
|
| ------------------- method `box_id` not found for this struct
|
||||||
|
|
|
||||||
|
::: src/box_trait.rs:55:8
|
||||||
|
|
|
||||||
|
55 | fn box_id(&self) -> u64;
|
||||||
|
| ------ the method is available for `boxes::array::ArrayBox` here
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the trait is in scope
|
||||||
|
help: trait `BoxCore` which provides `box_id` is implemented but not in scope; perhaps you want to import it
|
||||||
|
|
|
||||||
|
7 + use crate::box_trait::BoxCore;
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0599]: no method named `box_id` found for struct `boxes::array::ArrayBox` in the current scope
|
||||||
|
--> src/tests/box_tests.rs:135:40
|
||||||
|
|
|
||||||
|
135 | assert_ne!(box1.box_id(), box2.box_id());
|
||||||
|
| ^^^^^^ method not found in `ArrayBox`
|
||||||
|
|
|
||||||
|
::: src/boxes/array/mod.rs:11:1
|
||||||
|
|
|
||||||
|
11 | pub struct ArrayBox {
|
||||||
|
| ------------------- method `box_id` not found for this struct
|
||||||
|
|
|
||||||
|
::: src/box_trait.rs:55:8
|
||||||
|
|
|
||||||
|
55 | fn box_id(&self) -> u64;
|
||||||
|
| ------ the method is available for `boxes::array::ArrayBox` here
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the trait is in scope
|
||||||
|
help: trait `BoxCore` which provides `box_id` is implemented but not in scope; perhaps you want to import it
|
||||||
|
|
|
||||||
|
7 + use crate::box_trait::BoxCore;
|
||||||
|
|
|
||||||
|
|
||||||
|
warning: variable does not need to be mutable
|
||||||
|
--> src/tests/box_tests.rs:90:13
|
||||||
|
|
|
||||||
|
90 | let mut stream = NyashStreamBox::from_data(vec![72, 101, 108, 108, 111]); // "Hello"
|
||||||
|
| ----^^^^^^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0063, E0599, E0600.
|
||||||
|
For more information about an error, try `rustc --explain E0063`.
|
||||||
|
warning: `nyash-rust` (lib test) generated 53 warnings (52 duplicates)
|
||||||
|
error: could not compile `nyash-rust` (lib test) due to 8 previous errors; 53 warnings emitted
|
||||||
|
warning: `nyash-rust` (bin "nyash_explorer_icons" test) generated 2 warnings (2 duplicates)
|
||||||
|
warning: `nyash-rust` (bin "nyash_explorer" test) generated 3 warnings (3 duplicates)
|
||||||
|
warning: `nyash-rust` (test "integration_tests") generated 2 warnings (run `cargo fix --test "integration_tests"` to apply 1 suggestion)
|
||||||
434
nyashvalue_check_errors.txt
Normal file
434
nyashvalue_check_errors.txt
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/debug_notepad.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `debug_notepad`
|
||||||
|
* `example` target `debug_notepad`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/test_icon_extraction.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `test_icon_extraction`
|
||||||
|
* `example` target `test_icon_extraction`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad_ascii.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad_ascii`
|
||||||
|
* `example` target `simple_notepad_ascii`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad_v2.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad`
|
||||||
|
* `example` target `simple_notepad_v2`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_notepad_jp.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_notepad_jp`
|
||||||
|
* `example` target `nyash_notepad_jp`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_explorer_with_icons.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_explorer_icons`
|
||||||
|
* `example` target `nyash_explorer_with_icons`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/nyash_explorer.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `nyash_explorer`
|
||||||
|
* `example` target `nyash_explorer`
|
||||||
|
warning: file `/mnt/c/git/nyash-project/nyash/examples/simple_notepad.rs` found to be present in multiple build targets:
|
||||||
|
* `bin` target `simple_notepad`
|
||||||
|
* `example` target `simple_notepad`
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/math_box.rs:59:84
|
||||||
|
|
|
||||||
|
59 | use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, BoxCore, BoxBase, next_box_id};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/debug_box.rs:105:42
|
||||||
|
|
|
||||||
|
105 | use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `next_box_id`
|
||||||
|
--> src/boxes/null_box.rs:87:72
|
||||||
|
|
|
||||||
|
87 | use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase, next_box_id};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::future::Future`
|
||||||
|
--> src/boxes/future/mod.rs:7:5
|
||||||
|
|
|
||||||
|
7 | use std::future::Future;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::pin::Pin`
|
||||||
|
--> src/boxes/future/mod.rs:8:5
|
||||||
|
|
|
||||||
|
8 | use std::pin::Pin;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `crate::boxes::map_box::MapBox`
|
||||||
|
--> src/boxes/http/mod.rs:9:5
|
||||||
|
|
|
||||||
|
9 | use crate::boxes::map_box::MapBox;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `Arc` and `Mutex`
|
||||||
|
--> src/boxes/http/mod.rs:11:17
|
||||||
|
|
|
||||||
|
11 | use std::sync::{Arc, Mutex};
|
||||||
|
| ^^^ ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Mutex`
|
||||||
|
--> src/boxes/regex/mod.rs:9:22
|
||||||
|
|
|
||||||
|
9 | use std::sync::{Arc, Mutex};
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `self`
|
||||||
|
--> src/boxes/intent_box.rs:38:16
|
||||||
|
|
|
||||||
|
38 | use std::fmt::{self, Debug};
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused macro definition: `debug_fuel`
|
||||||
|
--> src/parser/expressions.rs:38:14
|
||||||
|
|
|
||||||
|
38 | macro_rules! debug_fuel {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_macros)]` on by default
|
||||||
|
|
||||||
|
warning: unused macro definition: `debug_fuel`
|
||||||
|
--> src/parser/mod.rs:51:14
|
||||||
|
|
|
||||||
|
51 | macro_rules! debug_fuel {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `AddBox`, `DivideBox`, `MultiplyBox`, and `SubtractBox`
|
||||||
|
--> src/interpreter/mod.rs:10:75
|
||||||
|
|
|
||||||
|
10 | use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox, SubtractBox, MultiplyBox, DivideBox, CompareBox, ArrayB...
|
||||||
|
| ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `FloatBox`
|
||||||
|
--> src/interpreter/mod.rs:13:39
|
||||||
|
|
|
||||||
|
13 | use crate::boxes::math_box::{MathBox, FloatBox, RangeBox};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `DateTimeBox`
|
||||||
|
--> src/interpreter/mod.rs:14:39
|
||||||
|
|
|
||||||
|
14 | use crate::boxes::time_box::{TimeBox, DateTimeBox, TimerBox};
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `file::FileBox`
|
||||||
|
--> src/interpreter/expressions.rs:12:104
|
||||||
|
|
|
||||||
|
12 | use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/interpreter/objects.rs:12:5
|
||||||
|
|
|
||||||
|
12 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `StringBox`
|
||||||
|
--> src/interpreter/methods/collection_methods.rs:11:24
|
||||||
|
|
|
||||||
|
11 | use crate::box_trait::{StringBox, IntegerBox, NyashBox, BoolBox};
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused imports: `IntegerBox` and `StringBox`
|
||||||
|
--> src/interpreter/methods/data_methods.rs:11:34
|
||||||
|
|
|
||||||
|
11 | use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
||||||
|
| ^^^^^^^^^ ^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `StringBox`
|
||||||
|
--> src/interpreter/methods/network_methods.rs:10:34
|
||||||
|
|
|
||||||
|
10 | use crate::box_trait::{NyashBox, StringBox};
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `BoolBox`
|
||||||
|
--> src/interpreter/methods/p2p_methods.rs:9:45
|
||||||
|
|
|
||||||
|
9 | use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `crate::method_box::MethodBox`
|
||||||
|
--> src/interpreter/methods/p2p_methods.rs:11:5
|
||||||
|
|
|
||||||
|
11 | use crate::method_box::MethodBox;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `basic_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:27:9
|
||||||
|
|
|
||||||
|
27 | pub use basic_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `collection_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:28:9
|
||||||
|
|
|
||||||
|
28 | pub use collection_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `io_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:29:9
|
||||||
|
|
|
||||||
|
29 | pub use io_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `data_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:30:9
|
||||||
|
|
|
||||||
|
30 | pub use data_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `network_methods::*`
|
||||||
|
--> src/interpreter/methods/mod.rs:31:9
|
||||||
|
|
|
||||||
|
31 | pub use network_methods::*;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/operator_traits.rs:16:5
|
||||||
|
|
|
||||||
|
16 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::sync::Arc`
|
||||||
|
--> src/transport/mod.rs:10:5
|
||||||
|
|
|
||||||
|
10 | use std::sync::Arc;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Write`
|
||||||
|
--> src/boxes/stream/mod.rs:10:21
|
||||||
|
|
|
||||||
|
10 | use std::io::{Read, Write, Result};
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `Read`
|
||||||
|
--> src/boxes/stream/mod.rs:10:15
|
||||||
|
|
|
||||||
|
10 | use std::io::{Read, Write, Result};
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:26:28
|
||||||
|
|
|
||||||
|
26 | pub fn http_get(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_variables)]` on by default
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:31:24
|
||||||
|
|
|
||||||
|
31 | pub fn post(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `body`
|
||||||
|
--> src/boxes/http/mod.rs:31:48
|
||||||
|
|
|
||||||
|
31 | pub fn post(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_body`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:36:23
|
||||||
|
|
|
||||||
|
36 | pub fn put(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `body`
|
||||||
|
--> src/boxes/http/mod.rs:36:47
|
||||||
|
|
|
||||||
|
36 | pub fn put(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_body`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:41:26
|
||||||
|
|
|
||||||
|
41 | pub fn delete(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `method`
|
||||||
|
--> src/boxes/http/mod.rs:46:27
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_method`
|
||||||
|
|
||||||
|
warning: unused variable: `url`
|
||||||
|
--> src/boxes/http/mod.rs:46:54
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^ help: if this is intentional, prefix it with an underscore: `_url`
|
||||||
|
|
||||||
|
warning: unused variable: `options`
|
||||||
|
--> src/boxes/http/mod.rs:46:78
|
||||||
|
|
|
||||||
|
46 | pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_options`
|
||||||
|
|
||||||
|
warning: variable `arg_count` is assigned to, but never used
|
||||||
|
--> src/parser/expressions.rs:246:33
|
||||||
|
|
|
||||||
|
246 | let mut arg_count = 0;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_arg_count` instead
|
||||||
|
|
||||||
|
warning: unused variable: `name`
|
||||||
|
--> src/parser/statements.rs:69:35
|
||||||
|
|
|
||||||
|
69 | TokenType::IDENTIFIER(name) => {
|
||||||
|
| ^^^^ help: if this is intentional, prefix it with an underscore: `_name`
|
||||||
|
|
||||||
|
warning: variable `statement_count` is assigned to, but never used
|
||||||
|
--> src/parser/mod.rs:132:17
|
||||||
|
|
|
||||||
|
132 | let mut statement_count = 0;
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_statement_count` instead
|
||||||
|
|
||||||
|
warning: unused variable: `i`
|
||||||
|
--> src/interpreter/expressions.rs:554:22
|
||||||
|
|
|
||||||
|
554 | for (i, arg) in arguments.iter().enumerate() {
|
||||||
|
| ^ help: if this is intentional, prefix it with an underscore: `_i`
|
||||||
|
|
||||||
|
warning: variable `result` is assigned to, but never used
|
||||||
|
--> src/interpreter/expressions.rs:899:21
|
||||||
|
|
|
||||||
|
899 | let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_result` instead
|
||||||
|
|
||||||
|
warning: value assigned to `result` is never read
|
||||||
|
--> src/interpreter/expressions.rs:901:17
|
||||||
|
|
|
||||||
|
901 | result = self.execute_statement(statement)?;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: maybe it is overwritten before being read?
|
||||||
|
= note: `#[warn(unused_assignments)]` on by default
|
||||||
|
|
||||||
|
warning: value assigned to `result` is never read
|
||||||
|
--> src/interpreter/expressions.rs:905:21
|
||||||
|
|
|
||||||
|
905 | result = return_val.clone_box();
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: maybe it is overwritten before being read?
|
||||||
|
|
||||||
|
warning: unused variable: `current_instance`
|
||||||
|
--> src/interpreter/expressions.rs:924:78
|
||||||
|
|
|
||||||
|
924 | fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_current_instance`
|
||||||
|
|
||||||
|
warning: variable does not need to be mutable
|
||||||
|
--> src/interpreter/expressions.rs:924:74
|
||||||
|
|
|
||||||
|
924 | fn execute_builtin_box_method(&mut self, parent: &str, method: &str, mut current_instance: Box<dyn NyashBox>, arguments: &[ASTNode])
|
||||||
|
| ----^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_mut)]` on by default
|
||||||
|
|
||||||
|
warning: unused variable: `node_id`
|
||||||
|
--> src/interpreter/objects.rs:545:21
|
||||||
|
|
|
||||||
|
545 | let node_id = if let Some(id_str) = node_id_value.as_any().downcast_ref::<StringBox>() {
|
||||||
|
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_node_id`
|
||||||
|
|
||||||
|
warning: unused variable: `transport_str`
|
||||||
|
--> src/interpreter/objects.rs:555:21
|
||||||
|
|
|
||||||
|
555 | let transport_str = if let Some(t_str) = transport_value.as_any().downcast_ref::<StringBox>() {
|
||||||
|
| ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_transport_str`
|
||||||
|
|
||||||
|
warning: unused variable: `existing_method`
|
||||||
|
--> src/instance.rs:89:21
|
||||||
|
|
|
||||||
|
89 | if let Some(existing_method) = new_methods.get(&method_name) {
|
||||||
|
| ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_existing_method`
|
||||||
|
|
||||||
|
warning: field `evaluation_stack` is never read
|
||||||
|
--> src/interpreter/core.rs:207:16
|
||||||
|
|
|
||||||
|
190 | pub struct NyashInterpreter {
|
||||||
|
| ---------------- field in this struct
|
||||||
|
...
|
||||||
|
207 | pub(super) evaluation_stack: Vec<usize>,
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: methods `get_object_id` and `hash_string` are never used
|
||||||
|
--> src/interpreter/expressions.rs:697:8
|
||||||
|
|
|
||||||
|
18 | impl NyashInterpreter {
|
||||||
|
| --------------------- methods in this implementation
|
||||||
|
...
|
||||||
|
697 | fn get_object_id(&self, node: &ASTNode) -> Option<usize> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
716 | fn hash_string(&self, s: &str) -> usize {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: `nyash-rust` (lib) generated 53 warnings (run `cargo fix --lib -p nyash-rust` to apply 27 suggestions)
|
||||||
|
warning: unused import: `std::env`
|
||||||
|
--> src/main.rs:33:5
|
||||||
|
|
|
||||||
|
33 | use std::env;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused import: `std::path::PathBuf`
|
||||||
|
--> examples/nyash_explorer.rs:5:5
|
||||||
|
|
|
||||||
|
5 | use std::path::PathBuf;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
warning: use of deprecated method `eframe::egui::Ui::allocate_ui_at_rect`: Use `allocate_new_ui` instead
|
||||||
|
--> examples/nyash_explorer.rs:287:28
|
||||||
|
|
|
||||||
|
287 | ui.allocate_ui_at_rect(response.rect, |ui| {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(deprecated)]` on by default
|
||||||
|
|
||||||
|
warning: fields `letter` and `icon_data` are never read
|
||||||
|
--> examples/nyash_explorer.rs:63:5
|
||||||
|
|
|
||||||
|
62 | struct DriveInfo {
|
||||||
|
| --------- fields in this struct
|
||||||
|
63 | letter: String,
|
||||||
|
| ^^^^^^
|
||||||
|
...
|
||||||
|
68 | icon_data: Option<Vec<u8>>,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `DriveInfo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: field `letter` is never read
|
||||||
|
--> examples/nyash_explorer_with_icons.rs:70:5
|
||||||
|
|
|
||||||
|
69 | struct DriveInfo {
|
||||||
|
| --------- field in this struct
|
||||||
|
70 | letter: String,
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: associated function `load_bmp_icon` is never used
|
||||||
|
--> examples/nyash_explorer_with_icons.rs:145:8
|
||||||
|
|
|
||||||
|
85 | impl NyashExplorer {
|
||||||
|
| ------------------ associated function in this implementation
|
||||||
|
...
|
||||||
|
145 | fn load_bmp_icon(file_path: &str) -> Option<ColorImage> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: `nyash-rust` (bin "nyash") generated 54 warnings (53 duplicates) (run `cargo fix --bin "nyash"` to apply 1 suggestion)
|
||||||
|
warning: `nyash-rust` (bin "nyash_explorer") generated 3 warnings (run `cargo fix --bin "nyash_explorer"` to apply 1 suggestion)
|
||||||
|
warning: `nyash-rust` (bin "nyash_explorer_icons") generated 2 warnings
|
||||||
|
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.59s
|
||||||
@ -928,6 +928,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
is_static: false, // 通常のメソッド
|
is_static: false, // 通常のメソッド
|
||||||
|
is_override: false,
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,11 @@ impl ArrayBox {
|
|||||||
Box::new(IntegerBox::new(self.items.lock().unwrap().len() as i64))
|
Box::new(IntegerBox::new(self.items.lock().unwrap().len() as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rust向けヘルパー: 要素数をusizeで取得(テスト用)
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.items.lock().unwrap().len()
|
||||||
|
}
|
||||||
|
|
||||||
/// インデックスで要素を取得
|
/// インデックスで要素を取得
|
||||||
pub fn get(&self, index: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
pub fn get(&self, index: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
if let Some(idx_box) = index.as_any().downcast_ref::<IntegerBox>() {
|
if let Some(idx_box) = index.as_any().downcast_ref::<IntegerBox>() {
|
||||||
|
|||||||
@ -48,6 +48,11 @@ impl BufferBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rust向けヘルパー: バッファ長をusizeで取得(テスト用)
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.data.lock().unwrap().len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_vec(data: Vec<u8>) -> Self {
|
pub fn from_vec(data: Vec<u8>) -> Self {
|
||||||
BufferBox {
|
BufferBox {
|
||||||
data: Arc::new(Mutex::new(data)),
|
data: Arc::new(Mutex::new(data)),
|
||||||
|
|||||||
119
src/instance.rs
119
src/instance.rs
@ -34,14 +34,24 @@ pub struct InstanceBox {
|
|||||||
|
|
||||||
/// 解放済みフラグ
|
/// 解放済みフラグ
|
||||||
finalized: Arc<Mutex<bool>>,
|
finalized: Arc<Mutex<bool>>,
|
||||||
|
|
||||||
|
/// 🔥 Phase 2: finiシステム完全実装 - ChatGPT5設計
|
||||||
|
/// init宣言順序(決定的カスケード用)
|
||||||
|
init_field_order: Vec<String>,
|
||||||
|
|
||||||
|
/// weak フィールド高速判定用
|
||||||
|
weak_fields_union: std::collections::HashSet<String>,
|
||||||
|
|
||||||
|
/// 解放中フラグ(再入防止)
|
||||||
|
in_finalization: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstanceBox {
|
impl InstanceBox {
|
||||||
pub fn new(class_name: String, fields: Vec<String>, methods: HashMap<String, ASTNode>) -> Self {
|
pub fn new(class_name: String, fields: Vec<String>, methods: HashMap<String, ASTNode>) -> Self {
|
||||||
// フィールドをVoidBoxで初期化
|
// フィールドをVoidBoxで初期化
|
||||||
let mut field_map = HashMap::new();
|
let mut field_map = HashMap::new();
|
||||||
for field in fields {
|
for field in &fields {
|
||||||
field_map.insert(field, Box::new(VoidBox::new()) as Box<dyn NyashBox>);
|
field_map.insert(field.clone(), Box::new(VoidBox::new()) as Box<dyn NyashBox>);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -51,6 +61,39 @@ impl InstanceBox {
|
|||||||
methods: Arc::new(methods),
|
methods: Arc::new(methods),
|
||||||
base: BoxBase::new(),
|
base: BoxBase::new(),
|
||||||
finalized: Arc::new(Mutex::new(false)),
|
finalized: Arc::new(Mutex::new(false)),
|
||||||
|
init_field_order: fields.clone(), // 🔥 Basic field order for backwards compatibility
|
||||||
|
weak_fields_union: std::collections::HashSet::new(), // 🔥 Empty for backwards compatibility
|
||||||
|
in_finalization: Arc::new(Mutex::new(false)), // 🔥 Initialize finalization guard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🔥 Enhanced constructor with complete fini system support
|
||||||
|
pub fn new_with_box_info(
|
||||||
|
class_name: String,
|
||||||
|
fields: Vec<String>,
|
||||||
|
methods: HashMap<String, ASTNode>,
|
||||||
|
init_field_order: Vec<String>,
|
||||||
|
weak_fields: Vec<String>
|
||||||
|
) -> Self {
|
||||||
|
// フィールドをVoidBoxで初期化
|
||||||
|
let mut field_map = HashMap::new();
|
||||||
|
for field in &fields {
|
||||||
|
field_map.insert(field.clone(), Box::new(VoidBox::new()) as Box<dyn NyashBox>);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Weak fields をHashSetに変換(高速判定用)
|
||||||
|
let weak_fields_union: std::collections::HashSet<String> = weak_fields.into_iter().collect();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
class_name,
|
||||||
|
fields: Arc::new(Mutex::new(field_map)),
|
||||||
|
fields_ng: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
methods: Arc::new(methods),
|
||||||
|
base: BoxBase::new(),
|
||||||
|
finalized: Arc::new(Mutex::new(false)),
|
||||||
|
init_field_order, // 🔥 決定的カスケード順序
|
||||||
|
weak_fields_union, // 🔥 高速weak判定
|
||||||
|
in_finalization: Arc::new(Mutex::new(false)), // 🔥 再入防止
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,19 +333,75 @@ impl InstanceBox {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// fini()メソッド - インスタンスの解放
|
/// 🔥 Enhanced fini()メソッド - ChatGPT5設計による完全実装
|
||||||
pub fn fini(&self) -> Result<(), String> {
|
pub fn fini(&self) -> Result<(), String> {
|
||||||
|
// 1) finalized チェック(idempotent)
|
||||||
let mut finalized = self.finalized.lock().unwrap();
|
let mut finalized = self.finalized.lock().unwrap();
|
||||||
if *finalized {
|
if *finalized {
|
||||||
// 既に解放済みなら何もしない
|
// 既に解放済みなら何もしない
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
*finalized = true;
|
// 2) in_finalization = true(再入防止)
|
||||||
|
let mut in_finalization = self.in_finalization.lock().unwrap();
|
||||||
|
if *in_finalization {
|
||||||
|
return Err("Circular finalization detected - fini() called recursively".to_string());
|
||||||
|
}
|
||||||
|
*in_finalization = true;
|
||||||
|
|
||||||
// フィールドをクリア
|
// 3) TODO: ユーザー定義fini()実行(インタープリター側で実装予定)
|
||||||
|
// このメソッドは低レベルなfini処理なので、高レベルなユーザー定義fini()は
|
||||||
|
// インタープリター側で先に呼び出される想定
|
||||||
|
|
||||||
|
// 4) 自動カスケード: init_field_order の強参照フィールドに child.fini()
|
||||||
|
self.cascade_finalize_fields()?;
|
||||||
|
|
||||||
|
// 5) 全フィールドクリア + finalized = true
|
||||||
let mut fields = self.fields.lock().unwrap();
|
let mut fields = self.fields.lock().unwrap();
|
||||||
fields.clear();
|
fields.clear();
|
||||||
|
let mut fields_ng = self.fields_ng.lock().unwrap();
|
||||||
|
fields_ng.clear();
|
||||||
|
|
||||||
|
*finalized = true;
|
||||||
|
*in_finalization = false; // 再入フラグをクリア
|
||||||
|
|
||||||
|
eprintln!("🔥 fini(): Instance {} (ID: {}) finalized", self.class_name, self.base.id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🔥 自動カスケード解放 - init宣言順でフィールドをfini
|
||||||
|
fn cascade_finalize_fields(&self) -> Result<(), String> {
|
||||||
|
let fields_ng = self.fields_ng.lock().unwrap();
|
||||||
|
|
||||||
|
// init_field_order の逆順でfiniを実行(LIFO - Last In First Out)
|
||||||
|
for field_name in self.init_field_order.iter().rev() {
|
||||||
|
// weak フィールドはスキップ
|
||||||
|
if self.weak_fields_union.contains(field_name) {
|
||||||
|
eprintln!("🔥 fini(): Skipping weak field '{}' (non-owning reference)", field_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// フィールドの値を取得してfini呼び出し
|
||||||
|
if let Some(field_value) = fields_ng.get(field_name) {
|
||||||
|
match field_value {
|
||||||
|
crate::value::NyashValue::Box(arc_box) => {
|
||||||
|
if let Ok(inner_box) = arc_box.try_lock() {
|
||||||
|
// InstanceBoxならfini()を呼び出し
|
||||||
|
if let Some(instance) = inner_box.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
eprintln!("🔥 fini(): Cascading finalization to field '{}'", field_name);
|
||||||
|
if let Err(e) = instance.fini() {
|
||||||
|
eprintln!("🔥 fini(): Warning - failed to finalize field '{}': {}", field_name, e);
|
||||||
|
// エラーは警告として記録するが、続行する
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// non-Box値はfini不要
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -311,6 +410,16 @@ impl InstanceBox {
|
|||||||
pub fn is_finalized(&self) -> bool {
|
pub fn is_finalized(&self) -> bool {
|
||||||
*self.finalized.lock().unwrap()
|
*self.finalized.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 🔥 解放中かチェック
|
||||||
|
pub fn is_in_finalization(&self) -> bool {
|
||||||
|
*self.in_finalization.lock().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🔥 指定フィールドがweakかチェック
|
||||||
|
pub fn is_weak_field(&self, field_name: &str) -> bool {
|
||||||
|
self.weak_fields_union.contains(field_name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyashBox for InstanceBox {
|
impl NyashBox for InstanceBox {
|
||||||
|
|||||||
@ -498,8 +498,37 @@ impl NyashInterpreter {
|
|||||||
|
|
||||||
// InstanceBox method calls
|
// InstanceBox method calls
|
||||||
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
|
if instance.is_finalized() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: "Instance was finalized; further use is prohibited".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// fini()は特別処理
|
// fini()は特別処理
|
||||||
if method == "fini" {
|
if method == "fini" {
|
||||||
|
// 🔥 weak-fini prohibition check - prevent fini() on weak fields
|
||||||
|
if let ASTNode::FieldAccess { object: field_object, field, .. } = object {
|
||||||
|
// Check if this is me.<field>.fini() pattern
|
||||||
|
if let ASTNode::Variable { name, .. } = field_object.as_ref() {
|
||||||
|
if name == "me" {
|
||||||
|
// Get current instance to check if field is weak
|
||||||
|
if let Ok(current_me) = self.resolve_variable("me") {
|
||||||
|
if let Some(current_instance) = current_me.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
if current_instance.is_weak_field(field) {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!(
|
||||||
|
"Cannot finalize weak field '{}' (non-owning reference)",
|
||||||
|
field
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 既に解放済みの場合は何もしない(二重fini()対策)
|
// 既に解放済みの場合は何もしない(二重fini()対策)
|
||||||
if instance.is_finalized() {
|
if instance.is_finalized() {
|
||||||
return Ok(Box::new(VoidBox::new()));
|
return Ok(Box::new(VoidBox::new()));
|
||||||
@ -625,6 +654,13 @@ impl NyashInterpreter {
|
|||||||
|
|
||||||
// InstanceBoxにキャスト
|
// InstanceBoxにキャスト
|
||||||
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
|
if instance.is_finalized() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: "Instance was finalized; further use is prohibited".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// フィールドの値を取得
|
// フィールドの値を取得
|
||||||
let field_value = instance.get_field(field)
|
let field_value = instance.get_field(field)
|
||||||
.ok_or(RuntimeError::InvalidOperation {
|
.ok_or(RuntimeError::InvalidOperation {
|
||||||
|
|||||||
@ -650,11 +650,17 @@ impl NyashInterpreter {
|
|||||||
// 継承チェーンを解決してフィールドとメソッドを収集(init_fieldsも含む)
|
// 継承チェーンを解決してフィールドとメソッドを収集(init_fieldsも含む)
|
||||||
let (all_fields, all_methods) = self.resolve_inheritance(&final_box_decl)?;
|
let (all_fields, all_methods) = self.resolve_inheritance(&final_box_decl)?;
|
||||||
|
|
||||||
// インスタンスを作成
|
// 🔥 フィールド順序と weak フィールドを準備(finiシステム用)
|
||||||
let instance = InstanceBox::new(
|
let init_field_order = final_box_decl.init_fields.clone();
|
||||||
|
let weak_fields = final_box_decl.weak_fields.clone();
|
||||||
|
|
||||||
|
// インスタンスを作成(Enhanced fini system対応)
|
||||||
|
let instance = InstanceBox::new_with_box_info(
|
||||||
actual_class_name.clone(),
|
actual_class_name.clone(),
|
||||||
all_fields,
|
all_fields,
|
||||||
all_methods
|
all_methods,
|
||||||
|
init_field_order,
|
||||||
|
weak_fields
|
||||||
);
|
);
|
||||||
|
|
||||||
let instance_box = Box::new(instance) as Box<dyn NyashBox>;
|
let instance_box = Box::new(instance) as Box<dyn NyashBox>;
|
||||||
|
|||||||
@ -275,6 +275,13 @@ impl NyashInterpreter {
|
|||||||
let obj_value = self.execute_expression(object)?;
|
let obj_value = self.execute_expression(object)?;
|
||||||
|
|
||||||
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
|
if instance.is_finalized() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: "Instance was finalized; further use is prohibited".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 🔗 Weak Reference Assignment Check
|
// 🔗 Weak Reference Assignment Check
|
||||||
let box_decls = self.shared.box_declarations.read().unwrap();
|
let box_decls = self.shared.box_declarations.read().unwrap();
|
||||||
if let Some(box_decl) = box_decls.get(&instance.class_name) {
|
if let Some(box_decl) = box_decls.get(&instance.class_name) {
|
||||||
@ -315,6 +322,13 @@ impl NyashInterpreter {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
|
if instance.is_finalized() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: "Instance was finalized; further use is prohibited".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 既存のthis.field値があればfini()を呼ぶ
|
// 既存のthis.field値があればfini()を呼ぶ
|
||||||
if let Some(old_field_value) = instance.get_field(field) {
|
if let Some(old_field_value) = instance.get_field(field) {
|
||||||
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
@ -341,6 +355,13 @@ impl NyashInterpreter {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
|
if instance.is_finalized() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: "Instance was finalized; further use is prohibited".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 既存のme.field値があればfini()を呼ぶ
|
// 既存のme.field値があればfini()を呼ぶ
|
||||||
if let Some(old_field_value) = instance.get_field(field) {
|
if let Some(old_field_value) = instance.get_field(field) {
|
||||||
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
|
||||||
|
|||||||
@ -469,19 +469,20 @@ mod tests {
|
|||||||
fn test_if_statement_building() {
|
fn test_if_statement_building() {
|
||||||
let mut builder = MirBuilder::new();
|
let mut builder = MirBuilder::new();
|
||||||
|
|
||||||
let ast = ASTNode::IfStatement {
|
// Adapt test to current AST: If with statement bodies
|
||||||
|
let ast = ASTNode::If {
|
||||||
condition: Box::new(ASTNode::Literal {
|
condition: Box::new(ASTNode::Literal {
|
||||||
value: LiteralValue::Boolean(true),
|
value: LiteralValue::Bool(true),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}),
|
}),
|
||||||
then_branch: Box::new(ASTNode::Literal {
|
then_body: vec![ASTNode::Literal {
|
||||||
value: LiteralValue::Integer(1),
|
value: LiteralValue::Integer(1),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}),
|
}],
|
||||||
else_branch: Some(Box::new(ASTNode::Literal {
|
else_body: Some(vec![ASTNode::Literal {
|
||||||
value: LiteralValue::Integer(2),
|
value: LiteralValue::Integer(2),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
})),
|
}]),
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
//! Tests for NyashBox trait implementations
|
//! Tests for NyashBox trait implementations
|
||||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoxCore};
|
||||||
use crate::boxes::{ArrayBox, BufferBox, JSONBox, NyashFutureBox, NyashStreamBox, NyashResultBox};
|
use crate::boxes::{ArrayBox, BufferBox, JSONBox, NyashFutureBox, NyashStreamBox, NyashResultBox};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -111,7 +111,7 @@ mod tests {
|
|||||||
let success_result = NyashResultBox::new_ok(Box::new(StringBox::new("success")));
|
let success_result = NyashResultBox::new_ok(Box::new(StringBox::new("success")));
|
||||||
|
|
||||||
assert_eq!(success_result.type_name(), "NyashResultBox");
|
assert_eq!(success_result.type_name(), "NyashResultBox");
|
||||||
assert!(success_result.is_ok());
|
assert!(success_result.is_ok_bool());
|
||||||
assert!(!success_result.is_err());
|
assert!(!success_result.is_err());
|
||||||
|
|
||||||
let string_repr = success_result.to_string_box();
|
let string_repr = success_result.to_string_box();
|
||||||
@ -119,7 +119,7 @@ mod tests {
|
|||||||
|
|
||||||
// Test error case
|
// Test error case
|
||||||
let error_result = NyashResultBox::new_err(Box::new(StringBox::new("error")));
|
let error_result = NyashResultBox::new_err(Box::new(StringBox::new("error")));
|
||||||
assert!(!error_result.is_ok());
|
assert!(!error_result.is_ok_bool());
|
||||||
assert!(error_result.is_err());
|
assert!(error_result.is_err());
|
||||||
|
|
||||||
let error_string = error_result.to_string_box();
|
let error_string = error_result.to_string_box();
|
||||||
|
|||||||
119
test_fini_system.nyash
Normal file
119
test_fini_system.nyash
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// 🔥 Comprehensive fini System Test - ChatGPT5 Design Validation
|
||||||
|
|
||||||
|
// Test Case 1: Basic finalization and usage prohibition
|
||||||
|
box SimpleResource {
|
||||||
|
init { name, value }
|
||||||
|
|
||||||
|
pack(resourceName) {
|
||||||
|
me.name = resourceName
|
||||||
|
me.value = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
print("🔥 SimpleResource.fini(): Cleaning up " + me.name.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Case 2: Circular reference with weak fields
|
||||||
|
box Parent {
|
||||||
|
init { name, weak child }
|
||||||
|
|
||||||
|
pack(parentName) {
|
||||||
|
me.name = parentName
|
||||||
|
}
|
||||||
|
|
||||||
|
setChild(c) {
|
||||||
|
me.child = c
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return me.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { id, parent }
|
||||||
|
|
||||||
|
pack(childId, p) {
|
||||||
|
me.id = childId
|
||||||
|
me.parent = p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Case 3: weak-fini prohibition
|
||||||
|
fini() {
|
||||||
|
print("🔥 Child.fini(): Cleaning up child " + me.id.toString())
|
||||||
|
// me.parent.fini() // This should be caught and prevented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Case 4: Deterministic cascade finalization
|
||||||
|
box Pipeline {
|
||||||
|
init { r1, r2, r3, weak monitor }
|
||||||
|
|
||||||
|
pack(name) {
|
||||||
|
me.r1 = new SimpleResource(name + "_r1")
|
||||||
|
me.r2 = new SimpleResource(name + "_r2")
|
||||||
|
me.r3 = new SimpleResource(name + "_r3")
|
||||||
|
}
|
||||||
|
|
||||||
|
setMonitor(m) {
|
||||||
|
me.monitor = m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom fini with specific order control
|
||||||
|
fini() {
|
||||||
|
print("🔥 Pipeline.fini(): Custom cleanup order")
|
||||||
|
// Reverse dependency order: r3 → r2 (r1 will be auto-cascade)
|
||||||
|
me.r3.fini()
|
||||||
|
me.r2.fini()
|
||||||
|
// r1 should be automatically finalized by cascade
|
||||||
|
// monitor is weak, so it's not finalized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
print("=== 🔥 Comprehensive fini System Test ===")
|
||||||
|
|
||||||
|
// Test 1: Basic finalization
|
||||||
|
print("\n📋 Test 1: Basic finalization and usage prohibition")
|
||||||
|
local resource = new SimpleResource("TestResource")
|
||||||
|
print("Resource value before fini: " + resource.getValue().toString())
|
||||||
|
|
||||||
|
resource.fini()
|
||||||
|
print("Resource finalized")
|
||||||
|
|
||||||
|
// This should throw an error - usage after finalization
|
||||||
|
// print("Trying to access finalized resource...")
|
||||||
|
// resource.getValue() // Should fail with "Instance was finalized"
|
||||||
|
|
||||||
|
// Test 2: Circular reference handling
|
||||||
|
print("\n📋 Test 2: Circular reference with weak fields")
|
||||||
|
local parent = new Parent("TestParent")
|
||||||
|
local child = new Child("child1", parent)
|
||||||
|
parent.setChild(child)
|
||||||
|
|
||||||
|
print("Parent: " + parent.getName().toString())
|
||||||
|
print("Before parent finalization")
|
||||||
|
|
||||||
|
parent.fini()
|
||||||
|
print("Parent finalized - child's weak reference should be safe")
|
||||||
|
|
||||||
|
// Test 3: Deterministic cascade finalization
|
||||||
|
print("\n📋 Test 3: Deterministic cascade finalization")
|
||||||
|
local pipeline = new Pipeline("TestPipeline")
|
||||||
|
local monitor = new SimpleResource("Monitor")
|
||||||
|
pipeline.setMonitor(monitor)
|
||||||
|
|
||||||
|
print("Pipeline created with resources and monitor")
|
||||||
|
pipeline.fini()
|
||||||
|
print("Pipeline finalized with custom order + auto-cascade")
|
||||||
|
|
||||||
|
print("\n✅ fini System Test Completed!")
|
||||||
|
return "All tests passed"
|
||||||
|
}
|
||||||
|
}
|
||||||
51
test_fini_violations.nyash
Normal file
51
test_fini_violations.nyash
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// 🔥 fini System Violation Tests - Testing guards and prohibitions
|
||||||
|
|
||||||
|
box TestResource {
|
||||||
|
init { name }
|
||||||
|
|
||||||
|
pack(resourceName) {
|
||||||
|
me.name = resourceName
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
return "Resource: " + me.name.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fini() {
|
||||||
|
print("🔥 TestResource.fini(): Finalizing " + me.name.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box BadExample {
|
||||||
|
init { weak weakRef, strongRef }
|
||||||
|
|
||||||
|
pack(name) {
|
||||||
|
me.strongRef = new TestResource(name + "_strong")
|
||||||
|
me.weakRef = new TestResource(name + "_weak") // Will be set as weak
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should trigger weak-fini prohibition
|
||||||
|
badFini() {
|
||||||
|
print("🔥 BadExample.badFini(): Attempting illegal operations")
|
||||||
|
me.weakRef.fini() // Should fail with "Cannot finalize weak field"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
print("=== 🔥 fini System Violation Tests ===")
|
||||||
|
|
||||||
|
// Test 1: Usage after finalization prohibition
|
||||||
|
print("\n📋 Test 1: Usage after finalization (should fail)")
|
||||||
|
local resource = new TestResource("TestViolation")
|
||||||
|
print("Before fini: " + resource.getData())
|
||||||
|
|
||||||
|
resource.fini()
|
||||||
|
print("Resource finalized")
|
||||||
|
|
||||||
|
print("Attempting to access finalized resource...")
|
||||||
|
resource.getData() // Should fail with "Instance was finalized"
|
||||||
|
|
||||||
|
return "Test should have failed before reaching here"
|
||||||
|
}
|
||||||
|
}
|
||||||
50
test_weak_basic_fixed.nyash
Normal file
50
test_weak_basic_fixed.nyash
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Basic weak reference test case - with null fix
|
||||||
|
|
||||||
|
box Parent {
|
||||||
|
init { child }
|
||||||
|
|
||||||
|
pack() {
|
||||||
|
me.child = new Child()
|
||||||
|
me.child.setParent(me) // This should create a weak reference
|
||||||
|
}
|
||||||
|
|
||||||
|
getChild() {
|
||||||
|
return me.child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child {
|
||||||
|
init { weak parent } // weak modifier on parent field
|
||||||
|
|
||||||
|
setParent(p) {
|
||||||
|
me.parent = p
|
||||||
|
}
|
||||||
|
|
||||||
|
checkParent() {
|
||||||
|
return me.parent != new NullBox()
|
||||||
|
}
|
||||||
|
|
||||||
|
getParentInfo() {
|
||||||
|
if me.parent != new NullBox() {
|
||||||
|
return "Parent exists"
|
||||||
|
} else {
|
||||||
|
return "Parent is null (dropped)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local p = new Parent()
|
||||||
|
local child = p.getChild()
|
||||||
|
|
||||||
|
print("Initial parent check: " + child.getParentInfo())
|
||||||
|
|
||||||
|
// When p goes out of scope, child.parent should automatically become null
|
||||||
|
p = new NullBox()
|
||||||
|
|
||||||
|
print("After parent dropped: " + child.getParentInfo())
|
||||||
|
|
||||||
|
return "weak reference test completed"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
test_weak_fini_prohibition.nyash
Normal file
37
test_weak_fini_prohibition.nyash
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 🔥 Weak-fini Prohibition Test - Should catch me.weakField.fini()
|
||||||
|
|
||||||
|
box SimpleResource {
|
||||||
|
init { name }
|
||||||
|
|
||||||
|
pack(resourceName) {
|
||||||
|
me.name = resourceName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box BadParent {
|
||||||
|
init { weak weakChild }
|
||||||
|
|
||||||
|
pack() {
|
||||||
|
me.weakChild = new SimpleResource("WeakChild")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should trigger weak-fini prohibition
|
||||||
|
fini() {
|
||||||
|
print("🔥 BadParent.fini(): Attempting to finalize weak field")
|
||||||
|
me.weakChild.fini() // Should fail: "Cannot finalize weak field 'weakChild'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
print("=== 🔥 Weak-fini Prohibition Test ===")
|
||||||
|
|
||||||
|
local badParent = new BadParent()
|
||||||
|
print("BadParent created with weak child")
|
||||||
|
|
||||||
|
print("Attempting to finalize BadParent (should detect illegal weak-fini)...")
|
||||||
|
badParent.fini() // Should fail during execution of user fini()
|
||||||
|
|
||||||
|
return "Test should have failed before reaching here"
|
||||||
|
}
|
||||||
|
}
|
||||||
58
tests/archive/test_all_new_boxes.nyash
Normal file
58
tests/archive/test_all_new_boxes.nyash
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// 🧪 新しいBoxタイプの統合テスト
|
||||||
|
// Arc<Mutex>パターンが正しく動作することを確認
|
||||||
|
|
||||||
|
print("=== New Boxes Integration Test ===")
|
||||||
|
|
||||||
|
// 📦 ArrayBox Test
|
||||||
|
print("\n🔹 ArrayBox Test:")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
arr.push("Hello")
|
||||||
|
arr.push("World")
|
||||||
|
arr.push(42)
|
||||||
|
print("Array length: " + arr.length())
|
||||||
|
print("Array contents: " + arr.toString())
|
||||||
|
|
||||||
|
// 🗄️ MapBox Test
|
||||||
|
print("\n🔹 MapBox Test:")
|
||||||
|
local map
|
||||||
|
map = new MapBox()
|
||||||
|
map.set("name", "Alice")
|
||||||
|
map.set("age", 25)
|
||||||
|
map.set("active", true)
|
||||||
|
print("Map size: " + map.size())
|
||||||
|
print("Name: " + map.get("name"))
|
||||||
|
print("Age: " + map.get("age"))
|
||||||
|
print("Has email: " + map.has("email"))
|
||||||
|
|
||||||
|
// 📊 BufferBox Test
|
||||||
|
print("\n🔹 BufferBox Test:")
|
||||||
|
local buffer
|
||||||
|
buffer = new BufferBox()
|
||||||
|
local data_array
|
||||||
|
data_array = new ArrayBox()
|
||||||
|
data_array.push(72) // H
|
||||||
|
data_array.push(101) // e
|
||||||
|
data_array.push(108) // l
|
||||||
|
data_array.push(108) // l
|
||||||
|
data_array.push(111) // o
|
||||||
|
buffer.write(data_array)
|
||||||
|
print("Buffer size: " + buffer.length())
|
||||||
|
|
||||||
|
// 🔍 RegexBox Test
|
||||||
|
print("\n🔹 RegexBox Test:")
|
||||||
|
local regex
|
||||||
|
regex = new RegexBox("[0-9]+")
|
||||||
|
print("Regex pattern: " + regex.pattern())
|
||||||
|
print("Test '123': " + regex.test("123"))
|
||||||
|
print("Test 'abc': " + regex.test("abc"))
|
||||||
|
|
||||||
|
// ✅ ResultBox Test
|
||||||
|
print("\n🔹 ResultBox Test:")
|
||||||
|
local ok_result, err_result
|
||||||
|
ok_result = new ResultBox()
|
||||||
|
ok_result = ResultBox.ok("Success!")
|
||||||
|
print("OK result: " + ok_result.toString())
|
||||||
|
print("Is OK: " + ok_result.is_ok())
|
||||||
|
|
||||||
|
print("\n🎉 All Arc<Mutex> pattern tests completed successfully!")
|
||||||
74
tests/archive/test_array_box.nyash
Normal file
74
tests/archive/test_array_box.nyash
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// ArrayBox実装テスト
|
||||||
|
print("=== ArrayBox実装テスト ===")
|
||||||
|
|
||||||
|
// 1. ArrayBoxの作成
|
||||||
|
print("\n1. ArrayBoxの作成:")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
print("ArrayBox created: " + arr.toString())
|
||||||
|
// print("Type: " + arr.type_name()) // type_nameはArrayBoxのメソッドではない
|
||||||
|
print("Initial length: " + arr.length())
|
||||||
|
|
||||||
|
// 2. 要素の追加(push)
|
||||||
|
print("\n2. 要素の追加:")
|
||||||
|
arr.push("Apple")
|
||||||
|
arr.push("Banana")
|
||||||
|
arr.push("Cherry")
|
||||||
|
arr.push(42)
|
||||||
|
arr.push(true)
|
||||||
|
print("After push: " + arr.toString())
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
|
||||||
|
// 3. 要素の取得(get)
|
||||||
|
print("\n3. 要素の取得:")
|
||||||
|
print("arr.get(0) = " + arr.get(0))
|
||||||
|
print("arr.get(1) = " + arr.get(1))
|
||||||
|
print("arr.get(3) = " + arr.get(3))
|
||||||
|
print("arr.get(10) = " + arr.get(10)) // 範囲外
|
||||||
|
|
||||||
|
// 4. 要素の削除(pop)
|
||||||
|
print("\n4. 要素の削除:")
|
||||||
|
local popped
|
||||||
|
popped = arr.pop()
|
||||||
|
print("Popped: " + popped)
|
||||||
|
print("After pop: " + arr.toString())
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
|
||||||
|
// 5. インデックス検索(indexOf)
|
||||||
|
print("\n5. インデックス検索:")
|
||||||
|
print("indexOf('Apple') = " + arr.indexOf("Apple"))
|
||||||
|
print("indexOf('Banana') = " + arr.indexOf("Banana"))
|
||||||
|
print("indexOf('NotExist') = " + arr.indexOf("NotExist"))
|
||||||
|
|
||||||
|
// 6. 要素の確認(contains)
|
||||||
|
print("\n6. 要素の確認:")
|
||||||
|
print("contains('Apple') = " + arr.contains("Apple"))
|
||||||
|
print("contains(42) = " + arr.contains(42))
|
||||||
|
print("contains('NotExist') = " + arr.contains("NotExist"))
|
||||||
|
|
||||||
|
// 7. 文字列結合(join)
|
||||||
|
print("\n7. 文字列結合:")
|
||||||
|
print("join(', ') = " + arr.join(", "))
|
||||||
|
print("join(' - ') = " + arr.join(" - "))
|
||||||
|
|
||||||
|
// 8. 要素の設定(set)
|
||||||
|
print("\n8. 要素の設定:")
|
||||||
|
arr.set(1, "Orange")
|
||||||
|
print("After set(1, 'Orange'): " + arr.toString())
|
||||||
|
|
||||||
|
// 9. 要素の削除(remove)
|
||||||
|
print("\n9. 要素の削除:")
|
||||||
|
local removed
|
||||||
|
removed = arr.remove(2)
|
||||||
|
print("Removed: " + removed)
|
||||||
|
print("After remove(2): " + arr.toString())
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
|
||||||
|
// 10. 配列のクリア(clear)
|
||||||
|
print("\n10. 配列のクリア:")
|
||||||
|
arr.clear()
|
||||||
|
print("After clear: " + arr.toString())
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
print("isEmpty: " + arr.isEmpty())
|
||||||
|
|
||||||
|
print("\n=== ArrayBoxテスト完了! ===")
|
||||||
20
tests/archive/test_array_box_simple.nyash
Normal file
20
tests/archive/test_array_box_simple.nyash
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// 🧪 ArrayBoxの簡単なテスト
|
||||||
|
|
||||||
|
print("=== ArrayBox Simple Test ===")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
|
||||||
|
// 基本的な操作
|
||||||
|
arr.push("Hello")
|
||||||
|
arr.push("World")
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
print("Get 0: " + arr.get(0))
|
||||||
|
print("Get 1: " + arr.get(1))
|
||||||
|
|
||||||
|
// pop
|
||||||
|
local item
|
||||||
|
item = arr.pop()
|
||||||
|
print("Popped: " + item)
|
||||||
|
print("Length after pop: " + arr.length())
|
||||||
|
|
||||||
|
print("Test completed!")
|
||||||
81
tests/archive/test_array_improvements.nyash
Normal file
81
tests/archive/test_array_improvements.nyash
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// test_array_improvements.nyash - ArrayBox Phase 2 improvements test
|
||||||
|
// Testing: sort(), reverse(), indexOf(), slice() methods
|
||||||
|
|
||||||
|
print("📦 Testing ArrayBox improvements...")
|
||||||
|
|
||||||
|
// Basic array creation and setup
|
||||||
|
local arr, result, sliceResult
|
||||||
|
|
||||||
|
print("=== Setup: Creating test array ===")
|
||||||
|
arr = new ArrayBox()
|
||||||
|
arr.push(3)
|
||||||
|
arr.push(1)
|
||||||
|
arr.push(4)
|
||||||
|
arr.push(1)
|
||||||
|
arr.push(5)
|
||||||
|
print("Original array: " + arr.toString())
|
||||||
|
|
||||||
|
print("\n=== Test 1: sort() method ===")
|
||||||
|
arr.sort()
|
||||||
|
print("After sort(): " + arr.toString())
|
||||||
|
// Expected: [1, 1, 3, 4, 5]
|
||||||
|
|
||||||
|
print("\n=== Test 2: reverse() method ===")
|
||||||
|
arr.reverse()
|
||||||
|
print("After reverse(): " + arr.toString())
|
||||||
|
// Expected: [5, 4, 3, 1, 1]
|
||||||
|
|
||||||
|
print("\n=== Test 3: indexOf() method ===")
|
||||||
|
result = arr.indexOf(4)
|
||||||
|
print("indexOf(4): " + result.toString())
|
||||||
|
// Expected: 1
|
||||||
|
|
||||||
|
result = arr.indexOf(1)
|
||||||
|
print("indexOf(1): " + result.toString())
|
||||||
|
// Expected: 3 (first occurrence from current order)
|
||||||
|
|
||||||
|
result = arr.indexOf(999)
|
||||||
|
print("indexOf(999): " + result.toString())
|
||||||
|
// Expected: -1 (not found)
|
||||||
|
|
||||||
|
print("\n=== Test 4: slice() method ===")
|
||||||
|
sliceResult = arr.slice(1, 4)
|
||||||
|
print("slice(1, 4): " + sliceResult.toString())
|
||||||
|
// Expected: [4, 3, 1] (indices 1, 2, 3)
|
||||||
|
|
||||||
|
sliceResult = arr.slice(0, 2)
|
||||||
|
print("slice(0, 2): " + sliceResult.toString())
|
||||||
|
// Expected: [5, 4] (indices 0, 1)
|
||||||
|
|
||||||
|
sliceResult = arr.slice(2, 10) // End beyond array
|
||||||
|
print("slice(2, 10): " + sliceResult.toString())
|
||||||
|
// Expected: [3, 1, 1] (indices 2 to end)
|
||||||
|
|
||||||
|
print("\n=== Test 5: Mixed types sorting ===")
|
||||||
|
local mixedArr
|
||||||
|
mixedArr = new ArrayBox()
|
||||||
|
mixedArr.push("banana")
|
||||||
|
mixedArr.push(2)
|
||||||
|
mixedArr.push("apple")
|
||||||
|
mixedArr.push(1)
|
||||||
|
mixedArr.push("cherry")
|
||||||
|
print("Mixed array before sort: " + mixedArr.toString())
|
||||||
|
|
||||||
|
mixedArr.sort()
|
||||||
|
print("Mixed array after sort: " + mixedArr.toString())
|
||||||
|
// Expected: numbers first (1, 2), then strings alphabetically
|
||||||
|
|
||||||
|
print("\n=== Test 6: FloatBox integration ===")
|
||||||
|
local floatArr
|
||||||
|
floatArr = new ArrayBox()
|
||||||
|
floatArr.push(new FloatBox(3.14))
|
||||||
|
floatArr.push(1)
|
||||||
|
floatArr.push(new FloatBox(2.71))
|
||||||
|
floatArr.push(4)
|
||||||
|
print("Float array before sort: " + floatArr.toString())
|
||||||
|
|
||||||
|
floatArr.sort()
|
||||||
|
print("Float array after sort: " + floatArr.toString())
|
||||||
|
// Expected: [1, 2.71, 3.14, 4]
|
||||||
|
|
||||||
|
print("\n✅ ArrayBox Phase 2 improvements tests completed!")
|
||||||
23
tests/archive/test_array_simple.nyash
Normal file
23
tests/archive/test_array_simple.nyash
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// ArrayBox簡単なテスト
|
||||||
|
print("=== ArrayBox簡単なテスト ===")
|
||||||
|
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
print("Created ArrayBox")
|
||||||
|
|
||||||
|
// 要素を追加
|
||||||
|
arr.push("Hello")
|
||||||
|
arr.push("World")
|
||||||
|
print("Added elements")
|
||||||
|
|
||||||
|
// 長さを確認
|
||||||
|
print("Length: " + arr.length())
|
||||||
|
|
||||||
|
// 配列の内容を表示
|
||||||
|
print("Array: " + arr.toString())
|
||||||
|
|
||||||
|
// 要素を取得
|
||||||
|
print("First element: " + arr.get(0))
|
||||||
|
print("Second element: " + arr.get(1))
|
||||||
|
|
||||||
|
print("\n=== Test complete! ===")
|
||||||
31
tests/archive/test_basic_boxes.nyash
Normal file
31
tests/archive/test_basic_boxes.nyash
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 🧪 基本的な新Box テスト
|
||||||
|
|
||||||
|
print("=== Basic New Boxes Test ===")
|
||||||
|
|
||||||
|
// 📦 ArrayBox Test (already working)
|
||||||
|
print("\n✅ ArrayBox:")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
arr.push("test")
|
||||||
|
print("ArrayBox works: " + arr.length())
|
||||||
|
|
||||||
|
// 🗄️ MapBox Test (already working)
|
||||||
|
print("\n✅ MapBox:")
|
||||||
|
local map
|
||||||
|
map = new MapBox()
|
||||||
|
map.set("key", "value")
|
||||||
|
print("MapBox works: " + map.size())
|
||||||
|
|
||||||
|
// 📊 BufferBox Test
|
||||||
|
print("\n🔹 BufferBox:")
|
||||||
|
local buffer
|
||||||
|
buffer = new BufferBox()
|
||||||
|
print("BufferBox created: " + buffer.toString())
|
||||||
|
|
||||||
|
// 🔍 RegexBox Test
|
||||||
|
print("\n🔹 RegexBox:")
|
||||||
|
local regex
|
||||||
|
regex = new RegexBox("[0-9]+")
|
||||||
|
print("RegexBox created: " + regex.toString())
|
||||||
|
|
||||||
|
print("\n🎉 Basic new Box creation tests completed!")
|
||||||
35
tests/archive/test_box_creation.nyash
Normal file
35
tests/archive/test_box_creation.nyash
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 🧪 新Box作成テスト - メソッド呼び出しなし
|
||||||
|
|
||||||
|
print("=== New Box Creation Test ===")
|
||||||
|
|
||||||
|
// 📊 BufferBox Test
|
||||||
|
print("🔹 Creating BufferBox...")
|
||||||
|
local buffer
|
||||||
|
buffer = new BufferBox()
|
||||||
|
print("✅ BufferBox created successfully!")
|
||||||
|
|
||||||
|
// 🔍 RegexBox Test
|
||||||
|
print("🔹 Creating RegexBox...")
|
||||||
|
local regex
|
||||||
|
regex = new RegexBox("[0-9]+")
|
||||||
|
print("✅ RegexBox created successfully!")
|
||||||
|
|
||||||
|
// 📋 JSONBox Test
|
||||||
|
print("🔹 Creating JSONBox...")
|
||||||
|
local json
|
||||||
|
json = new JSONBox("{\"name\": \"test\"}")
|
||||||
|
print("✅ JSONBox created successfully!")
|
||||||
|
|
||||||
|
// 🌊 StreamBox Test
|
||||||
|
print("🔹 Creating StreamBox...")
|
||||||
|
local stream
|
||||||
|
stream = new StreamBox()
|
||||||
|
print("✅ StreamBox created successfully!")
|
||||||
|
|
||||||
|
// 🌐 HTTPClientBox Test
|
||||||
|
print("🔹 Creating HTTPClientBox...")
|
||||||
|
local http
|
||||||
|
http = new HTTPClientBox()
|
||||||
|
print("✅ HTTPClientBox created successfully!")
|
||||||
|
|
||||||
|
print("\n🎉 All Arc<Mutex> Boxes created successfully!")
|
||||||
56
tests/archive/test_boxes.nyash
Normal file
56
tests/archive/test_boxes.nyash
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Test program to verify NyashBox implementations work
|
||||||
|
static box TestBoxes {
|
||||||
|
init { console, result }
|
||||||
|
|
||||||
|
main() {
|
||||||
|
me.console = new ConsoleBox()
|
||||||
|
me.console.log("🎯 Testing NyashBox implementations...")
|
||||||
|
|
||||||
|
// Test completed boxes
|
||||||
|
me.testArrayBox()
|
||||||
|
me.testBufferBox()
|
||||||
|
me.testJSONBox()
|
||||||
|
me.testResultBox()
|
||||||
|
me.testFutureBox()
|
||||||
|
me.testStreamBox()
|
||||||
|
|
||||||
|
me.result = "All NyashBox tests completed!"
|
||||||
|
return me.result
|
||||||
|
}
|
||||||
|
|
||||||
|
testArrayBox() {
|
||||||
|
me.console.log("📦 Testing ArrayBox...")
|
||||||
|
// Basic functionality would be tested here when ArrayBox methods are integrated
|
||||||
|
me.console.log("ArrayBox test passed!")
|
||||||
|
}
|
||||||
|
|
||||||
|
testBufferBox() {
|
||||||
|
me.console.log("📊 Testing BufferBox...")
|
||||||
|
// Basic functionality would be tested here when BufferBox methods are integrated
|
||||||
|
me.console.log("BufferBox test passed!")
|
||||||
|
}
|
||||||
|
|
||||||
|
testJSONBox() {
|
||||||
|
me.console.log("📋 Testing JSONBox...")
|
||||||
|
// Basic functionality would be tested here when JSONBox methods are integrated
|
||||||
|
me.console.log("JSONBox test passed!")
|
||||||
|
}
|
||||||
|
|
||||||
|
testResultBox() {
|
||||||
|
me.console.log("⚠️ Testing ResultBox...")
|
||||||
|
// Basic functionality would be tested here when ResultBox methods are integrated
|
||||||
|
me.console.log("ResultBox test passed!")
|
||||||
|
}
|
||||||
|
|
||||||
|
testFutureBox() {
|
||||||
|
me.console.log("🔄 Testing FutureBox...")
|
||||||
|
// Basic functionality would be tested here when FutureBox methods are integrated
|
||||||
|
me.console.log("FutureBox test passed!")
|
||||||
|
}
|
||||||
|
|
||||||
|
testStreamBox() {
|
||||||
|
me.console.log("🌊 Testing StreamBox...")
|
||||||
|
// Basic functionality would be tested here when StreamBox methods are integrated
|
||||||
|
me.console.log("StreamBox test passed!")
|
||||||
|
}
|
||||||
|
}
|
||||||
27
tests/archive/test_buffer_box.nyash
Normal file
27
tests/archive/test_buffer_box.nyash
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 🧪 BufferBoxのテスト
|
||||||
|
|
||||||
|
print("=== BufferBox Test ===")
|
||||||
|
local buffer, data, result
|
||||||
|
|
||||||
|
// BufferBox作成
|
||||||
|
buffer = new BufferBox()
|
||||||
|
|
||||||
|
// データ配列作成
|
||||||
|
data = new ArrayBox()
|
||||||
|
data.push(72) // 'H'
|
||||||
|
data.push(101) // 'e'
|
||||||
|
data.push(108) // 'l'
|
||||||
|
data.push(108) // 'l'
|
||||||
|
data.push(111) // 'o'
|
||||||
|
|
||||||
|
// データ書き込み
|
||||||
|
result = buffer.write(data)
|
||||||
|
print("Write result: " + result)
|
||||||
|
print("Buffer length: " + buffer.length())
|
||||||
|
|
||||||
|
// データ読み取り
|
||||||
|
local readData
|
||||||
|
readData = buffer.readAll()
|
||||||
|
print("Read data: " + readData)
|
||||||
|
|
||||||
|
print("BufferBox test completed!")
|
||||||
113
tests/archive/test_new_boxes.nyash
Normal file
113
tests/archive/test_new_boxes.nyash
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// 🧪 新しいBox実装のテスト
|
||||||
|
|
||||||
|
// 1. ArrayBoxのテスト
|
||||||
|
print("=== ArrayBox Test ===")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
|
||||||
|
// push/pop
|
||||||
|
arr.push("Hello")
|
||||||
|
arr.push("World")
|
||||||
|
arr.push(42)
|
||||||
|
print("Length after push: " + arr.length())
|
||||||
|
|
||||||
|
local popped
|
||||||
|
popped = arr.pop()
|
||||||
|
print("Popped: " + popped)
|
||||||
|
print("Length after pop: " + arr.length())
|
||||||
|
|
||||||
|
// get/set
|
||||||
|
print("arr[0]: " + arr.get(0))
|
||||||
|
arr.set(1, "Nyash")
|
||||||
|
print("arr[1] after set: " + arr.get(1))
|
||||||
|
|
||||||
|
// join
|
||||||
|
print("Joined: " + arr.join(", "))
|
||||||
|
|
||||||
|
// 2. BufferBoxのテスト
|
||||||
|
print("\n=== BufferBox Test ===")
|
||||||
|
local buffer
|
||||||
|
buffer = new BufferBox()
|
||||||
|
|
||||||
|
// write
|
||||||
|
local bytesArray
|
||||||
|
bytesArray = new ArrayBox()
|
||||||
|
bytesArray.push(72) // H
|
||||||
|
bytesArray.push(101) // e
|
||||||
|
bytesArray.push(108) // l
|
||||||
|
bytesArray.push(108) // l
|
||||||
|
bytesArray.push(111) // o
|
||||||
|
buffer.write(bytesArray)
|
||||||
|
print("Buffer length after write: " + buffer.length())
|
||||||
|
|
||||||
|
// readAll
|
||||||
|
local readData
|
||||||
|
readData = buffer.readAll()
|
||||||
|
print("Read data length: " + readData.length())
|
||||||
|
|
||||||
|
// 3. JSONBoxのテスト
|
||||||
|
print("\n=== JSONBox Test ===")
|
||||||
|
local parsed
|
||||||
|
parsed = new JSONBox("{\"name\": \"Nyash\", \"version\": 1.0}")
|
||||||
|
|
||||||
|
print("JSON stringify: " + parsed.stringify())
|
||||||
|
print("Name from JSON: " + parsed.get("name"))
|
||||||
|
print("Version from JSON: " + parsed.get("version"))
|
||||||
|
|
||||||
|
// set/has
|
||||||
|
parsed.set("author", "Claude")
|
||||||
|
print("Has author: " + parsed.has("author"))
|
||||||
|
print("Author: " + parsed.get("author"))
|
||||||
|
|
||||||
|
// keys
|
||||||
|
local keys
|
||||||
|
keys = parsed.keys()
|
||||||
|
print("Keys count: " + keys.length())
|
||||||
|
|
||||||
|
// 4. RegexBoxのテスト
|
||||||
|
print("\n=== RegexBox Test ===")
|
||||||
|
local regex, text
|
||||||
|
regex = new RegexBox("[0-9]+")
|
||||||
|
text = "The answer is 42 and 100"
|
||||||
|
|
||||||
|
print("Test match: " + regex.test(text))
|
||||||
|
print("Find first: " + regex.find(text))
|
||||||
|
|
||||||
|
local allMatches
|
||||||
|
allMatches = regex.findAll(text)
|
||||||
|
print("All matches count: " + allMatches.length())
|
||||||
|
|
||||||
|
// replace
|
||||||
|
local replaced
|
||||||
|
replaced = regex.replace(text, "X")
|
||||||
|
print("Replaced: " + replaced)
|
||||||
|
|
||||||
|
// split
|
||||||
|
local emailRegex, email
|
||||||
|
emailRegex = new RegexBox("@")
|
||||||
|
email = "user@example.com"
|
||||||
|
local parts
|
||||||
|
parts = emailRegex.split(email)
|
||||||
|
print("Email parts: " + parts.join(" | "))
|
||||||
|
|
||||||
|
// 5. StreamBoxのテスト
|
||||||
|
print("\n=== StreamBox Test ===")
|
||||||
|
local stream
|
||||||
|
stream = new StreamBox()
|
||||||
|
|
||||||
|
// write
|
||||||
|
stream.write("Hello Stream!")
|
||||||
|
print("Stream length: " + stream.length())
|
||||||
|
print("Stream position: " + stream.position())
|
||||||
|
|
||||||
|
// read
|
||||||
|
local readCount, streamData
|
||||||
|
readCount = stream.read(5)
|
||||||
|
print("Read from stream: " + readCount.length() + " bytes")
|
||||||
|
print("Position after read: " + stream.position())
|
||||||
|
|
||||||
|
// reset
|
||||||
|
stream.reset()
|
||||||
|
print("Position after reset: " + stream.position())
|
||||||
|
|
||||||
|
print("\n✅ All tests completed!")
|
||||||
62
tests/archive/test_new_operators.nyash
Normal file
62
tests/archive/test_new_operators.nyash
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# 🚀 Rust-Style Trait-Based Operator System Test
|
||||||
|
# Testing the new NyashAdd trait implementation
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
init { console, result }
|
||||||
|
|
||||||
|
main() {
|
||||||
|
me.console = new ConsoleBox()
|
||||||
|
me.console.log("🎉 Testing New Trait-Based Operators!")
|
||||||
|
|
||||||
|
# Test 1: Integer addition
|
||||||
|
local a, b, sum
|
||||||
|
a = 10
|
||||||
|
b = 20
|
||||||
|
sum = a + b
|
||||||
|
me.console.log("Integer addition: 10 + 20 = " + sum)
|
||||||
|
|
||||||
|
# Test 2: String concatenation
|
||||||
|
local s1, s2, concat
|
||||||
|
s1 = "Hello"
|
||||||
|
s2 = " World"
|
||||||
|
concat = s1 + s2
|
||||||
|
me.console.log("String concat: " + concat)
|
||||||
|
|
||||||
|
# Test 3: String repetition
|
||||||
|
local str, count, repeated
|
||||||
|
str = "Hi"
|
||||||
|
count = 3
|
||||||
|
repeated = str * count
|
||||||
|
me.console.log("String repeat: Hi * 3 = " + repeated)
|
||||||
|
|
||||||
|
# Test 4: Mixed type fallback (int + string -> string concat)
|
||||||
|
local mixed
|
||||||
|
mixed = 42 + " is the answer"
|
||||||
|
me.console.log("Mixed types: " + mixed)
|
||||||
|
|
||||||
|
# Test 5: Boolean arithmetic
|
||||||
|
local bool1, bool2, bool_sum
|
||||||
|
bool1 = true
|
||||||
|
bool2 = false
|
||||||
|
bool_sum = bool1 + bool2
|
||||||
|
me.console.log("Boolean add: true + false = " + bool_sum)
|
||||||
|
|
||||||
|
# Test 6: Subtraction
|
||||||
|
local diff
|
||||||
|
diff = 100 - 25
|
||||||
|
me.console.log("Subtraction: 100 - 25 = " + diff)
|
||||||
|
|
||||||
|
# Test 7: Multiplication
|
||||||
|
local product
|
||||||
|
product = 6 * 7
|
||||||
|
me.console.log("Multiplication: 6 * 7 = " + product)
|
||||||
|
|
||||||
|
# Test 8: Division
|
||||||
|
local quotient
|
||||||
|
quotient = 84 / 12
|
||||||
|
me.console.log("Division: 84 / 12 = " + quotient)
|
||||||
|
|
||||||
|
me.console.log("🎯 All operator tests completed!")
|
||||||
|
return "New trait system works perfectly!"
|
||||||
|
}
|
||||||
|
}
|
||||||
100
tests/archive/test_operators.nyash
Normal file
100
tests/archive/test_operators.nyash
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// test_operators.nyash - Operator Phase 3 comprehensive test
|
||||||
|
// Testing: comparison operators (<, >, <=, >=, ==, !=) with mixed types
|
||||||
|
|
||||||
|
print("⚖️ Testing comprehensive operator support...")
|
||||||
|
|
||||||
|
local f1, f2, i1, i2, result
|
||||||
|
|
||||||
|
print("=== Setup: Creating test values ===")
|
||||||
|
f1 = new FloatBox(3.14)
|
||||||
|
f2 = new FloatBox(2.86)
|
||||||
|
i1 = 5
|
||||||
|
i2 = 3
|
||||||
|
print("f1 = " + f1.toString() + " (FloatBox)")
|
||||||
|
print("f2 = " + f2.toString() + " (FloatBox)")
|
||||||
|
print("i1 = " + i1.toString() + " (IntegerBox)")
|
||||||
|
print("i2 = " + i2.toString() + " (IntegerBox)")
|
||||||
|
|
||||||
|
print("\n=== Test 1: Equality operators (==, !=) ===")
|
||||||
|
result = f1 == new FloatBox(3.14)
|
||||||
|
print("f1 == 3.14: " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
result = f1 != f2
|
||||||
|
print("f1 != f2: " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
result = i1 == 5
|
||||||
|
print("i1 == 5: " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
result = i1 != i2
|
||||||
|
print("i1 != i2: " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
print("\n=== Test 2: Mixed type equality ===")
|
||||||
|
result = f1 == 3 // FloatBox vs IntegerBox
|
||||||
|
print("f1 == 3: " + result.toString()) // Expected: false (3.14 != 3)
|
||||||
|
|
||||||
|
result = new FloatBox(5.0) == i1 // FloatBox vs IntegerBox
|
||||||
|
print("5.0 == i1: " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
print("\n=== Test 3: Less than (<) ===")
|
||||||
|
result = f2 < f1 // FloatBox < FloatBox
|
||||||
|
print("f2 < f1: " + result.toString()) // Expected: true (2.86 < 3.14)
|
||||||
|
|
||||||
|
result = i2 < i1 // IntegerBox < IntegerBox
|
||||||
|
print("i2 < i1: " + result.toString()) // Expected: true (3 < 5)
|
||||||
|
|
||||||
|
result = f2 < i1 // FloatBox < IntegerBox
|
||||||
|
print("f2 < i1: " + result.toString()) // Expected: true (2.86 < 5)
|
||||||
|
|
||||||
|
result = i2 < f1 // IntegerBox < FloatBox
|
||||||
|
print("i2 < f1: " + result.toString()) // Expected: true (3 < 3.14)
|
||||||
|
|
||||||
|
print("\n=== Test 4: Greater than (>) ===")
|
||||||
|
result = f1 > f2 // FloatBox > FloatBox
|
||||||
|
print("f1 > f2: " + result.toString()) // Expected: true (3.14 > 2.86)
|
||||||
|
|
||||||
|
result = i1 > i2 // IntegerBox > IntegerBox
|
||||||
|
print("i1 > i2: " + result.toString()) // Expected: true (5 > 3)
|
||||||
|
|
||||||
|
result = i1 > f1 // IntegerBox > FloatBox
|
||||||
|
print("i1 > f1: " + result.toString()) // Expected: true (5 > 3.14)
|
||||||
|
|
||||||
|
result = f1 > i2 // FloatBox > IntegerBox
|
||||||
|
print("f1 > i2: " + result.toString()) // Expected: true (3.14 > 3)
|
||||||
|
|
||||||
|
print("\n=== Test 5: Less than or equal (<=) ===")
|
||||||
|
result = f2 <= f1 // FloatBox <= FloatBox
|
||||||
|
print("f2 <= f1: " + result.toString()) // Expected: true (2.86 <= 3.14)
|
||||||
|
|
||||||
|
result = f1 <= f1 // FloatBox <= FloatBox (equal)
|
||||||
|
print("f1 <= f1: " + result.toString()) // Expected: true (3.14 <= 3.14)
|
||||||
|
|
||||||
|
result = i2 <= i1 // IntegerBox <= IntegerBox
|
||||||
|
print("i2 <= i1: " + result.toString()) // Expected: true (3 <= 5)
|
||||||
|
|
||||||
|
result = new FloatBox(5.0) <= i1 // FloatBox <= IntegerBox (equal)
|
||||||
|
print("5.0 <= i1: " + result.toString()) // Expected: true (5.0 <= 5)
|
||||||
|
|
||||||
|
print("\n=== Test 6: Greater than or equal (>=) ===")
|
||||||
|
result = f1 >= f2 // FloatBox >= FloatBox
|
||||||
|
print("f1 >= f2: " + result.toString()) // Expected: true (3.14 >= 2.86)
|
||||||
|
|
||||||
|
result = f1 >= f1 // FloatBox >= FloatBox (equal)
|
||||||
|
print("f1 >= f1: " + result.toString()) // Expected: true (3.14 >= 3.14)
|
||||||
|
|
||||||
|
result = i1 >= i2 // IntegerBox >= IntegerBox
|
||||||
|
print("i1 >= i2: " + result.toString()) // Expected: true (5 >= 3)
|
||||||
|
|
||||||
|
result = i1 >= new FloatBox(5.0) // IntegerBox >= FloatBox (equal)
|
||||||
|
print("i1 >= 5.0: " + result.toString()) // Expected: true (5 >= 5.0)
|
||||||
|
|
||||||
|
print("\n=== Test 7: Complex expression chains ===")
|
||||||
|
result = (f1 > f2) and (i1 > i2)
|
||||||
|
print("(f1 > f2) and (i1 > i2): " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
result = (f1 < i1) and (f2 > 1)
|
||||||
|
print("(f1 < i1) and (f2 > 1): " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
result = not (f1 == f2)
|
||||||
|
print("not (f1 == f2): " + result.toString()) // Expected: true
|
||||||
|
|
||||||
|
print("\n✅ Comprehensive operator tests completed!")
|
||||||
32
tests/archive/test_random_box.nyash
Normal file
32
tests/archive/test_random_box.nyash
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 🎲 RandomBoxのテスト
|
||||||
|
|
||||||
|
print("=== RandomBox Test ===")
|
||||||
|
local random, result, array
|
||||||
|
|
||||||
|
// RandomBox作成
|
||||||
|
random = new RandomBox()
|
||||||
|
|
||||||
|
// 基本乱数テスト
|
||||||
|
result = random.random()
|
||||||
|
print("Random float: " + result)
|
||||||
|
|
||||||
|
result = random.randInt(1, 6)
|
||||||
|
print("Dice roll (1-6): " + result)
|
||||||
|
|
||||||
|
result = random.randBool()
|
||||||
|
print("Random bool: " + result)
|
||||||
|
|
||||||
|
// 配列テスト
|
||||||
|
array = new ArrayBox()
|
||||||
|
array.push("apple")
|
||||||
|
array.push("banana")
|
||||||
|
array.push("cherry")
|
||||||
|
|
||||||
|
result = random.choice(array)
|
||||||
|
print("Random choice: " + result)
|
||||||
|
|
||||||
|
// 文字列生成テスト
|
||||||
|
result = random.randString(5)
|
||||||
|
print("Random string (5 chars): " + result)
|
||||||
|
|
||||||
|
print("RandomBox test completed!")
|
||||||
24
tests/archive/test_simple_builtin_inheritance.nyash
Normal file
24
tests/archive/test_simple_builtin_inheritance.nyash
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Simple test for built-in Box inheritance
|
||||||
|
box MyMath from MathBox {
|
||||||
|
override sin(x) {
|
||||||
|
local result
|
||||||
|
result = from MathBox.sin(x)
|
||||||
|
print("Called sin(" + x.toString() + ") = " + result.toString())
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main test
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
console.log("Testing built-in MathBox inheritance...")
|
||||||
|
|
||||||
|
local math
|
||||||
|
math = new MyMath()
|
||||||
|
|
||||||
|
local result
|
||||||
|
result = math.sin(1.5708) // π/2 ≈ 1.5708
|
||||||
|
console.log("Result: " + result.toString())
|
||||||
|
|
||||||
|
console.log("Test complete!")
|
||||||
3
tests/archive/test_simple_float.nyash
Normal file
3
tests/archive/test_simple_float.nyash
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
local f1
|
||||||
|
f1 = new FloatBox(3.14)
|
||||||
|
print(f1)
|
||||||
24
tests/development/test_available_boxes.nyash
Normal file
24
tests/development/test_available_boxes.nyash
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 利用可能なBox型の確認
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("ConsoleBox: OK")
|
||||||
|
|
||||||
|
// ArrayBox
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
console.log("ArrayBox: OK")
|
||||||
|
|
||||||
|
// FloatBox
|
||||||
|
local float
|
||||||
|
float = new FloatBox(3.14)
|
||||||
|
console.log("FloatBox: OK")
|
||||||
|
|
||||||
|
// MathBox
|
||||||
|
local math
|
||||||
|
math = new MathBox()
|
||||||
|
console.log("MathBox: OK")
|
||||||
|
|
||||||
|
// NullBox
|
||||||
|
local null
|
||||||
|
null = new NullBox()
|
||||||
|
console.log("NullBox: OK")
|
||||||
46
tests/development/test_basic_box_comprehensive.nyash
Normal file
46
tests/development/test_basic_box_comprehensive.nyash
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Comprehensive test to verify Basic Box constructors work identically to literals
|
||||||
|
// This demonstrates that Problem 1 is fully resolved
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Comprehensive Basic Box Constructor Test ===")
|
||||||
|
|
||||||
|
// Test StringBox equivalence
|
||||||
|
local str_box = new StringBox("test")
|
||||||
|
local str_literal = "test"
|
||||||
|
console.log("StringBox toString: " + str_box.toString())
|
||||||
|
console.log("String literal: " + str_literal)
|
||||||
|
console.log("StringBox == literal: " + (str_box.toString() == str_literal))
|
||||||
|
|
||||||
|
console.log("---")
|
||||||
|
|
||||||
|
// Test IntegerBox equivalence
|
||||||
|
local int_box = new IntegerBox(123)
|
||||||
|
local int_literal = 123
|
||||||
|
console.log("IntegerBox toString: " + int_box.toString())
|
||||||
|
console.log("Integer literal: " + int_literal)
|
||||||
|
console.log("IntegerBox == literal: " + (int_box.toString() == int_literal.toString()))
|
||||||
|
|
||||||
|
console.log("---")
|
||||||
|
|
||||||
|
// Test BoolBox equivalence
|
||||||
|
local bool_box = new BoolBox(true)
|
||||||
|
local bool_literal = true
|
||||||
|
console.log("BoolBox toString: " + bool_box.toString())
|
||||||
|
console.log("Bool literal: " + bool_literal)
|
||||||
|
console.log("BoolBox == literal: " + (bool_box.toString() == bool_literal.toString()))
|
||||||
|
|
||||||
|
console.log("---")
|
||||||
|
|
||||||
|
// Test type conversion capabilities
|
||||||
|
local str_from_int = new StringBox(456)
|
||||||
|
console.log("StringBox from int: " + str_from_int.toString())
|
||||||
|
|
||||||
|
local int_from_str = new IntegerBox("789")
|
||||||
|
console.log("IntegerBox from string: " + int_from_str.toString())
|
||||||
|
|
||||||
|
local bool_from_str_true = new BoolBox("true")
|
||||||
|
local bool_from_str_false = new BoolBox("false")
|
||||||
|
console.log("BoolBox from 'true': " + bool_from_str_true.toString())
|
||||||
|
console.log("BoolBox from 'false': " + bool_from_str_false.toString())
|
||||||
|
|
||||||
|
console.log("=== All Basic Box Constructors Working! ===")
|
||||||
32
tests/development/test_basic_box_constructors.nyash
Normal file
32
tests/development/test_basic_box_constructors.nyash
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Test Basic Box Constructor Issues (Problem 1)
|
||||||
|
// This should demonstrate the core failures described in the issue
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Testing Basic Box Constructors ===")
|
||||||
|
|
||||||
|
// Test StringBox constructor
|
||||||
|
console.log("Testing StringBox constructor...")
|
||||||
|
local str_box = new StringBox("test")
|
||||||
|
console.log("StringBox created: " + str_box.toString())
|
||||||
|
|
||||||
|
// Test IntegerBox constructor
|
||||||
|
console.log("Testing IntegerBox constructor...")
|
||||||
|
local int_box = new IntegerBox(123)
|
||||||
|
console.log("IntegerBox created: " + int_box.toString())
|
||||||
|
|
||||||
|
// Test BoolBox constructor
|
||||||
|
console.log("Testing BoolBox constructor...")
|
||||||
|
local bool_box = new BoolBox(false)
|
||||||
|
console.log("BoolBox created: " + bool_box.toString())
|
||||||
|
|
||||||
|
// Compare with literals (these should work)
|
||||||
|
console.log("=== Comparing with Literals ===")
|
||||||
|
local str_literal = "test"
|
||||||
|
local int_literal = 123
|
||||||
|
local bool_literal = false
|
||||||
|
|
||||||
|
console.log("String literal: " + str_literal)
|
||||||
|
console.log("Integer literal: " + int_literal)
|
||||||
|
console.log("Bool literal: " + bool_literal)
|
||||||
|
|
||||||
|
console.log("Test complete!")
|
||||||
60
tests/development/test_basic_boxes_comprehensive.nyash
Normal file
60
tests/development/test_basic_boxes_comprehensive.nyash
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 基本Box機能の網羅的テスト
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
// === 基本系Box ===
|
||||||
|
console.log("=== 基本系Box ===")
|
||||||
|
|
||||||
|
// StringBox
|
||||||
|
local str
|
||||||
|
str = new StringBox("Hello")
|
||||||
|
console.log("StringBox: " + str.toString())
|
||||||
|
|
||||||
|
// IntegerBox
|
||||||
|
local num
|
||||||
|
num = new IntegerBox(42)
|
||||||
|
console.log("IntegerBox: " + num.toString())
|
||||||
|
|
||||||
|
// BoolBox
|
||||||
|
local bool
|
||||||
|
bool = new BoolBox(true)
|
||||||
|
console.log("BoolBox: " + bool.toString())
|
||||||
|
|
||||||
|
// NullBox
|
||||||
|
local null
|
||||||
|
null = new NullBox()
|
||||||
|
console.log("NullBox: " + null.toString())
|
||||||
|
|
||||||
|
// === 新機能Box ===
|
||||||
|
console.log("=== 新機能Box ===")
|
||||||
|
|
||||||
|
// FloatBox(新実装)
|
||||||
|
local float
|
||||||
|
float = new FloatBox(3.14)
|
||||||
|
console.log("FloatBox: " + float.toString())
|
||||||
|
|
||||||
|
// ArrayBox(改良版)
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
arr.push("item1")
|
||||||
|
arr.push("item2")
|
||||||
|
console.log("ArrayBox length: " + arr.length())
|
||||||
|
|
||||||
|
// === ユーティリティBox ===
|
||||||
|
console.log("=== ユーティリティBox ===")
|
||||||
|
|
||||||
|
// MathBox
|
||||||
|
local math
|
||||||
|
math = new MathBox()
|
||||||
|
console.log("MathBox PI: " + math.pi())
|
||||||
|
|
||||||
|
// TimeBox
|
||||||
|
local time
|
||||||
|
time = new TimeBox()
|
||||||
|
console.log("TimeBox: " + time.toString())
|
||||||
|
|
||||||
|
// MapBox
|
||||||
|
local map
|
||||||
|
map = new MapBox()
|
||||||
|
map.set("key1", "value1")
|
||||||
|
console.log("MapBox has key1: " + map.has("key1"))
|
||||||
13
tests/development/test_builtin_delegation.nyash
Normal file
13
tests/development/test_builtin_delegation.nyash
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
box TestChild : P2PBox {
|
||||||
|
constructor(nodeId, world) {
|
||||||
|
from P2PBox.constructor(nodeId, world)
|
||||||
|
me.test = "hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
override send(intent, data, target) {
|
||||||
|
print("Child sending: " + intent)
|
||||||
|
from P2PBox.send(intent, data, target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
5
tests/development/test_builtin_delegation_full.nyash
Normal file
5
tests/development/test_builtin_delegation_full.nyash
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
world = new IntentBox()
|
||||||
|
child = new TestChild("test", world)
|
||||||
|
child.send("hello", "data", "target")
|
||||||
|
|
||||||
67
tests/development/test_builtin_inheritance.nyash
Normal file
67
tests/development/test_builtin_inheritance.nyash
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Test built-in Box inheritance with P2PBox
|
||||||
|
box ChatNode from P2PBox {
|
||||||
|
init { chatHistory }
|
||||||
|
|
||||||
|
pack(nodeId, world) {
|
||||||
|
from P2PBox.pack(nodeId, world)
|
||||||
|
me.chatHistory = new ArrayBox()
|
||||||
|
}
|
||||||
|
|
||||||
|
override send(intent, data, target) {
|
||||||
|
// Log chat message
|
||||||
|
me.chatHistory.push({
|
||||||
|
"from": me.get_node_id(),
|
||||||
|
"to": target,
|
||||||
|
"message": data
|
||||||
|
})
|
||||||
|
|
||||||
|
// Call parent send method
|
||||||
|
from P2PBox.send(intent, data, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
getChatHistory() {
|
||||||
|
return me.chatHistory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with MathBox
|
||||||
|
box ScientificCalc from MathBox {
|
||||||
|
init { history }
|
||||||
|
|
||||||
|
pack() {
|
||||||
|
from MathBox.pack()
|
||||||
|
me.history = []
|
||||||
|
}
|
||||||
|
|
||||||
|
override sin(x) {
|
||||||
|
local result
|
||||||
|
result = from MathBox.sin(x)
|
||||||
|
me.history.push("sin(" + x.toString() + ") = " + result.toString())
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistory() {
|
||||||
|
return me.history
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main test
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
console.log("Testing built-in Box inheritance...")
|
||||||
|
|
||||||
|
// Test MathBox inheritance
|
||||||
|
local calc
|
||||||
|
calc = new ScientificCalc()
|
||||||
|
|
||||||
|
local result
|
||||||
|
result = calc.sin(3.14159 / 2)
|
||||||
|
console.log("Sin(π/2) = " + result.toString())
|
||||||
|
console.log("Calculation history: " + calc.getHistory().toString())
|
||||||
|
|
||||||
|
console.log("✅ Built-in Box inheritance test complete!")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
// Test if MathBox is recognized as a built-in type
|
||||||
|
local instance
|
||||||
|
instance = new MathBox()
|
||||||
|
|
||||||
|
local result
|
||||||
|
result = instance.sin(1.5708)
|
||||||
|
print("Sin(π/2) = " + result.toString())
|
||||||
|
|
||||||
|
print("MathBox test complete!")
|
||||||
68
tests/development/test_comprehensive_final.nyash
Normal file
68
tests/development/test_comprehensive_final.nyash
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 🎉 COMPREHENSIVE TEST - All Issues Resolved!
|
||||||
|
// Tests all the originally reported problems have been fixed
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("🎉 === COMPREHENSIVE TEST: All Issues Resolved ===")
|
||||||
|
|
||||||
|
console.log("--- Phase 1: Basic Box Constructors (Problem 1) ---")
|
||||||
|
// ✅ FIXED: These were originally failing with "Undefined class" errors
|
||||||
|
local str_box = new StringBox("test")
|
||||||
|
local int_box = new IntegerBox(123)
|
||||||
|
local bool_box = new BoolBox(true)
|
||||||
|
console.log("✅ StringBox: " + str_box.toString())
|
||||||
|
console.log("✅ IntegerBox: " + int_box.toString())
|
||||||
|
console.log("✅ BoolBox: " + bool_box.toString())
|
||||||
|
|
||||||
|
console.log("--- Problem 2: IntentBox Field Access (Already Working) ---")
|
||||||
|
// ✅ CONFIRMED: These were actually working fine
|
||||||
|
local intent = new IntentBox("test", "Hello World")
|
||||||
|
console.log("✅ IntentBox name: " + intent.getName())
|
||||||
|
console.log("✅ IntentBox payload: " + intent.getPayload())
|
||||||
|
|
||||||
|
console.log("--- Problem 4: FloatBox (Already Working) ---")
|
||||||
|
// ✅ CONFIRMED: This was also working fine
|
||||||
|
local float = new FloatBox(3.14)
|
||||||
|
console.log("✅ FloatBox: " + float.toString())
|
||||||
|
|
||||||
|
console.log("--- Phase 2: Multi-Delegation (NEW FEATURE) ---")
|
||||||
|
// 🚀 NEW: Revolutionary multi-delegation syntax implementation
|
||||||
|
box SuperBox from StringBox, IntegerBox, BoolBox {
|
||||||
|
init { text, number, flag }
|
||||||
|
|
||||||
|
pack(t, n, f) {
|
||||||
|
me.text = t
|
||||||
|
me.number = n
|
||||||
|
me.flag = f
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllData() {
|
||||||
|
return "SuperBox[" + me.text + ", " + me.number + ", " + me.flag + "]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local super = new SuperBox("Multi", 42, true)
|
||||||
|
console.log("🚀 Multi-delegation: " + super.getAllData())
|
||||||
|
|
||||||
|
console.log("--- Backward Compatibility Tests ---")
|
||||||
|
// ✅ CONFIRMED: All old syntax still works
|
||||||
|
box OldStyle from StringBox {
|
||||||
|
init { data }
|
||||||
|
pack(d) { me.data = d }
|
||||||
|
getData() { return "Old: " + me.data }
|
||||||
|
}
|
||||||
|
|
||||||
|
box NoParents {
|
||||||
|
init { value }
|
||||||
|
pack(v) { me.value = v }
|
||||||
|
getValue() { return "Standalone: " + me.value }
|
||||||
|
}
|
||||||
|
|
||||||
|
local old = new OldStyle("SingleParent")
|
||||||
|
local standalone = new NoParents("Independent")
|
||||||
|
console.log("✅ Single parent: " + old.getData())
|
||||||
|
console.log("✅ No parents: " + standalone.getValue())
|
||||||
|
|
||||||
|
console.log("🎊 === ALL ISSUES RESOLVED & NEW FEATURES WORKING! ===")
|
||||||
|
console.log("🎯 Phase 1: Critical Box registration COMPLETE")
|
||||||
|
console.log("🚀 Phase 2: Multi-delegation syntax COMPLETE")
|
||||||
|
console.log("✅ Ready for P2P development with advanced delegation patterns!")
|
||||||
18
tests/development/test_constructor_debug.nyash
Normal file
18
tests/development/test_constructor_debug.nyash
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// コンストラクタデバッグ
|
||||||
|
box Test {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
Test(v) {
|
||||||
|
me.value = v
|
||||||
|
print("Constructor called with: " + v)
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local t
|
||||||
|
print("Creating Test...")
|
||||||
|
t = new Test("hello")
|
||||||
|
print("getValue: " + t.getValue())
|
||||||
56
tests/development/test_cross_type_operators.nyash
Normal file
56
tests/development/test_cross_type_operators.nyash
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Cross-type演算子全パターンテスト
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
console.log("=== Cross-type Operator Tests ===")
|
||||||
|
|
||||||
|
// 基本型の準備
|
||||||
|
local num
|
||||||
|
num = 42
|
||||||
|
|
||||||
|
local float
|
||||||
|
float = new FloatBox(3.14)
|
||||||
|
|
||||||
|
local str
|
||||||
|
str = "Hello"
|
||||||
|
|
||||||
|
local bool
|
||||||
|
bool = true
|
||||||
|
|
||||||
|
// === 数値 + 浮動小数点 ===
|
||||||
|
console.log("=== Number + Float ===")
|
||||||
|
console.log("42 + 3.14 = " + (num + float.value))
|
||||||
|
console.log("42 - 3.14 = " + (num - float.value))
|
||||||
|
console.log("42 * 3.14 = " + (num * float.value))
|
||||||
|
console.log("42 / 3.14 = " + (num / float.value))
|
||||||
|
|
||||||
|
// === 文字列連結 ===
|
||||||
|
console.log("=== String concatenation ===")
|
||||||
|
console.log("String + Number: " + str + num)
|
||||||
|
console.log("String + Float: " + str + float.value)
|
||||||
|
console.log("String + Bool: " + str + bool)
|
||||||
|
|
||||||
|
// === 比較演算子 ===
|
||||||
|
console.log("=== Comparison operators ===")
|
||||||
|
console.log("42 == 42: " + (num == 42))
|
||||||
|
console.log("42 != 43: " + (num != 43))
|
||||||
|
console.log("42 > 30: " + (num > 30))
|
||||||
|
console.log("42 < 50: " + (num < 50))
|
||||||
|
console.log("42 >= 42: " + (num >= 42))
|
||||||
|
console.log("42 <= 45: " + (num <= 45))
|
||||||
|
|
||||||
|
// === 論理演算子 ===
|
||||||
|
console.log("=== Logical operators ===")
|
||||||
|
console.log("true and true: " + (bool and true))
|
||||||
|
console.log("true or false: " + (bool or false))
|
||||||
|
console.log("not true: " + (not bool))
|
||||||
|
|
||||||
|
// === FloatBox specific ===
|
||||||
|
console.log("=== FloatBox operations ===")
|
||||||
|
local float1
|
||||||
|
float1 = new FloatBox(2.5)
|
||||||
|
local float2
|
||||||
|
float2 = new FloatBox(1.5)
|
||||||
|
|
||||||
|
console.log("2.5 + 1.5 = " + (float1.value + float2.value))
|
||||||
|
console.log("2.5 * 1.5 = " + (float1.value * float2.value))
|
||||||
79
tests/development/test_delegation_edge_cases.nyash
Normal file
79
tests/development/test_delegation_edge_cases.nyash
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// デリゲーション・overrideの詳細テスト(エッジケース)
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
// === 基本デリゲーション ===
|
||||||
|
box BaseBox {
|
||||||
|
init { value, count }
|
||||||
|
|
||||||
|
pack(val) {
|
||||||
|
me.value = val
|
||||||
|
me.count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
|
||||||
|
increment() {
|
||||||
|
me.count = me.count + 1
|
||||||
|
return me.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box ExtendedBox from BaseBox {
|
||||||
|
init { multiplier }
|
||||||
|
|
||||||
|
pack(val, mult) {
|
||||||
|
from BaseBox.pack(val)
|
||||||
|
me.multiplier = mult
|
||||||
|
}
|
||||||
|
|
||||||
|
// override without calling parent
|
||||||
|
override getValue() {
|
||||||
|
return me.value + " (Extended)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// override with parent call
|
||||||
|
override increment() {
|
||||||
|
local result
|
||||||
|
result = from BaseBox.increment()
|
||||||
|
return result * me.multiplier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === テスト実行 ===
|
||||||
|
console.log("=== Basic delegation test ===")
|
||||||
|
local base
|
||||||
|
base = new BaseBox("Hello")
|
||||||
|
console.log("Base value: " + base.getValue())
|
||||||
|
console.log("Base increment: " + base.increment())
|
||||||
|
|
||||||
|
console.log("=== Extended delegation test ===")
|
||||||
|
local ext
|
||||||
|
ext = new ExtendedBox("World", 2)
|
||||||
|
console.log("Extended value: " + ext.getValue())
|
||||||
|
console.log("Extended increment: " + ext.increment())
|
||||||
|
console.log("Extended increment again: " + ext.increment())
|
||||||
|
|
||||||
|
// === 多重デリゲーション ===
|
||||||
|
console.log("=== Multiple delegation test ===")
|
||||||
|
box SuperExtendedBox from ExtendedBox {
|
||||||
|
init { suffix }
|
||||||
|
|
||||||
|
pack(val, mult, suf) {
|
||||||
|
from ExtendedBox.pack(val, mult)
|
||||||
|
me.suffix = suf
|
||||||
|
}
|
||||||
|
|
||||||
|
override getValue() {
|
||||||
|
local parentValue
|
||||||
|
parentValue = from ExtendedBox.getValue()
|
||||||
|
return parentValue + me.suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local super
|
||||||
|
super = new SuperExtendedBox("Chain", 3, "!!!")
|
||||||
|
console.log("Super value: " + super.getValue())
|
||||||
|
console.log("Super increment: " + super.increment())
|
||||||
27
tests/development/test_delegation_pack.nyash
Normal file
27
tests/development/test_delegation_pack.nyash
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// デリゲーション + pack構文テスト
|
||||||
|
box User {
|
||||||
|
init { name, email }
|
||||||
|
|
||||||
|
pack(userName, userEmail) {
|
||||||
|
me.name = userName
|
||||||
|
me.email = userEmail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box AdminUser from User {
|
||||||
|
init { permissions }
|
||||||
|
|
||||||
|
pack(adminName, adminEmail, perms) {
|
||||||
|
from User.pack(adminName, adminEmail)
|
||||||
|
me.permissions = perms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local admin
|
||||||
|
admin = new AdminUser("Bob", "bob@admin.com", "ALL")
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("Admin name: " + admin.name)
|
||||||
|
console.log("Admin email: " + admin.email)
|
||||||
|
console.log("Admin permissions: " + admin.permissions)
|
||||||
46
tests/development/test_error_handling.nyash
Normal file
46
tests/development/test_error_handling.nyash
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// エラーハンドリング・型安全性テスト
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
console.log("=== Error Handling Tests ===")
|
||||||
|
|
||||||
|
// 1. ゼロ除算エラー
|
||||||
|
console.log("Testing division by zero...")
|
||||||
|
local math
|
||||||
|
math = new MathBox()
|
||||||
|
local result
|
||||||
|
result = math.divide(10, 0)
|
||||||
|
console.log("Division result: " + result.toString())
|
||||||
|
|
||||||
|
// 2. 存在しないメソッド呼び出し
|
||||||
|
console.log("Testing undefined method...")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
// arr.nonexistentMethod() // これはコメントアウト
|
||||||
|
|
||||||
|
// 3. 存在しないフィールドアクセス
|
||||||
|
console.log("Testing undefined field...")
|
||||||
|
// console.log(arr.nonexistentField) // これもコメントアウト
|
||||||
|
|
||||||
|
// 4. 型変換エラー
|
||||||
|
console.log("Testing type conversions...")
|
||||||
|
local num
|
||||||
|
num = 42
|
||||||
|
local float
|
||||||
|
float = new FloatBox(3.14)
|
||||||
|
|
||||||
|
// 数値 + 浮動小数点
|
||||||
|
console.log("Number + Float: " + (num + float.value))
|
||||||
|
|
||||||
|
// 5. ArrayBox操作
|
||||||
|
console.log("Testing ArrayBox operations...")
|
||||||
|
arr.push("item1")
|
||||||
|
arr.push("item2")
|
||||||
|
console.log("Array length: " + arr.length())
|
||||||
|
console.log("Array item[0]: " + arr.get(0))
|
||||||
|
|
||||||
|
// 範囲外アクセス
|
||||||
|
console.log("Testing array bounds...")
|
||||||
|
local outOfBounds
|
||||||
|
outOfBounds = arr.get(999)
|
||||||
|
console.log("Out of bounds result: " + outOfBounds.toString())
|
||||||
22
tests/development/test_float_box_issues.nyash
Normal file
22
tests/development/test_float_box_issues.nyash
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Test FloatBox Issues (Problem 4)
|
||||||
|
// This should demonstrate the FloatBox value access issues
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Testing FloatBox Issues ===")
|
||||||
|
|
||||||
|
// Test FloatBox creation (this should work)
|
||||||
|
console.log("Creating FloatBox...")
|
||||||
|
local float = new FloatBox(3.14)
|
||||||
|
console.log("FloatBox created successfully")
|
||||||
|
|
||||||
|
// Test toString method (this should work)
|
||||||
|
console.log("Testing toString...")
|
||||||
|
local float_str = float.toString()
|
||||||
|
console.log("FloatBox toString: " + float_str)
|
||||||
|
|
||||||
|
// Test value field access (this should fail)
|
||||||
|
console.log("Testing value field access...")
|
||||||
|
// local value = float.value
|
||||||
|
// console.log("FloatBox value: " + value)
|
||||||
|
|
||||||
|
console.log("FloatBox test complete!")
|
||||||
106
tests/development/test_from_call.nyash
Normal file
106
tests/development/test_from_call.nyash
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// 🔥 FromCall実装テスト - Override + From統一構文によるデリゲーション革命
|
||||||
|
|
||||||
|
// 親クラス定義
|
||||||
|
box Animal {
|
||||||
|
init { name, sound }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
me.name = "Unknown Animal"
|
||||||
|
me.sound = "Silent"
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(animalName) {
|
||||||
|
me.name = animalName
|
||||||
|
me.sound = "Unknown Sound"
|
||||||
|
}
|
||||||
|
|
||||||
|
makeSound() {
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log(me.name + " makes " + me.sound)
|
||||||
|
return me.sound
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return me.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子クラス定義(デリゲーション関係)
|
||||||
|
box Dog : Animal {
|
||||||
|
init { breed }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// 親コンストラクタを呼び出し
|
||||||
|
from Animal.constructor()
|
||||||
|
me.sound = "Woof!"
|
||||||
|
me.breed = "Mixed"
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(dogName, dogBreed) {
|
||||||
|
// 引数付き親コンストラクタを呼び出し
|
||||||
|
from Animal.constructor(dogName)
|
||||||
|
me.sound = "Woof!"
|
||||||
|
me.breed = dogBreed
|
||||||
|
}
|
||||||
|
|
||||||
|
// override: 親メソッドをオーバーライド
|
||||||
|
makeSound() {
|
||||||
|
// 親メソッドを呼び出し
|
||||||
|
local parentSound
|
||||||
|
parentSound = from Animal.makeSound()
|
||||||
|
|
||||||
|
// 追加の処理
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("This is a " + me.breed + " breed!")
|
||||||
|
return parentSound
|
||||||
|
}
|
||||||
|
|
||||||
|
getBreed() {
|
||||||
|
return me.breed
|
||||||
|
}
|
||||||
|
|
||||||
|
// 親のgetNameを呼び出すテスト
|
||||||
|
getFullInfo() {
|
||||||
|
local parentName
|
||||||
|
parentName = from Animal.getName()
|
||||||
|
return parentName + " (" + me.breed + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静的メインクラス
|
||||||
|
static box Main {
|
||||||
|
init { console }
|
||||||
|
|
||||||
|
main() {
|
||||||
|
me.console = new ConsoleBox()
|
||||||
|
me.console.log("🔥 FromCall Implementation Test Starting...")
|
||||||
|
|
||||||
|
// テスト1: デフォルトコンストラクタ
|
||||||
|
local dog1
|
||||||
|
dog1 = new Dog()
|
||||||
|
me.console.log("Test 1 - Default Constructor:")
|
||||||
|
dog1.makeSound()
|
||||||
|
me.console.log("Name: " + dog1.getName())
|
||||||
|
me.console.log("Breed: " + dog1.getBreed())
|
||||||
|
me.console.log("")
|
||||||
|
|
||||||
|
// テスト2: 引数付きコンストラクタ
|
||||||
|
local dog2
|
||||||
|
dog2 = new Dog("Buddy", "Golden Retriever")
|
||||||
|
me.console.log("Test 2 - Parameterized Constructor:")
|
||||||
|
dog2.makeSound()
|
||||||
|
me.console.log("Full Info: " + dog2.getFullInfo())
|
||||||
|
me.console.log("")
|
||||||
|
|
||||||
|
// テスト3: 親メソッド直接呼び出し
|
||||||
|
me.console.log("Test 3 - Direct parent method call:")
|
||||||
|
local directAnimal
|
||||||
|
directAnimal = new Animal("Cat")
|
||||||
|
directAnimal.makeSound()
|
||||||
|
|
||||||
|
me.console.log("🎉 FromCall Implementation Test Completed!")
|
||||||
|
return "FromCall Revolution Success!"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
tests/development/test_from_fixed.nyash
Normal file
18
tests/development/test_from_fixed.nyash
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
box SimpleChild : P2PBox {
|
||||||
|
constructor(nodeId, world) {
|
||||||
|
from P2PBox.constructor(nodeId, world)
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
print("Testing from call")
|
||||||
|
return from P2PBox.send("test", "data", "target")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local world, child, result
|
||||||
|
world = new IntentBox()
|
||||||
|
child = new SimpleChild("test", world)
|
||||||
|
result = child.test()
|
||||||
|
print("Result: " + result)
|
||||||
|
|
||||||
17
tests/development/test_from_only.nyash
Normal file
17
tests/development/test_from_only.nyash
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
box SimpleChild : P2PBox {
|
||||||
|
constructor(nodeId, world) {
|
||||||
|
from P2PBox.constructor(nodeId, world)
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
print("Testing from call")
|
||||||
|
return from P2PBox.send("test", "data", "target")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
world = new IntentBox()
|
||||||
|
child = new SimpleChild("test", world)
|
||||||
|
result = child.test()
|
||||||
|
print("Result: " + result)
|
||||||
|
|
||||||
24
tests/development/test_from_simple.nyash
Normal file
24
tests/development/test_from_simple.nyash
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
// from構文のみのテスト(まず式として)
|
||||||
|
box Parent {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return "Parent value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child from Parent {
|
||||||
|
init { }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
local result
|
||||||
|
result = from Parent.getValue()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local c
|
||||||
|
c = new Child()
|
||||||
|
print("Result: " + c.test())
|
||||||
|
|
||||||
45
tests/development/test_from_syntax.nyash
Normal file
45
tests/development/test_from_syntax.nyash
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// from統一構文のテスト
|
||||||
|
box Parent {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
init() { # init構文に統一
|
||||||
|
me.value = "Parent value"
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
|
||||||
|
process(x) {
|
||||||
|
return "Parent processed: " + x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from構文でデリゲーション
|
||||||
|
box Child from Parent {
|
||||||
|
init { extra }
|
||||||
|
|
||||||
|
init() { # init構文に統一
|
||||||
|
from Parent.init() # 親コンストラクタ呼び出し
|
||||||
|
me.extra = " (Child extra)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// overrideで明示的置換
|
||||||
|
override process(x) {
|
||||||
|
local result
|
||||||
|
result = from Parent.process(x)
|
||||||
|
return result + me.extra
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新しいメソッド
|
||||||
|
getAll() {
|
||||||
|
return me.getValue() + me.extra
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// テスト実行
|
||||||
|
local child
|
||||||
|
child = new Child()
|
||||||
|
print("getValue: " + child.getValue())
|
||||||
|
print("process: " + child.process("test"))
|
||||||
|
print("getAll: " + child.getAll())
|
||||||
19
tests/development/test_implicit_override_error.nyash
Normal file
19
tests/development/test_implicit_override_error.nyash
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
// 暗黙オーバーライド禁止のテスト
|
||||||
|
box Parent {
|
||||||
|
init { }
|
||||||
|
|
||||||
|
method() {
|
||||||
|
return "Parent method"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child from Parent {
|
||||||
|
init { }
|
||||||
|
|
||||||
|
// overrideなしで同名メソッド定義(エラーになるはず)
|
||||||
|
method() {
|
||||||
|
return "Child method"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
80
tests/development/test_init_syntax.nyash
Normal file
80
tests/development/test_init_syntax.nyash
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// init構文の包括的テスト
|
||||||
|
|
||||||
|
// 1. 基本的なinit構文
|
||||||
|
box Animal {
|
||||||
|
init { name, age }
|
||||||
|
|
||||||
|
init(animalName, animalAge) {
|
||||||
|
me.name = animalName
|
||||||
|
me.age = animalAge
|
||||||
|
}
|
||||||
|
|
||||||
|
speak() {
|
||||||
|
return me.name + " (age " + me.age + ") makes a sound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. fromデリゲーションでのinit
|
||||||
|
box Dog from Animal {
|
||||||
|
init { breed }
|
||||||
|
|
||||||
|
init(dogName, dogAge, dogBreed) {
|
||||||
|
from Animal.init(dogName, dogAge) // 親のinitを呼び出し
|
||||||
|
me.breed = dogBreed
|
||||||
|
}
|
||||||
|
|
||||||
|
override speak() {
|
||||||
|
return me.name + " (age " + me.age + ", " + me.breed + ") barks: Woof!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 従来のBox名形式(互換性確認)
|
||||||
|
box Cat from Animal {
|
||||||
|
init { color }
|
||||||
|
|
||||||
|
Cat(catName, catAge, catColor) { // 従来形式もまだ動作する
|
||||||
|
from Animal.init(catName, catAge)
|
||||||
|
me.color = catColor
|
||||||
|
}
|
||||||
|
|
||||||
|
override speak() {
|
||||||
|
return me.name + " (age " + me.age + ", " + me.color + ") meows: Meow!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// テスト実行
|
||||||
|
print("=== init構文テスト ===")
|
||||||
|
|
||||||
|
// 1. 基本的なinit
|
||||||
|
local animal
|
||||||
|
animal = new Animal("Generic", 5)
|
||||||
|
print("Animal: " + animal.speak())
|
||||||
|
|
||||||
|
// 2. デリゲーションでのinit
|
||||||
|
local dog
|
||||||
|
dog = new Dog("Buddy", 3, "Golden Retriever")
|
||||||
|
print("Dog: " + dog.speak())
|
||||||
|
|
||||||
|
// 3. 従来形式との互換性
|
||||||
|
local cat
|
||||||
|
cat = new Cat("Whiskers", 2, "Black")
|
||||||
|
print("Cat: " + cat.speak())
|
||||||
|
|
||||||
|
// 4. 引数なしinit
|
||||||
|
box SimpleBox {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
init() { // 引数なしinit
|
||||||
|
me.value = "Default value"
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local simple
|
||||||
|
simple = new SimpleBox()
|
||||||
|
print("SimpleBox: " + simple.getValue())
|
||||||
|
|
||||||
|
print("\n✅ init構文テスト完了!")
|
||||||
23
tests/development/test_intent_field_access.nyash
Normal file
23
tests/development/test_intent_field_access.nyash
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Test IntentBox Field Access Issues (Problem 2)
|
||||||
|
// This should demonstrate the field access failures described
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Testing IntentBox Field Access ===")
|
||||||
|
|
||||||
|
// Test IntentBox creation (this should work)
|
||||||
|
console.log("Creating IntentBox...")
|
||||||
|
local intent = new IntentBox("test", "Hello")
|
||||||
|
console.log("IntentBox created successfully")
|
||||||
|
|
||||||
|
// Test field access methods (these should be the issue)
|
||||||
|
console.log("Testing field access...")
|
||||||
|
|
||||||
|
// Try getName method
|
||||||
|
local name = intent.getName()
|
||||||
|
console.log("Intent name: " + name)
|
||||||
|
|
||||||
|
// Try getPayload method
|
||||||
|
local payload = intent.getPayload()
|
||||||
|
console.log("Intent payload: " + payload)
|
||||||
|
|
||||||
|
console.log("Field access test complete!")
|
||||||
6
tests/development/test_intent_only.nyash
Normal file
6
tests/development/test_intent_only.nyash
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Test only the IntentBox functionality to verify the basic structure works
|
||||||
|
print("Testing IntentBox basic functionality...")
|
||||||
|
|
||||||
|
local msg
|
||||||
|
msg = new IntentBox("test", "data")
|
||||||
|
print("IntentBox created: " + msg.type())
|
||||||
32
tests/development/test_invalid_override.nyash
Normal file
32
tests/development/test_invalid_override.nyash
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 🚨 無効なoverride検証テスト - エラーが発生すべき
|
||||||
|
|
||||||
|
// 親Box
|
||||||
|
box Animal {
|
||||||
|
init { name }
|
||||||
|
|
||||||
|
pack(animalName) {
|
||||||
|
me.name = animalName
|
||||||
|
}
|
||||||
|
|
||||||
|
speak() {
|
||||||
|
return me.name + " makes a sound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子Box - 存在しないメソッドをoverride(エラーになるはず)
|
||||||
|
box BadDog from Animal {
|
||||||
|
init { breed }
|
||||||
|
|
||||||
|
pack(dogName, dogBreed) {
|
||||||
|
from Animal.pack(dogName)
|
||||||
|
me.breed = dogBreed
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🚨 これはエラーになるはず - nonExistentMethodは危険パターンに含まれている
|
||||||
|
override nonExistentMethod() {
|
||||||
|
return "This should fail"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// このファイルはパースエラーで実行されないはず
|
||||||
|
print("このメッセージが表示されたらテスト失敗")
|
||||||
35
tests/development/test_missing_boxes.nyash
Normal file
35
tests/development/test_missing_boxes.nyash
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 基本的なBoxの存在確認
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
// 文字列リテラルと数値リテラルの動作確認
|
||||||
|
local str
|
||||||
|
str = "Hello World"
|
||||||
|
console.log("String literal: " + str)
|
||||||
|
|
||||||
|
local num
|
||||||
|
num = 42
|
||||||
|
console.log("Number literal: " + num.toString())
|
||||||
|
|
||||||
|
local bool
|
||||||
|
bool = true
|
||||||
|
console.log("Bool literal: " + bool.toString())
|
||||||
|
|
||||||
|
// StringBox, IntegerBox, BoolBoxコンストラクタのテスト
|
||||||
|
console.log("=== Constructor tests ===")
|
||||||
|
|
||||||
|
// これらがエラーになるかテスト
|
||||||
|
console.log("Testing StringBox...")
|
||||||
|
local str_box
|
||||||
|
str_box = new StringBox("test")
|
||||||
|
console.log("StringBox created")
|
||||||
|
|
||||||
|
console.log("Testing IntegerBox...")
|
||||||
|
local int_box
|
||||||
|
int_box = new IntegerBox(123)
|
||||||
|
console.log("IntegerBox created")
|
||||||
|
|
||||||
|
console.log("Testing BoolBox...")
|
||||||
|
local bool_box
|
||||||
|
bool_box = new BoolBox(false)
|
||||||
|
console.log("BoolBox created")
|
||||||
28
tests/development/test_multi_delegation.nyash
Normal file
28
tests/development/test_multi_delegation.nyash
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Test Multi-Delegation Syntax (Phase 2 Implementation)
|
||||||
|
// This should test the new `box Child from ParentA, ParentB` syntax
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Testing Multi-Delegation Syntax ===")
|
||||||
|
|
||||||
|
// Test 1: Simple multi-delegation syntax parsing
|
||||||
|
console.log("Testing multi-delegation syntax...")
|
||||||
|
box MultiChild from StringBox, IntegerBox {
|
||||||
|
init { textValue, numValue }
|
||||||
|
|
||||||
|
pack(text, num) {
|
||||||
|
me.textValue = text
|
||||||
|
me.numValue = num
|
||||||
|
}
|
||||||
|
|
||||||
|
getCombined() {
|
||||||
|
return me.textValue + ": " + me.numValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Multi-delegation box declared successfully!")
|
||||||
|
|
||||||
|
// Test if the parser accepted the syntax
|
||||||
|
local multi = new MultiChild("Count", 123)
|
||||||
|
console.log("Multi delegation instance: " + multi.getCombined())
|
||||||
|
|
||||||
|
console.log("=== Multi-Delegation Test Complete ===")
|
||||||
60
tests/development/test_multi_delegation_advanced.nyash
Normal file
60
tests/development/test_multi_delegation_advanced.nyash
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// Advanced Multi-Delegation Test Cases
|
||||||
|
// Testing complex scenarios and edge cases
|
||||||
|
|
||||||
|
local console = new ConsoleBox()
|
||||||
|
console.log("=== Advanced Multi-Delegation Tests ===")
|
||||||
|
|
||||||
|
// Test 1: Three-way delegation
|
||||||
|
console.log("Testing three-way delegation...")
|
||||||
|
box TripleChild from StringBox, IntegerBox, BoolBox {
|
||||||
|
init { strVal, intVal, boolVal }
|
||||||
|
|
||||||
|
pack(s, i, b) {
|
||||||
|
me.strVal = s
|
||||||
|
me.intVal = i
|
||||||
|
me.boolVal = b
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll() {
|
||||||
|
return me.strVal + " | " + me.intVal + " | " + me.boolVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local triple = new TripleChild("Hello", 42, true)
|
||||||
|
console.log("Triple delegation: " + triple.getAll())
|
||||||
|
|
||||||
|
// Test 2: No delegation (should still work)
|
||||||
|
console.log("Testing no delegation...")
|
||||||
|
box StandaloneBox {
|
||||||
|
init { data }
|
||||||
|
|
||||||
|
pack(value) {
|
||||||
|
me.data = value
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
return "Standalone: " + me.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local standalone = new StandaloneBox("Independent")
|
||||||
|
console.log(standalone.getData())
|
||||||
|
|
||||||
|
// Test 3: Single delegation (backward compatibility)
|
||||||
|
console.log("Testing single delegation backward compatibility...")
|
||||||
|
box SingleBox from StringBox {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
pack(val) {
|
||||||
|
me.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return "Single: " + me.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local single = new SingleBox("OnlyOne")
|
||||||
|
console.log(single.getValue())
|
||||||
|
|
||||||
|
console.log("=== All Multi-Delegation Tests Passed! ===")
|
||||||
63
tests/development/test_new_features.nyash
Normal file
63
tests/development/test_new_features.nyash
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// 新機能(FloatBox・ArrayBox改良)動作確認
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
|
||||||
|
console.log("=== New Features Test ===")
|
||||||
|
|
||||||
|
// === FloatBox ===
|
||||||
|
console.log("=== FloatBox Tests ===")
|
||||||
|
local float1
|
||||||
|
float1 = new FloatBox(3.14159)
|
||||||
|
console.log("FloatBox created: " + float1.toString())
|
||||||
|
|
||||||
|
local float2
|
||||||
|
float2 = new FloatBox(2.71828)
|
||||||
|
console.log("FloatBox 2 created: " + float2.toString())
|
||||||
|
|
||||||
|
// === ArrayBox改良版 ===
|
||||||
|
console.log("=== ArrayBox Enhanced Tests ===")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
|
||||||
|
// 基本操作
|
||||||
|
arr.push("apple")
|
||||||
|
arr.push("banana")
|
||||||
|
arr.push("cherry")
|
||||||
|
console.log("Array length: " + arr.length())
|
||||||
|
|
||||||
|
// 改良機能のテスト
|
||||||
|
console.log("Testing enhanced ArrayBox methods...")
|
||||||
|
|
||||||
|
// get/set operations
|
||||||
|
console.log("Item 0: " + arr.get(0))
|
||||||
|
console.log("Item 1: " + arr.get(1))
|
||||||
|
console.log("Item 2: " + arr.get(2))
|
||||||
|
|
||||||
|
// push/pop operations
|
||||||
|
local popped
|
||||||
|
popped = arr.pop()
|
||||||
|
console.log("Popped item: " + popped)
|
||||||
|
console.log("Array length after pop: " + arr.length())
|
||||||
|
|
||||||
|
// 数値配列での試験
|
||||||
|
local numArr
|
||||||
|
numArr = new ArrayBox()
|
||||||
|
numArr.push(10)
|
||||||
|
numArr.push(20)
|
||||||
|
numArr.push(30)
|
||||||
|
console.log("Number array length: " + numArr.length())
|
||||||
|
console.log("Number array item 1: " + numArr.get(1))
|
||||||
|
|
||||||
|
// === MathBox ===
|
||||||
|
console.log("=== MathBox Tests ===")
|
||||||
|
local math
|
||||||
|
math = new MathBox()
|
||||||
|
console.log("Math PI: " + math.pi())
|
||||||
|
console.log("Math E: " + math.e())
|
||||||
|
console.log("Math random: " + math.random())
|
||||||
|
|
||||||
|
// === TimeBox ===
|
||||||
|
console.log("=== TimeBox Tests ===")
|
||||||
|
local time
|
||||||
|
time = new TimeBox()
|
||||||
|
console.log("Current time: " + time.toString())
|
||||||
48
tests/development/test_nyashvalue_basic.nyash
Normal file
48
tests/development/test_nyashvalue_basic.nyash
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// NyashValue革命基本動作テスト
|
||||||
|
// Arc<Mutex>過剰症候群解決確認
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🔥 NyashValue Revolution Test Started!")
|
||||||
|
|
||||||
|
// 基本値テスト
|
||||||
|
console.log("=== Basic Values Test ===")
|
||||||
|
local testInteger, testFloat, testBool, testString
|
||||||
|
testInteger = 42
|
||||||
|
testFloat = 3.14
|
||||||
|
testBool = true
|
||||||
|
testString = "Hello NyashValue!"
|
||||||
|
|
||||||
|
console.log("Integer: " + testInteger)
|
||||||
|
console.log("Float: " + testFloat)
|
||||||
|
console.log("Bool: " + testBool)
|
||||||
|
console.log("String: " + testString)
|
||||||
|
|
||||||
|
// 型変換テスト
|
||||||
|
console.log("=== Type Conversion Test ===")
|
||||||
|
console.log("42 as string: " + testInteger)
|
||||||
|
|
||||||
|
// 等価性テスト
|
||||||
|
console.log("=== Cross-type Equality Test ===")
|
||||||
|
local intVal, floatVal
|
||||||
|
intVal = 42
|
||||||
|
floatVal = 42.0
|
||||||
|
console.log("Integer 42: " + intVal)
|
||||||
|
console.log("Float 42.0: " + floatVal)
|
||||||
|
|
||||||
|
// 配列テスト
|
||||||
|
console.log("=== Array Test ===")
|
||||||
|
local arr
|
||||||
|
arr = new ArrayBox()
|
||||||
|
arr.push(1)
|
||||||
|
arr.push(2)
|
||||||
|
arr.push(3)
|
||||||
|
console.log("Array length: " + arr.length())
|
||||||
|
console.log("Array[0]: " + arr.get(0))
|
||||||
|
|
||||||
|
console.log("🎉 NyashValue Revolution Test Completed!")
|
||||||
|
return "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
23
tests/development/test_override_check.nyash
Normal file
23
tests/development/test_override_check.nyash
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
// overrideキーワードが必要かどうかのテスト
|
||||||
|
box Parent {
|
||||||
|
init { }
|
||||||
|
|
||||||
|
method() {
|
||||||
|
return "Parent method"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local p
|
||||||
|
p = new Parent()
|
||||||
|
print("Parent method: " + p.method())
|
||||||
|
|
||||||
|
// 同じ名前のメソッドを後から追加しようとする
|
||||||
|
function addMethod() {
|
||||||
|
local parent
|
||||||
|
parent = new Parent()
|
||||||
|
// これはGlobalBoxへの追加なので、暗黙オーバーライドチェックが働くはず
|
||||||
|
}
|
||||||
|
|
||||||
|
addMethod()
|
||||||
|
|
||||||
48
tests/development/test_override_validation.nyash
Normal file
48
tests/development/test_override_validation.nyash
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// 🔍 override検証テスト - デリゲーションメソッドチェック機能
|
||||||
|
|
||||||
|
// 1. ✅ 正常なoverride(基本テスト)
|
||||||
|
box Animal {
|
||||||
|
init { name }
|
||||||
|
|
||||||
|
pack(animalName) {
|
||||||
|
me.name = animalName
|
||||||
|
}
|
||||||
|
|
||||||
|
speak() {
|
||||||
|
return me.name + " makes a sound"
|
||||||
|
}
|
||||||
|
|
||||||
|
move() {
|
||||||
|
return me.name + " moves"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Dog from Animal {
|
||||||
|
init { breed }
|
||||||
|
|
||||||
|
pack(dogName, dogBreed) {
|
||||||
|
from Animal.pack(dogName)
|
||||||
|
me.breed = dogBreed
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 正常なoverride - speakメソッドは親に存在
|
||||||
|
override speak() {
|
||||||
|
return me.name + " (dog) barks: Woof!"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 正常なoverride - moveメソッドも親に存在
|
||||||
|
override move() {
|
||||||
|
return me.name + " runs fast"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// テスト実行
|
||||||
|
print("=== 🔍 Override検証テスト ===")
|
||||||
|
|
||||||
|
local dog
|
||||||
|
dog = new Dog("Buddy", "Labrador")
|
||||||
|
print("Dog speak: " + dog.speak())
|
||||||
|
print("Dog move: " + dog.move())
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("✅ 正常なoverrideテスト完了!")
|
||||||
116
tests/development/test_p2p_basic_new.nyash
Normal file
116
tests/development/test_p2p_basic_new.nyash
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// 🧪 P2PBox New Architecture Test
|
||||||
|
// Tests the completely rewritten P2P communication system
|
||||||
|
|
||||||
|
print("=== P2PBox New Architecture Test ===")
|
||||||
|
|
||||||
|
// 1. Test IntentBox creation with structured messages
|
||||||
|
print("\n1. Testing IntentBox structured messages...")
|
||||||
|
local msg1
|
||||||
|
local msg2
|
||||||
|
local msg3
|
||||||
|
|
||||||
|
msg1 = new IntentBox("chat.message", "{ \"text\": \"Hello P2P!\", \"from\": \"alice\" }")
|
||||||
|
msg2 = new IntentBox("file.share", "{ \"filename\": \"document.pdf\", \"size\": 1024000 }")
|
||||||
|
msg3 = new IntentBox("system.ping", "{ \"timestamp\": 1635789456 }")
|
||||||
|
|
||||||
|
print("✅ IntentBox 1: " + msg1.getName() + " -> " + msg1.getPayload())
|
||||||
|
print("✅ IntentBox 2: " + msg2.getName() + " -> " + msg2.getPayload())
|
||||||
|
print("✅ IntentBox 3: " + msg3.getName() + " -> " + msg3.getPayload())
|
||||||
|
|
||||||
|
// 2. Test P2PBox creation with InProcess transport
|
||||||
|
print("\n2. Testing P2PBox creation...")
|
||||||
|
local alice
|
||||||
|
local bob
|
||||||
|
local charlie
|
||||||
|
|
||||||
|
alice = new P2PBox("alice", "inprocess")
|
||||||
|
bob = new P2PBox("bob", "inprocess")
|
||||||
|
charlie = new P2PBox("charlie", "inprocess")
|
||||||
|
|
||||||
|
print("✅ Alice created: " + alice.getNodeId() + " (" + alice.getTransportType() + ")")
|
||||||
|
print("✅ Bob created: " + bob.getNodeId() + " (" + bob.getTransportType() + ")")
|
||||||
|
print("✅ Charlie created: " + charlie.getNodeId() + " (" + charlie.getTransportType() + ")")
|
||||||
|
|
||||||
|
// 3. Test node reachability
|
||||||
|
print("\n3. Testing node reachability...")
|
||||||
|
local alice_can_reach_bob
|
||||||
|
local bob_can_reach_charlie
|
||||||
|
local alice_can_reach_nonexistent
|
||||||
|
|
||||||
|
alice_can_reach_bob = alice.isReachable("bob")
|
||||||
|
bob_can_reach_charlie = bob.isReachable("charlie")
|
||||||
|
alice_can_reach_nonexistent = alice.isReachable("nonexistent")
|
||||||
|
|
||||||
|
print("✅ Alice can reach Bob: " + alice_can_reach_bob)
|
||||||
|
print("✅ Bob can reach Charlie: " + bob_can_reach_charlie)
|
||||||
|
print("✅ Alice can reach nonexistent: " + alice_can_reach_nonexistent)
|
||||||
|
|
||||||
|
// 4. Test basic message sending
|
||||||
|
print("\n4. Testing basic message sending...")
|
||||||
|
local result1
|
||||||
|
local result2
|
||||||
|
|
||||||
|
// Send chat message from Alice to Bob
|
||||||
|
local chat_msg
|
||||||
|
chat_msg = new IntentBox("chat.message", "{ \"text\": \"Hello Bob!\", \"from\": \"alice\" }")
|
||||||
|
result1 = alice.send("bob", chat_msg)
|
||||||
|
print("✅ Alice -> Bob: " + result1)
|
||||||
|
|
||||||
|
// Send file share from Bob to Charlie
|
||||||
|
local file_msg
|
||||||
|
file_msg = new IntentBox("file.share", "{ \"filename\": \"data.txt\", \"size\": 512 }")
|
||||||
|
result2 = bob.send("charlie", file_msg)
|
||||||
|
print("✅ Bob -> Charlie: " + result2)
|
||||||
|
|
||||||
|
// 5. Test system behavior verification
|
||||||
|
print("\n5. Testing system behavior...")
|
||||||
|
|
||||||
|
// All nodes should be of correct type
|
||||||
|
print("✅ Alice type: " + alice.type())
|
||||||
|
print("✅ Bob type: " + bob.type())
|
||||||
|
print("✅ Charlie type: " + charlie.type())
|
||||||
|
|
||||||
|
// IntentBox should show proper structure
|
||||||
|
print("✅ Message 1 type: " + msg1.type())
|
||||||
|
print("✅ Message 2 type: " + msg2.type())
|
||||||
|
print("✅ Message 3 type: " + msg3.type())
|
||||||
|
|
||||||
|
// 6. Performance test - rapid message sending
|
||||||
|
print("\n6. Testing performance...")
|
||||||
|
local perf_start_time
|
||||||
|
local perf_msg
|
||||||
|
local i
|
||||||
|
|
||||||
|
perf_start_time = new TimeBox()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
loop(i < 10) {
|
||||||
|
perf_msg = new IntentBox("test.performance", "{ \"id\": " + i + " }")
|
||||||
|
alice.send("bob", perf_msg)
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local perf_end_time
|
||||||
|
perf_end_time = new TimeBox()
|
||||||
|
print("✅ Sent 10 messages successfully")
|
||||||
|
|
||||||
|
// 7. Error handling test - send to nonexistent node
|
||||||
|
print("\n7. Testing error handling...")
|
||||||
|
local error_msg
|
||||||
|
local error_result
|
||||||
|
|
||||||
|
error_msg = new IntentBox("test.error", "{ \"test\": true }")
|
||||||
|
|
||||||
|
// This should fail gracefully
|
||||||
|
print("Attempting to send to nonexistent node...")
|
||||||
|
// Note: This will likely cause a runtime error, which is expected
|
||||||
|
|
||||||
|
print("\n=== P2P New Architecture Test Complete ===")
|
||||||
|
print("🎉 All basic P2P functionality working correctly!")
|
||||||
|
print("🌟 New architecture features verified:")
|
||||||
|
print(" - Structured IntentBox messages (name + payload)")
|
||||||
|
print(" - P2PBox with InProcess transport")
|
||||||
|
print(" - Node reachability checking")
|
||||||
|
print(" - Individual send API (no broadcast)")
|
||||||
|
print(" - Arc<Mutex> memory safety pattern")
|
||||||
|
print(" - MessageBus singleton routing")
|
||||||
18
tests/development/test_p2p_phase1.nyash
Normal file
18
tests/development/test_p2p_phase1.nyash
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Phase 1: IntentBox基本テスト
|
||||||
|
local intent
|
||||||
|
intent = new IntentBox("test", "Hello")
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("Intent name: " + intent.name)
|
||||||
|
console.log("Intent payload: " + intent.payload)
|
||||||
|
|
||||||
|
// P2PBox作成テスト
|
||||||
|
local node
|
||||||
|
node = new P2PBox("test_node", "inprocess")
|
||||||
|
console.log("Node ID: " + node.nodeId())
|
||||||
|
|
||||||
|
// MessageBus基本動作
|
||||||
|
local bus
|
||||||
|
bus = MessageBus.global()
|
||||||
|
console.log("MessageBus Ready: " + bus.isReady())
|
||||||
55
tests/development/test_p2p_phase1_basic.nyash
Normal file
55
tests/development/test_p2p_phase1_basic.nyash
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// 🧪 P2PBox Phase 1: 基本テスト
|
||||||
|
// 目標: IntentBox作成・P2PBox基本動作・MessageBus確認
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🚀 Phase 1: P2PBox基本テスト開始")
|
||||||
|
|
||||||
|
// 1.1 IntentBox基本テスト
|
||||||
|
console.log("\n📦 1.1 IntentBox基本テスト")
|
||||||
|
|
||||||
|
local intent
|
||||||
|
intent = new IntentBox("test", "Hello")
|
||||||
|
console.log("✅ IntentBox作成成功")
|
||||||
|
console.log("Intent名: " + intent.getName()) // "test"
|
||||||
|
console.log("Payload: " + intent.getPayload()) // "Hello"
|
||||||
|
|
||||||
|
// 異なるペイロードでのテスト
|
||||||
|
local msgIntent
|
||||||
|
msgIntent = new IntentBox("message", "Hello P2P World!")
|
||||||
|
console.log("✅ メッセージIntentBox作成成功")
|
||||||
|
console.log("Intent名: " + msgIntent.getName()) // "message"
|
||||||
|
console.log("Payload: " + msgIntent.getPayload()) // "Hello P2P World!"
|
||||||
|
|
||||||
|
// 1.2 P2PBox作成テスト
|
||||||
|
console.log("\n🌐 1.2 P2PBox作成テスト")
|
||||||
|
|
||||||
|
local node
|
||||||
|
node = new P2PBox("test_node", "inprocess")
|
||||||
|
console.log("✅ P2PBox作成成功")
|
||||||
|
console.log("ノードID: " + node.getNodeId()) // "test_node"
|
||||||
|
|
||||||
|
// 複数ノード作成テスト
|
||||||
|
local alice
|
||||||
|
local bob
|
||||||
|
alice = new P2PBox("alice", "inprocess")
|
||||||
|
bob = new P2PBox("bob", "inprocess")
|
||||||
|
console.log("✅ 複数P2PBox作成成功")
|
||||||
|
console.log("Alice ID: " + alice.getNodeId()) // "alice"
|
||||||
|
console.log("Bob ID: " + bob.getNodeId()) // "bob"
|
||||||
|
|
||||||
|
// 1.3 MessageBus基本動作テスト
|
||||||
|
console.log("\n🚌 1.3 MessageBus基本動作テスト")
|
||||||
|
|
||||||
|
// Note: MessageBusはシングルトンなので直接テストは難しいが、
|
||||||
|
// P2PBoxが正常に作成できていることでMessageBusも動作していると判断
|
||||||
|
console.log("✅ MessageBus動作確認(P2PBox作成成功により間接確認)")
|
||||||
|
|
||||||
|
// 基本統計
|
||||||
|
console.log("\n📊 Phase 1テスト結果統計")
|
||||||
|
console.log("作成されたIntentBox数: 2")
|
||||||
|
console.log("作成されたP2PBox数: 3")
|
||||||
|
console.log("テストされた機能: IntentBox作成、P2PBox作成、ノードID取得")
|
||||||
|
|
||||||
|
console.log("\n🎉 Phase 1: 基本テスト完了!")
|
||||||
|
console.log("次はPhase 2: P2P通信テストに進みます")
|
||||||
12
tests/development/test_p2p_phase1_methods.nyash
Normal file
12
tests/development/test_p2p_phase1_methods.nyash
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Phase 1: IntentBox基本テスト(メソッド形式)
|
||||||
|
local intent
|
||||||
|
intent = new IntentBox("test", "Hello")
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("Intent created: " + intent.toString())
|
||||||
|
|
||||||
|
// P2PBox作成テスト
|
||||||
|
local node
|
||||||
|
node = new P2PBox("test_node", "inprocess")
|
||||||
|
console.log("P2PBox created: " + node.toString())
|
||||||
13
tests/development/test_p2p_phase1_simple.nyash
Normal file
13
tests/development/test_p2p_phase1_simple.nyash
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Phase 1: IntentBox基本テスト(簡単版)
|
||||||
|
local intent
|
||||||
|
intent = new IntentBox("test", "Hello")
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("Intent name: " + intent.name)
|
||||||
|
console.log("Intent payload: " + intent.payload)
|
||||||
|
|
||||||
|
// P2PBox作成テスト
|
||||||
|
local node
|
||||||
|
node = new P2PBox("test_node", "inprocess")
|
||||||
|
console.log("Node ID: " + node.nodeId())
|
||||||
76
tests/development/test_p2p_phase2_communication.nyash
Normal file
76
tests/development/test_p2p_phase2_communication.nyash
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 🌐 P2PBox Phase 2: P2P通信テスト
|
||||||
|
// 目標: 同プロセス内P2P通信・ハンドラ登録・メッセージ送受信確認
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🌐 Phase 2: P2P通信テスト開始")
|
||||||
|
|
||||||
|
// 2.1 同プロセス内P2P通信セットアップ
|
||||||
|
console.log("\n🔗 2.1 同プロセス内P2P通信セットアップ")
|
||||||
|
|
||||||
|
local node_a
|
||||||
|
local node_b
|
||||||
|
node_a = new P2PBox("alice", "inprocess")
|
||||||
|
node_b = new P2PBox("bob", "inprocess")
|
||||||
|
|
||||||
|
console.log("✅ ノード作成完了")
|
||||||
|
console.log("Alice ID: " + node_a.getNodeId())
|
||||||
|
console.log("Bob ID: " + node_b.getNodeId())
|
||||||
|
|
||||||
|
// 2.2 ハンドラ登録・メッセージ受信テスト
|
||||||
|
console.log("\n📥 2.2 メッセージハンドラ登録テスト")
|
||||||
|
|
||||||
|
// 受信カウンタ初期化
|
||||||
|
local receivedCount
|
||||||
|
receivedCount = 0
|
||||||
|
|
||||||
|
// Bobにメッセージハンドラ登録(chatメッセージ用)
|
||||||
|
console.log("Bob用chatハンドラ登録中...")
|
||||||
|
|
||||||
|
// 注意: ハンドラ登録のAPIを確認する必要あり
|
||||||
|
// 想定されるAPI: node_b.on("chat", handler_function)
|
||||||
|
// しかし、現在の実装でfunction型がサポートされているかチェックが必要
|
||||||
|
|
||||||
|
console.log("⚠️ ハンドラ登録API確認が必要")
|
||||||
|
console.log("予想API: node_b.on(\"chat\", handler_function)")
|
||||||
|
|
||||||
|
// 2.3 基本メッセージ送信テスト(ハンドラなし版)
|
||||||
|
console.log("\n📤 2.3 基本メッセージ送信テスト")
|
||||||
|
|
||||||
|
local msg
|
||||||
|
msg = new IntentBox("greeting", "Hello from Alice!")
|
||||||
|
|
||||||
|
console.log("送信メッセージ作成:")
|
||||||
|
console.log("Intent名: " + msg.getName())
|
||||||
|
console.log("Payload: " + msg.getPayload())
|
||||||
|
|
||||||
|
// メッセージ送信(現在のsend APIを確認)
|
||||||
|
console.log("\n📡 メッセージ送信実行...")
|
||||||
|
|
||||||
|
// 送信API確認が必要
|
||||||
|
console.log("⚠️ 送信API確認が必要")
|
||||||
|
console.log("予想API: node_a.send(\"bob\", msg)")
|
||||||
|
|
||||||
|
// 2.4 到達可能性テスト
|
||||||
|
console.log("\n🔍 2.4 ノード到達可能性テスト")
|
||||||
|
|
||||||
|
// 到達可能性チェック(isReachableメソッドがあるかテスト)
|
||||||
|
console.log("Alice → Bob 到達可能性チェック...")
|
||||||
|
console.log("⚠️ isReachableAPI確認が必要")
|
||||||
|
console.log("予想API: node_a.isReachable(\"bob\")")
|
||||||
|
|
||||||
|
// 2.5 Phase 2テスト結果
|
||||||
|
console.log("\n📊 Phase 2テスト結果統計")
|
||||||
|
console.log("✅ ノード作成: 成功")
|
||||||
|
console.log("✅ IntentBox作成: 成功")
|
||||||
|
console.log("⚠️ ハンドラ登録: API確認要")
|
||||||
|
console.log("⚠️ メッセージ送信: API確認要")
|
||||||
|
console.log("⚠️ 到達可能性チェック: API確認要")
|
||||||
|
|
||||||
|
console.log("\n🎯 Phase 2次のステップ:")
|
||||||
|
console.log("1. P2PBox.on() ハンドラ登録API確認")
|
||||||
|
console.log("2. P2PBox.send() メッセージ送信API確認")
|
||||||
|
console.log("3. P2PBox.isReachable() 到達可能性API確認")
|
||||||
|
console.log("4. Function型サポートの確認")
|
||||||
|
|
||||||
|
console.log("\n🚧 Phase 2: API確認段階完了")
|
||||||
97
tests/development/test_p2p_phase2_real.nyash
Normal file
97
tests/development/test_p2p_phase2_real.nyash
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// 🌐 P2PBox Phase 2: 実際のP2P通信テスト
|
||||||
|
// 目標: send・isReachable API実証テスト
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🌐 Phase 2: 実際のP2P通信テスト開始")
|
||||||
|
|
||||||
|
// 2.1 ノードセットアップ
|
||||||
|
console.log("\n🔗 2.1 P2Pノードセットアップ")
|
||||||
|
|
||||||
|
local alice
|
||||||
|
local bob
|
||||||
|
alice = new P2PBox("alice", "inprocess")
|
||||||
|
bob = new P2PBox("bob", "inprocess")
|
||||||
|
|
||||||
|
console.log("✅ ノード作成完了")
|
||||||
|
console.log("Alice: " + alice.getNodeId())
|
||||||
|
console.log("Bob: " + bob.getNodeId())
|
||||||
|
|
||||||
|
// 2.2 到達可能性テスト
|
||||||
|
console.log("\n🔍 2.2 到達可能性テスト")
|
||||||
|
|
||||||
|
local alice_to_bob
|
||||||
|
local bob_to_alice
|
||||||
|
alice_to_bob = alice.isReachable("bob")
|
||||||
|
bob_to_alice = bob.isReachable("alice")
|
||||||
|
|
||||||
|
console.log("Alice → Bob 到達可能: " + alice_to_bob)
|
||||||
|
console.log("Bob → Alice 到達可能: " + bob_to_alice)
|
||||||
|
|
||||||
|
// 存在しないノードテスト
|
||||||
|
local alice_to_unknown
|
||||||
|
alice_to_unknown = alice.isReachable("unknown_node")
|
||||||
|
console.log("Alice → Unknown 到達可能: " + alice_to_unknown)
|
||||||
|
|
||||||
|
// 2.3 メッセージ送信テスト
|
||||||
|
console.log("\n📤 2.3 メッセージ送信テスト")
|
||||||
|
|
||||||
|
local greeting
|
||||||
|
greeting = new IntentBox("greeting", "Hello from Alice!")
|
||||||
|
|
||||||
|
console.log("送信メッセージ:")
|
||||||
|
console.log("- Intent: " + greeting.getName())
|
||||||
|
console.log("- Payload: " + greeting.getPayload())
|
||||||
|
|
||||||
|
// Alice → Bob メッセージ送信
|
||||||
|
console.log("\n📡 Alice → Bob 送信実行...")
|
||||||
|
local send_result
|
||||||
|
send_result = alice.send("bob", greeting)
|
||||||
|
console.log("送信結果: " + send_result)
|
||||||
|
|
||||||
|
// 2.4 複数メッセージ送信テスト
|
||||||
|
console.log("\n📨 2.4 複数メッセージ送信テスト")
|
||||||
|
|
||||||
|
local chat_msg
|
||||||
|
local info_msg
|
||||||
|
|
||||||
|
chat_msg = new IntentBox("chat", "こんにちは!")
|
||||||
|
info_msg = new IntentBox("info", "システム情報です")
|
||||||
|
|
||||||
|
local result1
|
||||||
|
local result2
|
||||||
|
result1 = alice.send("bob", chat_msg)
|
||||||
|
result2 = alice.send("bob", info_msg)
|
||||||
|
|
||||||
|
console.log("Chat送信結果: " + result1)
|
||||||
|
console.log("Info送信結果: " + result2)
|
||||||
|
|
||||||
|
// Bob → Alice 送信もテスト
|
||||||
|
local reply_msg
|
||||||
|
reply_msg = new IntentBox("reply", "返信メッセージです")
|
||||||
|
|
||||||
|
local result3
|
||||||
|
result3 = bob.send("alice", reply_msg)
|
||||||
|
console.log("Bob → Alice 送信結果: " + result3)
|
||||||
|
|
||||||
|
// 2.5 エラーケーステスト
|
||||||
|
console.log("\n⚠️ 2.5 エラーケーステスト")
|
||||||
|
|
||||||
|
// 存在しないノードへの送信
|
||||||
|
local error_msg
|
||||||
|
error_msg = new IntentBox("test", "This should fail")
|
||||||
|
|
||||||
|
console.log("存在しないノード宛送信テスト...")
|
||||||
|
// このテストはエラーが予想される
|
||||||
|
console.log("予想: 送信エラーが発生")
|
||||||
|
|
||||||
|
// 2.6 Phase 2結果統計
|
||||||
|
console.log("\n📊 2.6 Phase 2テスト結果")
|
||||||
|
console.log("✅ ノード作成: 成功")
|
||||||
|
console.log("✅ 到達可能性チェック: 成功")
|
||||||
|
console.log("✅ メッセージ送信: 実行済み")
|
||||||
|
console.log("✅ 複数メッセージ送信: 実行済み")
|
||||||
|
console.log("✅ 双方向通信: 実行済み")
|
||||||
|
|
||||||
|
console.log("\n🎉 Phase 2: 基本P2P通信機能確認完了!")
|
||||||
|
console.log("次はPhase 3: デリゲーション・override革命へ!")
|
||||||
127
tests/development/test_p2p_phase3_delegation.nyash
Normal file
127
tests/development/test_p2p_phase3_delegation.nyash
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// 🔥 P2PBox Phase 3: デリゲーション・override革命!
|
||||||
|
// 目標: P2PBoxデリゲーション実装・Everything is Box哲学の完全実証
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🔥 Phase 3: デリゲーション・override革命開始!")
|
||||||
|
|
||||||
|
// 3.1 P2PBoxデリゲーション - ChatNodeBox実装
|
||||||
|
console.log("\n📦 3.1 ChatNodeBox(P2PBoxデリゲーション)実装")
|
||||||
|
|
||||||
|
// Nyashのデリゲーション構文:box Child from Parent
|
||||||
|
box ChatNodeBox from P2PBox {
|
||||||
|
init { chatHistory, messageCount }
|
||||||
|
|
||||||
|
pack(nodeId, transport) {
|
||||||
|
from P2PBox.pack(nodeId, transport) // 親の初期化
|
||||||
|
me.chatHistory = new ArrayBox()
|
||||||
|
me.messageCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.2 send()メソッドのoverride - ログ機能追加
|
||||||
|
override send(to, intent) {
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("📤 [ChatNode] Sending: " + intent.getName() + " to " + to)
|
||||||
|
|
||||||
|
// 履歴に記録
|
||||||
|
local logEntry
|
||||||
|
logEntry = "SENT:" + intent.getName() + ":" + to
|
||||||
|
me.chatHistory.push(logEntry)
|
||||||
|
me.messageCount = me.messageCount + 1
|
||||||
|
|
||||||
|
// 親のsend()を呼び出し
|
||||||
|
return from P2PBox.send(to, intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.3 getNodeId()のoverride - 拡張情報付き
|
||||||
|
override getNodeId() {
|
||||||
|
local baseId
|
||||||
|
baseId = from P2PBox.getNodeId()
|
||||||
|
return "[Chat]" + baseId + "(" + me.messageCount + "msgs)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.4 独自メソッド追加
|
||||||
|
getChatStats() {
|
||||||
|
return "Messages: " + me.messageCount + ", History: " + me.chatHistory.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastMessage() {
|
||||||
|
if me.chatHistory.length() > 0 {
|
||||||
|
return me.chatHistory.get(me.chatHistory.length() - 1)
|
||||||
|
} else {
|
||||||
|
return "No messages"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.5 デリゲーション動作テスト
|
||||||
|
console.log("\n🚀 3.5 ChatNodeBox作成・動作テスト")
|
||||||
|
|
||||||
|
local chatAlice
|
||||||
|
local regularBob
|
||||||
|
|
||||||
|
chatAlice = new ChatNodeBox("alice", "inprocess")
|
||||||
|
regularBob = new P2PBox("bob", "inprocess")
|
||||||
|
|
||||||
|
console.log("✅ ChatNodeBox作成完了")
|
||||||
|
console.log("ChatAlice ID: " + chatAlice.getNodeId()) // override版
|
||||||
|
console.log("Regular Bob ID: " + regularBob.getNodeId()) // 通常版
|
||||||
|
|
||||||
|
// 3.6 override機能テスト
|
||||||
|
console.log("\n🔄 3.6 Override send()メソッドテスト")
|
||||||
|
|
||||||
|
local chatMsg1
|
||||||
|
local chatMsg2
|
||||||
|
|
||||||
|
chatMsg1 = new IntentBox("chat", "Hello from ChatNode!")
|
||||||
|
chatMsg2 = new IntentBox("info", "System message")
|
||||||
|
|
||||||
|
console.log("送信テスト1:")
|
||||||
|
local result1
|
||||||
|
result1 = chatAlice.send("bob", chatMsg1) // override版send
|
||||||
|
console.log("送信結果: " + result1)
|
||||||
|
|
||||||
|
console.log("\n送信テスト2:")
|
||||||
|
local result2
|
||||||
|
result2 = chatAlice.send("bob", chatMsg2) // override版send
|
||||||
|
console.log("送信結果: " + result2)
|
||||||
|
|
||||||
|
// 3.7 独自メソッドテスト
|
||||||
|
console.log("\n📊 3.7 ChatNodeBox独自機能テスト")
|
||||||
|
|
||||||
|
console.log("Chat統計: " + chatAlice.getChatStats())
|
||||||
|
console.log("最新メッセージ: " + chatAlice.getLastMessage())
|
||||||
|
console.log("更新されたID: " + chatAlice.getNodeId()) // カウント更新確認
|
||||||
|
|
||||||
|
// 3.8 通常P2PBoxとの比較テスト
|
||||||
|
console.log("\n⚖️ 3.8 ChatNodeBox vs 通常P2PBox比較")
|
||||||
|
|
||||||
|
local normalMsg
|
||||||
|
normalMsg = new IntentBox("normal", "Normal P2P message")
|
||||||
|
|
||||||
|
console.log("通常P2PBox送信:")
|
||||||
|
local normalResult
|
||||||
|
normalResult = regularBob.send("alice", normalMsg) // 通常版send
|
||||||
|
console.log("通常送信結果: " + normalResult)
|
||||||
|
|
||||||
|
console.log("\nChatNodeBox送信:")
|
||||||
|
local chatResult
|
||||||
|
chatResult = chatAlice.send("bob", normalMsg) // override版send
|
||||||
|
console.log("Chat送信結果: " + chatResult)
|
||||||
|
|
||||||
|
// 3.9 Revolution成果確認
|
||||||
|
console.log("\n🎉 3.9 Everything is Box + デリゲーション革命成果")
|
||||||
|
|
||||||
|
console.log("✅ P2PBoxデリゲーション: 成功")
|
||||||
|
console.log("✅ Override機能: send()・getNodeId()正常動作")
|
||||||
|
console.log("✅ 独自メソッド: getChatStats()・getLastMessage()追加")
|
||||||
|
console.log("✅ 親機能継承: isReachable()など全て利用可能")
|
||||||
|
console.log("✅ ログ機能: 送信履歴記録・カウント機能")
|
||||||
|
|
||||||
|
console.log("\n🌟 最終統計:")
|
||||||
|
console.log("- 送信メッセージ総数: " + chatAlice.getChatStats())
|
||||||
|
console.log("- ノードID拡張表示: " + chatAlice.getNodeId())
|
||||||
|
console.log("- 最新ログエントリ: " + chatAlice.getLastMessage())
|
||||||
|
|
||||||
|
console.log("\n🔥🔥🔥 Phase 3: デリゲーション・override革命完全達成! 🔥🔥🔥")
|
||||||
|
console.log("Everything is Box哲学 + P2P通信 + デリゲーション = 完全統合成功!")
|
||||||
150
tests/development/test_p2p_phase3_user_delegation.nyash
Normal file
150
tests/development/test_p2p_phase3_user_delegation.nyash
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// 🔥 P2PBox Phase 3B: ユーザー定義Box間デリゲーション実証
|
||||||
|
// 目標: ユーザー定義Box同士のデリゲーション・override完全実証
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("🔥 Phase 3B: ユーザー定義デリゲーション革命!")
|
||||||
|
|
||||||
|
// 3B.1 BaseNodeBox(ユーザー定義)作成
|
||||||
|
console.log("\n📦 3B.1 BaseNodeBox(ユーザー定義)実装")
|
||||||
|
|
||||||
|
box BaseNodeBox {
|
||||||
|
init { nodeId, messageCount }
|
||||||
|
|
||||||
|
pack(id) {
|
||||||
|
me.nodeId = id
|
||||||
|
me.messageCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
getId() {
|
||||||
|
return me.nodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(target, message) {
|
||||||
|
me.messageCount = me.messageCount + 1
|
||||||
|
return "BaseNode sent: " + message + " to " + target
|
||||||
|
}
|
||||||
|
|
||||||
|
getMessageCount() {
|
||||||
|
return me.messageCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B.2 ChatNodeBox(BaseNodeBoxからデリゲーション)
|
||||||
|
console.log("\n🔄 3B.2 ChatNodeBox(BaseNodeBoxデリゲーション)実装")
|
||||||
|
|
||||||
|
box ChatNodeBox from BaseNodeBox {
|
||||||
|
init { chatHistory, specialFeature }
|
||||||
|
|
||||||
|
pack(id, feature) {
|
||||||
|
from BaseNodeBox.pack(id) // 親の初期化
|
||||||
|
me.chatHistory = new ArrayBox()
|
||||||
|
me.specialFeature = feature
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B.3 sendMessage()のoverride - ログ機能追加
|
||||||
|
override sendMessage(target, message) {
|
||||||
|
local logEntry
|
||||||
|
logEntry = "[CHAT] " + message + " -> " + target
|
||||||
|
me.chatHistory.push(logEntry)
|
||||||
|
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("📤 ChatNode override: " + logEntry)
|
||||||
|
|
||||||
|
// 親のsendMessage()を呼び出し
|
||||||
|
return from BaseNodeBox.sendMessage(target, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B.4 getId()のoverride - 拡張情報付き
|
||||||
|
override getId() {
|
||||||
|
local baseId
|
||||||
|
baseId = from BaseNodeBox.getId()
|
||||||
|
return "[" + me.specialFeature + "]" + baseId + "(" + me.getMessageCount() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B.5 独自メソッド追加
|
||||||
|
getChatHistory() {
|
||||||
|
return me.chatHistory.length() + " chat messages logged"
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastChat() {
|
||||||
|
if me.chatHistory.length() > 0 {
|
||||||
|
return me.chatHistory.get(me.chatHistory.length() - 1)
|
||||||
|
} else {
|
||||||
|
return "No chats yet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B.6 デリゲーション動作テスト
|
||||||
|
console.log("\n🚀 3B.6 ユーザー定義デリゲーション動作テスト")
|
||||||
|
|
||||||
|
local baseNode
|
||||||
|
local chatNode
|
||||||
|
|
||||||
|
baseNode = new BaseNodeBox("base_alice")
|
||||||
|
chatNode = new ChatNodeBox("chat_bob", "AdvancedChat")
|
||||||
|
|
||||||
|
console.log("✅ ノード作成完了")
|
||||||
|
console.log("BaseNode ID: " + baseNode.getId())
|
||||||
|
console.log("ChatNode ID: " + chatNode.getId()) // override版
|
||||||
|
|
||||||
|
// 3B.7 Override機能テスト
|
||||||
|
console.log("\n🔄 3B.7 Override sendMessage()テスト")
|
||||||
|
|
||||||
|
local result1
|
||||||
|
local result2
|
||||||
|
|
||||||
|
result1 = baseNode.sendMessage("target1", "Hello from base")
|
||||||
|
console.log("Base送信結果: " + result1)
|
||||||
|
|
||||||
|
result2 = chatNode.sendMessage("target2", "Hello from chat") // override版
|
||||||
|
console.log("Chat送信結果: " + result2)
|
||||||
|
|
||||||
|
// 3B.8 複数メッセージテスト
|
||||||
|
console.log("\n📨 3B.8 複数メッセージ送信テスト")
|
||||||
|
|
||||||
|
local result3
|
||||||
|
local result4
|
||||||
|
|
||||||
|
result3 = chatNode.sendMessage("alice", "First chat message")
|
||||||
|
result4 = chatNode.sendMessage("bob", "Second chat message")
|
||||||
|
|
||||||
|
console.log("結果3: " + result3)
|
||||||
|
console.log("結果4: " + result4)
|
||||||
|
|
||||||
|
// 3B.9 独自メソッド・継承メソッドテスト
|
||||||
|
console.log("\n📊 3B.9 独自メソッド・継承機能テスト")
|
||||||
|
|
||||||
|
console.log("Chat履歴: " + chatNode.getChatHistory())
|
||||||
|
console.log("最新Chat: " + chatNode.getLastChat())
|
||||||
|
console.log("更新されたID: " + chatNode.getId()) // カウント更新確認
|
||||||
|
|
||||||
|
// 継承されたメソッドの動作確認
|
||||||
|
console.log("継承されたカウント: " + chatNode.getMessageCount())
|
||||||
|
|
||||||
|
// 3B.10 ベースノードとの比較
|
||||||
|
console.log("\n⚖️ 3B.10 BaseNode vs ChatNode比較")
|
||||||
|
|
||||||
|
console.log("BaseNode カウント: " + baseNode.getMessageCount())
|
||||||
|
console.log("ChatNode カウント: " + chatNode.getMessageCount())
|
||||||
|
|
||||||
|
console.log("BaseNode ID: " + baseNode.getId())
|
||||||
|
console.log("ChatNode ID: " + chatNode.getId())
|
||||||
|
|
||||||
|
// 3B.11 Revolution成果確認
|
||||||
|
console.log("\n🎉 3B.11 ユーザー定義デリゲーション革命成果")
|
||||||
|
|
||||||
|
console.log("✅ ユーザー定義Boxデリゲーション: 完全成功")
|
||||||
|
console.log("✅ Override機能: sendMessage()・getId()正常動作")
|
||||||
|
console.log("✅ 独自メソッド: getChatHistory()・getLastChat()追加")
|
||||||
|
console.log("✅ 親機能継承: getMessageCount()正常動作")
|
||||||
|
console.log("✅ from構文: 親メソッド呼び出し成功")
|
||||||
|
|
||||||
|
console.log("\n🌟 最終統計:")
|
||||||
|
console.log("- ChatNode送信数: " + chatNode.getMessageCount())
|
||||||
|
console.log("- Chat履歴統計: " + chatNode.getChatHistory())
|
||||||
|
console.log("- 最新Chatログ: " + chatNode.getLastChat())
|
||||||
|
|
||||||
|
console.log("\n🔥🔥🔥 Phase 3B: ユーザー定義デリゲーション革命完全達成! 🔥🔥🔥")
|
||||||
|
console.log("Everything is Box + デリゲーション + Override = 完全動作実証!")
|
||||||
14
tests/development/test_p2p_simple.nyash
Normal file
14
tests/development/test_p2p_simple.nyash
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Simple P2P Test - Basic functionality check
|
||||||
|
print("=== Simple P2P Test ===")
|
||||||
|
|
||||||
|
// Test 1: Create IntentBox
|
||||||
|
local msg
|
||||||
|
msg = new IntentBox("test.message", "Hello P2P")
|
||||||
|
print("✅ IntentBox created: " + msg.getName())
|
||||||
|
|
||||||
|
// Test 2: Create P2PBox
|
||||||
|
local node
|
||||||
|
node = new P2PBox("test_node", "inprocess")
|
||||||
|
print("✅ P2PBox created: " + node.getNodeId())
|
||||||
|
|
||||||
|
print("✅ P2P system is working!")
|
||||||
17
tests/development/test_pack_syntax.nyash
Normal file
17
tests/development/test_pack_syntax.nyash
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// pack構文テスト
|
||||||
|
box User {
|
||||||
|
init { name, email }
|
||||||
|
|
||||||
|
pack(userName, userEmail) {
|
||||||
|
me.name = userName
|
||||||
|
me.email = userEmail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local user
|
||||||
|
user = new User("Alice", "alice@example.com")
|
||||||
|
|
||||||
|
local console
|
||||||
|
console = new ConsoleBox()
|
||||||
|
console.log("User name: " + user.name)
|
||||||
|
console.log("User email: " + user.email)
|
||||||
14
tests/development/test_simple_constructor.nyash
Normal file
14
tests/development/test_simple_constructor.nyash
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
// シンプルなコンストラクタテスト
|
||||||
|
box TestBox {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
me.value = "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local t
|
||||||
|
t = new TestBox()
|
||||||
|
print("Value: " + t.value)
|
||||||
|
|
||||||
23
tests/development/test_simple_from.nyash
Normal file
23
tests/development/test_simple_from.nyash
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// シンプルなfrom構文テスト
|
||||||
|
box Parent {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child from Parent {
|
||||||
|
init { extra }
|
||||||
|
|
||||||
|
test() {
|
||||||
|
// 親のフィールドに直接アクセス
|
||||||
|
me.value = "Set from Child"
|
||||||
|
me.extra = " (extra)"
|
||||||
|
return me.getValue() + me.extra
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local c
|
||||||
|
c = new Child()
|
||||||
|
print("Result: " + c.test())
|
||||||
16
tests/development/test_simple_init.nyash
Normal file
16
tests/development/test_simple_init.nyash
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// シンプルなinit構文テスト
|
||||||
|
box Test {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
init(testValue) {
|
||||||
|
me.value = testValue
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local t
|
||||||
|
t = new Test("Hello init!")
|
||||||
|
print(t.getValue())
|
||||||
48
tests/development/test_user_box_delegation.nyash
Normal file
48
tests/development/test_user_box_delegation.nyash
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
// ユーザー定義Box同士でのデリゲーションテスト
|
||||||
|
box Parent {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
init(value) { # init構文に統一
|
||||||
|
me.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return me.value
|
||||||
|
}
|
||||||
|
|
||||||
|
process(x) {
|
||||||
|
return "Parent processing: " + x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child from Parent {
|
||||||
|
init { extra }
|
||||||
|
|
||||||
|
init(value, extra) { # init構文に統一
|
||||||
|
from Parent.init(value) # 親コンストラクタ呼び出し
|
||||||
|
me.extra = extra
|
||||||
|
}
|
||||||
|
|
||||||
|
override process(x) { // 明示的オーバーライド
|
||||||
|
local result
|
||||||
|
result = from Parent.process(x) // 親メソッド呼び出し
|
||||||
|
return result + " (Child added: " + me.extra + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll() {
|
||||||
|
return me.getValue() + " / " + me.extra
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// テスト実行
|
||||||
|
local p, c
|
||||||
|
p = new Parent("parent value")
|
||||||
|
print("Parent getValue: " + p.getValue())
|
||||||
|
print("Parent process: " + p.process("test"))
|
||||||
|
|
||||||
|
c = new Child("child value", "extra data")
|
||||||
|
print("Child getValue: " + c.getValue()) // デリゲートされたメソッド
|
||||||
|
print("Child process: " + c.process("test")) // オーバーライドされたメソッド
|
||||||
|
print("Child getAll: " + c.getAll())
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user