docs: reorganize into 説明書/予定/archive; update docs/README.md and CLAUDE.md; move root .nyash to local_tests; consolidate native-plan notes into README + archive

This commit is contained in:
Moe Charm
2025-08-13 18:19:49 +09:00
parent 7941c4ed6a
commit 621bf7cc3d
154 changed files with 11342 additions and 236 deletions

View 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を段階的に整備するのが最も効果的。

View 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あり版」を並記

View 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)
```

View 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 へ最終ルール・エラーメッセージ・サンプルを移植。

View 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 values 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() => Childs 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.

View 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 後は使用禁止をガードで強制、誤用を早期検知。

View 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`(将来案)を付与したフィールドは自動カスケード対象から除外。

View 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

View 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: メトリクス・エラーの可視化を追加(検証再現性の強化)。

View 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/`)を参照。

View 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ページで切替・確認可能。