From 621bf7cc3da29005354354c9038106cec44eb70b Mon Sep 17 00:00:00 2001 From: Moe Charm Date: Wed, 13 Aug 2025 18:19:49 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20reorganize=20into=20=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E6=9B=B8/=E4=BA=88=E5=AE=9A/archive;=20update=20docs/README.md?= =?UTF-8?q?=20and=20CLAUDE.md;=20move=20root=20.nyash=20to=20local=5Ftests?= =?UTF-8?q?;=20consolidate=20native-plan=20notes=20into=20README=20+=20arc?= =?UTF-8?q?hive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 51 +- CURRENT_TASK.md => docs/CURRENT_TASK.md | 0 docs/README.md | 107 +-- docs/{ => archive}/GETTING_STARTED.md | 0 docs/{ => archive}/LANGUAGE_OVERVIEW_2025.md | 0 .../archive/MAPBOX_HANG_BUG_REPORT.md | 0 .../archive/P2P_IMPLEMENTATION_ISSUE.md | 0 README.ja.md => docs/archive/README.ja.md | 0 docs/archive/README.md | 97 ++ .../ai_conference_overload_decision.md | 0 docs/archive/build_error.txt | 41 + docs/archive/build_errors.txt | 328 +++++++ docs/archive/build_log.txt | 0 docs/archive/build_output.txt | 0 .../chatgpt5/インタープリタ評価.txt | 0 .../chatgpt5/プレイグラウンド_ガイド.md | 0 .../chatgpt5/プレイグラウンド_サンプル.md | 0 .../chatgpt5/実装TODO_解放とガード.txt | 0 .../chatgpt5/実装計画_fini統合.txt | 0 .../chatgpt5/解放ポリシー_fini.txt | 0 .../chatgpt5/解放ポリシー_エラーと診断.txt | 0 .../chatgpt5/解放ポリシー_例.txt | 0 .../設計RFC_多重デリゲーションとfini.txt | 0 docs/{ => archive}/chatgpt5/論文_サマリ.md | 0 .../chatgpt5/論文_プロダクト寄りドラフト.md | 0 .../explicit-delegation-revolution.md | 0 .../design/DELEGATION_DESIGN_SUMMARY.md | 0 .../design/NYASHFLOW_PROJECT_HANDOVER.md | 0 .../archive/design/PHILOSOPHY.md | 0 .../ai_conference_overload_decision.md | 103 ++ ...nsultation_constructor_design_question.txt | 51 + ..._consultation_override_design_question.txt | 106 +++ .../decisions}/architecture_consultation.txt | 0 ...onsultation_weak_architecture_decision.txt | 100 ++ .../chatgpt_consultation_overload.txt | 0 .../gemini_consultation_overload.txt | 0 ...consultation_weak_final_implementation.txt | 73 ++ ...ak_reference_architecture_consultation.txt | 40 + .../design/decisions/インタープリタ評価.txt | 56 ++ .../decisions/プレイグラウンド_サンプル.md | 65 ++ .../decisions/実装TODO_解放とガード.txt | 31 + .../design/decisions/実装計画_fini統合.txt | 92 ++ .../design/decisions/解放ポリシー_fini.txt | 63 ++ .../decisions/解放ポリシー_エラーと診断.txt | 39 + .../design/decisions/解放ポリシー_例.txt | 73 ++ .../設計RFC_多重デリゲーションとfini.txt | 94 ++ docs/archive/design/decisions/論文_サマリ.md | 126 +++ .../decisions/論文_プロダクト寄りドラフト.md | 81 ++ .../design/explicit-delegation-revolution.md} | 0 .../design}/lisp_interpreter_design.md | 0 docs/archive/design/technical_architecture.md | 393 ++++++++ .../geminichatgpt相談20250811.txt | 0 docs/archive/nativebuild大作戦/README.md | 12 + .../chatgptネイティブビルド大作戦.txt | 0 docs/archive/nyashvalue_build_errors.txt | 668 +++++++++++++ docs/archive/nyashvalue_check_errors.txt | 434 +++++++++ .../sessions/architecture_consultation.txt | 77 ++ .../chatgpt_consultation_overload.txt | 64 ++ .../sessions/gemini_consultation_overload.txt | 46 + docs/guides/how-to-build-native/README.md | 130 --- docs/nyash_core_concepts.md | 257 +++++ docs/予定/README.md | 5 + docs/予定/native-plan/README.md | 43 + .../archive/chatgptネイティブビルド大作戦.txt | 596 ++++++++++++ docs/予定/native-plan/archive/追記相談.txt | 898 ++++++++++++++++++ docs/予定/native-plan/copilot_issues.txt | 235 +++++ .../issues/phase5_2_static_main_lowering.md | 24 + .../issues/phase6_box_ops_minimal.md | 0 .../native-plan/issues/phase7_async_mir.md | 20 + .../issues/tooling_snapshot_printer.md | 13 + .../native-plan/issues/vm_profiling_backend.md | 13 + .../GETTING_STARTED.md} | 0 docs/説明書/GETTING_STARTED_2025.md | 547 +++++++++++ docs/{ => 説明書}/LANGUAGE_GUIDE.md | 0 docs/説明書/LANGUAGE_OVERVIEW_2025.md | 332 +++++++ docs/{ => 説明書}/P2P_GUIDE.md | 0 docs/説明書/README.md | 23 + docs/説明書/guides/1_getting_started.md | 547 +++++++++++ docs/説明書/guides/2_language_guide.md | 254 +++++ docs/説明書/guides/playground_guide.md | 102 ++ docs/{ => 説明書}/reference/builtin-boxes.md | 0 docs/説明書/reference/design-philosophy.md | 337 +++++++ .../reference/finalization-system.md | 0 .../reference/language-reference.md | 0 .../override-delegation-syntax.md | 0 docs/説明書/reference/language_spec.md | 525 ++++++++++ .../reference/override-delegation-syntax.md | 0 docs/説明書/reference/p2p_spec.md | 254 +++++ .../説明書/wasm/wasm_browser_plan.md | 0 .../説明書/wasm/wasm_quick_start.md | 0 examples/wasm/test_drawing_app.html | 53 ++ .../debug_from_test.nyash | 0 .../field_access_test.nyash | 0 .../mir_examples.nyash | 0 local_tests/mir_try_basic.nyash | 12 + local_tests/sample.nyash | 14 + .../simple_from_test.nyash | 0 .../simple_loop_test.nyash | 0 .../simple_loop_test2.nyash | 0 .../simple_loop_test3.nyash | 0 .../simple_test.nyash | 0 .../simple_throw_test.nyash | 0 .../simple_try_test.nyash | 0 local_tests/test_all_new_boxes.nyash | 58 ++ local_tests/test_array_box.nyash | 74 ++ local_tests/test_array_box_simple.nyash | 20 + local_tests/test_array_improvements.nyash | 81 ++ local_tests/test_array_methods.nyash | 65 ++ local_tests/test_array_simple.nyash | 23 + .../test_basic_box_comprehensive.nyash | 46 + local_tests/test_basic_box_constructors.nyash | 32 + local_tests/test_basic_boxes.nyash | 31 + local_tests/test_box_creation.nyash | 35 + local_tests/test_boxes.nyash | 56 ++ local_tests/test_buffer_box.nyash | 27 + local_tests/test_comparison_operators.nyash | 77 ++ local_tests/test_comprehensive_final.nyash | 68 ++ local_tests/test_cross_type_operators.nyash | 115 +++ local_tests/test_datetime_box.nyash | 43 + local_tests/test_datetime_tostring.nyash | 4 + local_tests/test_final_weak_demo.nyash | 83 ++ local_tests/test_fini_system.nyash | 119 +++ local_tests/test_fini_violations.nyash | 51 + local_tests/test_float_box.nyash | 49 + local_tests/test_float_box_issues.nyash | 22 + local_tests/test_float_tostring.nyash | 4 + local_tests/test_from_call.nyash | 106 +++ local_tests/test_intent_field_access.nyash | 23 + local_tests/test_intent_only.nyash | 6 + local_tests/test_invalid_override.nyash | 32 + local_tests/test_mir_simple.nyash | 6 + local_tests/test_multi_delegation.nyash | 28 + .../test_multi_delegation_advanced.nyash | 60 ++ local_tests/test_new_boxes.nyash | 113 +++ local_tests/test_new_operators.nyash | 62 ++ local_tests/test_operators.nyash | 100 ++ local_tests/test_override_validation.nyash | 48 + local_tests/test_p2p_basic.nyash | 61 ++ local_tests/test_p2p_basic_new.nyash | 116 +++ local_tests/test_p2p_callback_demo.nyash | 94 ++ local_tests/test_p2p_edge_cases.nyash | 86 ++ local_tests/test_p2p_message_types.nyash | 66 ++ local_tests/test_p2p_simple.nyash | 14 + local_tests/test_pack_syntax.nyash | 108 +++ local_tests/test_random_box.nyash | 32 + local_tests/test_weak_basic_fixed.nyash | 50 + local_tests/test_weak_comprehensive.nyash | 84 ++ local_tests/test_weak_detection.nyash | 38 + local_tests/test_weak_fini_prohibition.nyash | 37 + local_tests/test_weak_lifecycle.nyash | 62 ++ local_tests/test_weak_reference_basic.nyash | 50 + .../test_weak_reference_complete.nyash | 54 ++ local_tests/test_weak_simple.nyash | 54 ++ local_tests/test_working_weak_demo.nyash | 60 ++ 154 files changed, 11342 insertions(+), 236 deletions(-) rename CURRENT_TASK.md => docs/CURRENT_TASK.md (100%) rename docs/{ => archive}/GETTING_STARTED.md (100%) rename docs/{ => archive}/LANGUAGE_OVERVIEW_2025.md (100%) rename MAPBOX_HANG_BUG_REPORT.md => docs/archive/MAPBOX_HANG_BUG_REPORT.md (100%) rename P2P_IMPLEMENTATION_ISSUE.md => docs/archive/P2P_IMPLEMENTATION_ISSUE.md (100%) rename README.ja.md => docs/archive/README.ja.md (100%) create mode 100644 docs/archive/README.md rename ai_conference_overload_decision.md => docs/archive/ai_conference_overload_decision.md (100%) create mode 100644 docs/archive/build_error.txt create mode 100644 docs/archive/build_errors.txt create mode 100644 docs/archive/build_log.txt create mode 100644 docs/archive/build_output.txt rename docs/{ => archive}/chatgpt5/インタープリタ評価.txt (100%) rename docs/{ => archive}/chatgpt5/プレイグラウンド_ガイド.md (100%) rename docs/{ => archive}/chatgpt5/プレイグラウンド_サンプル.md (100%) rename docs/{ => archive}/chatgpt5/実装TODO_解放とガード.txt (100%) rename docs/{ => archive}/chatgpt5/実装計画_fini統合.txt (100%) rename docs/{ => archive}/chatgpt5/解放ポリシー_fini.txt (100%) rename docs/{ => archive}/chatgpt5/解放ポリシー_エラーと診断.txt (100%) rename docs/{ => archive}/chatgpt5/解放ポリシー_例.txt (100%) rename docs/{ => archive}/chatgpt5/設計RFC_多重デリゲーションとfini.txt (100%) rename docs/{ => archive}/chatgpt5/論文_サマリ.md (100%) rename docs/{ => archive}/chatgpt5/論文_プロダクト寄りドラフト.md (100%) rename docs/{ => archive}/design-philosophy/explicit-delegation-revolution.md (100%) rename DELEGATION_DESIGN_SUMMARY.md => docs/archive/design/DELEGATION_DESIGN_SUMMARY.md (100%) rename NYASHFLOW_PROJECT_HANDOVER.md => docs/archive/design/NYASHFLOW_PROJECT_HANDOVER.md (100%) rename PHILOSOPHY.md => docs/archive/design/PHILOSOPHY.md (100%) create mode 100644 docs/archive/design/decisions/ai_conference_overload_decision.md create mode 100644 docs/archive/design/decisions/ai_consultation_constructor_design_question.txt create mode 100644 docs/archive/design/decisions/ai_consultation_override_design_question.txt rename docs/{sessions => archive/design/decisions}/architecture_consultation.txt (100%) create mode 100644 docs/archive/design/decisions/chatgpt5_consultation_weak_architecture_decision.txt rename docs/{sessions => archive/design/decisions}/chatgpt_consultation_overload.txt (100%) rename docs/{sessions => archive/design/decisions}/gemini_consultation_overload.txt (100%) create mode 100644 docs/archive/design/decisions/gemini_consultation_weak_final_implementation.txt create mode 100644 docs/archive/design/decisions/weak_reference_architecture_consultation.txt create mode 100644 docs/archive/design/decisions/インタープリタ評価.txt create mode 100644 docs/archive/design/decisions/プレイグラウンド_サンプル.md create mode 100644 docs/archive/design/decisions/実装TODO_解放とガード.txt create mode 100644 docs/archive/design/decisions/実装計画_fini統合.txt create mode 100644 docs/archive/design/decisions/解放ポリシー_fini.txt create mode 100644 docs/archive/design/decisions/解放ポリシー_エラーと診断.txt create mode 100644 docs/archive/design/decisions/解放ポリシー_例.txt create mode 100644 docs/archive/design/decisions/設計RFC_多重デリゲーションとfini.txt create mode 100644 docs/archive/design/decisions/論文_サマリ.md create mode 100644 docs/archive/design/decisions/論文_プロダクト寄りドラフト.md rename docs/{reference/design-philosophy.md => archive/design/explicit-delegation-revolution.md} (100%) rename docs/{ => archive/design}/lisp_interpreter_design.md (100%) create mode 100644 docs/archive/design/technical_architecture.md rename docs/{ => archive}/geminichatgpt相談20250811.txt (100%) create mode 100644 docs/archive/nativebuild大作戦/README.md rename docs/{ => archive}/nativebuild大作戦/chatgptネイティブビルド大作戦.txt (100%) create mode 100644 docs/archive/nyashvalue_build_errors.txt create mode 100644 docs/archive/nyashvalue_check_errors.txt create mode 100644 docs/archive/sessions/architecture_consultation.txt create mode 100644 docs/archive/sessions/chatgpt_consultation_overload.txt create mode 100644 docs/archive/sessions/gemini_consultation_overload.txt delete mode 100644 docs/guides/how-to-build-native/README.md create mode 100644 docs/nyash_core_concepts.md create mode 100644 docs/予定/README.md create mode 100644 docs/予定/native-plan/README.md create mode 100644 docs/予定/native-plan/archive/chatgptネイティブビルド大作戦.txt create mode 100644 docs/予定/native-plan/archive/追記相談.txt create mode 100644 docs/予定/native-plan/copilot_issues.txt create mode 100644 docs/予定/native-plan/issues/phase5_2_static_main_lowering.md rename docs/{guides/how-to-build-native => 予定/native-plan}/issues/phase6_box_ops_minimal.md (100%) create mode 100644 docs/予定/native-plan/issues/phase7_async_mir.md create mode 100644 docs/予定/native-plan/issues/tooling_snapshot_printer.md create mode 100644 docs/予定/native-plan/issues/vm_profiling_backend.md rename docs/{GETTING_STARTED_2025.md => 説明書/GETTING_STARTED.md} (100%) create mode 100644 docs/説明書/GETTING_STARTED_2025.md rename docs/{ => 説明書}/LANGUAGE_GUIDE.md (100%) create mode 100644 docs/説明書/LANGUAGE_OVERVIEW_2025.md rename docs/{ => 説明書}/P2P_GUIDE.md (100%) create mode 100644 docs/説明書/README.md create mode 100644 docs/説明書/guides/1_getting_started.md create mode 100644 docs/説明書/guides/2_language_guide.md create mode 100644 docs/説明書/guides/playground_guide.md rename docs/{ => 説明書}/reference/builtin-boxes.md (100%) create mode 100644 docs/説明書/reference/design-philosophy.md rename docs/{ => 説明書}/reference/finalization-system.md (100%) rename docs/{ => 説明書}/reference/language-reference.md (100%) rename docs/{ => 説明書/reference}/language-specification/override-delegation-syntax.md (100%) create mode 100644 docs/説明書/reference/language_spec.md rename docs/{ => 説明書}/reference/override-delegation-syntax.md (100%) create mode 100644 docs/説明書/reference/p2p_spec.md rename wasm_browser_plan.md => docs/説明書/wasm/wasm_browser_plan.md (100%) rename wasm_quick_start.md => docs/説明書/wasm/wasm_quick_start.md (100%) create mode 100644 examples/wasm/test_drawing_app.html rename debug_from_test.nyash => local_tests/debug_from_test.nyash (100%) rename field_access_test.nyash => local_tests/field_access_test.nyash (100%) rename mir_examples.nyash => local_tests/mir_examples.nyash (100%) create mode 100644 local_tests/mir_try_basic.nyash create mode 100644 local_tests/sample.nyash rename simple_from_test.nyash => local_tests/simple_from_test.nyash (100%) rename simple_loop_test.nyash => local_tests/simple_loop_test.nyash (100%) rename simple_loop_test2.nyash => local_tests/simple_loop_test2.nyash (100%) rename simple_loop_test3.nyash => local_tests/simple_loop_test3.nyash (100%) rename simple_test.nyash => local_tests/simple_test.nyash (100%) rename simple_throw_test.nyash => local_tests/simple_throw_test.nyash (100%) rename simple_try_test.nyash => local_tests/simple_try_test.nyash (100%) create mode 100644 local_tests/test_all_new_boxes.nyash create mode 100644 local_tests/test_array_box.nyash create mode 100644 local_tests/test_array_box_simple.nyash create mode 100644 local_tests/test_array_improvements.nyash create mode 100644 local_tests/test_array_methods.nyash create mode 100644 local_tests/test_array_simple.nyash create mode 100644 local_tests/test_basic_box_comprehensive.nyash create mode 100644 local_tests/test_basic_box_constructors.nyash create mode 100644 local_tests/test_basic_boxes.nyash create mode 100644 local_tests/test_box_creation.nyash create mode 100644 local_tests/test_boxes.nyash create mode 100644 local_tests/test_buffer_box.nyash create mode 100644 local_tests/test_comparison_operators.nyash create mode 100644 local_tests/test_comprehensive_final.nyash create mode 100644 local_tests/test_cross_type_operators.nyash create mode 100644 local_tests/test_datetime_box.nyash create mode 100644 local_tests/test_datetime_tostring.nyash create mode 100644 local_tests/test_final_weak_demo.nyash create mode 100644 local_tests/test_fini_system.nyash create mode 100644 local_tests/test_fini_violations.nyash create mode 100644 local_tests/test_float_box.nyash create mode 100644 local_tests/test_float_box_issues.nyash create mode 100644 local_tests/test_float_tostring.nyash create mode 100644 local_tests/test_from_call.nyash create mode 100644 local_tests/test_intent_field_access.nyash create mode 100644 local_tests/test_intent_only.nyash create mode 100644 local_tests/test_invalid_override.nyash create mode 100644 local_tests/test_mir_simple.nyash create mode 100644 local_tests/test_multi_delegation.nyash create mode 100644 local_tests/test_multi_delegation_advanced.nyash create mode 100644 local_tests/test_new_boxes.nyash create mode 100644 local_tests/test_new_operators.nyash create mode 100644 local_tests/test_operators.nyash create mode 100644 local_tests/test_override_validation.nyash create mode 100644 local_tests/test_p2p_basic.nyash create mode 100644 local_tests/test_p2p_basic_new.nyash create mode 100644 local_tests/test_p2p_callback_demo.nyash create mode 100644 local_tests/test_p2p_edge_cases.nyash create mode 100644 local_tests/test_p2p_message_types.nyash create mode 100644 local_tests/test_p2p_simple.nyash create mode 100644 local_tests/test_pack_syntax.nyash create mode 100644 local_tests/test_random_box.nyash create mode 100644 local_tests/test_weak_basic_fixed.nyash create mode 100644 local_tests/test_weak_comprehensive.nyash create mode 100644 local_tests/test_weak_detection.nyash create mode 100644 local_tests/test_weak_fini_prohibition.nyash create mode 100644 local_tests/test_weak_lifecycle.nyash create mode 100644 local_tests/test_weak_reference_basic.nyash create mode 100644 local_tests/test_weak_reference_complete.nyash create mode 100644 local_tests/test_weak_simple.nyash create mode 100644 local_tests/test_working_weak_demo.nyash diff --git a/CLAUDE.md b/CLAUDE.md index ccbfc339..2d9e0e7a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,10 @@ Nyashプログラミング言語開発に必要な情報をまとめたクイックリファレンス。 +## 🧭 Start Here (最初に見る) +- 現在のタスク: docs/CURRENT_TASK.md +- コア概念(速習): docs/nyash_core_concepts.md + ## 🚀 クイックスタート ### 🐧 Linux/WSL版 @@ -31,27 +35,28 @@ cd projects/nyash-wasm ## 📚 ドキュメント構造 +- 説明書: docs/説明書/README.md + - ネイティブビルド: docs/説明書/native-build/README.md + - WASM: docs/説明書/wasm/ + - リファレンス: docs/説明書/reference/ +- 予定: docs/予定/README.md + - CURRENT_TASK, ネイティブ計画, フェーズ課題 +- archive: docs/archive/ ### 🎯 よく使う情報 -- **[構文早見表](docs/quick-reference/syntax-cheatsheet.md)** - 基本構文・よくある間違い -- **[演算子一覧](docs/quick-reference/operators-summary.md)** - 実装済み演算子 -- **[開発コマンド](docs/quick-reference/development-commands.md)** - build/test/AI相談 - +- Getting Started: docs/説明書/GETTING_STARTED.md +- Language Guide: docs/説明書/LANGUAGE_GUIDE.md +- Playground Guide: docs/説明書/guides/playground_guide.md ### 📊 最新開発状況 -- **[実装状況](docs/status/current-implementation.md)** - 完全な機能実装状況 -- **[最新成果](docs/status/recent-achievements.md)** - 2025-08-08更新 -- **[既知の問題](docs/status/known-issues.md)** - 制限事項・回避策 - +- 現在のタスク: docs/CURRENT_TASK.md +- 予定インデックス: docs/予定/README.md ### 📖 詳細リファレンス -- **[完全リファレンス](docs/reference/)** - 言語仕様詳細 - - [予約語一覧](docs/reference/keywords.md) - - [演算子リファレンス](docs/reference/operators.md) - - [ビルトイン型](docs/reference/built-in-boxes.md) - - [MethodBox(invoke)](docs/reference/method-box-reference.md) - - [ジェネリクス](docs/reference/generics-reference.md) -- **[学習ガイド](docs/language-guide/)** - 体系的学習用 - +- リファレンス: docs/説明書/reference/ + - 言語: docs/説明書/reference/language-reference.md + - デリゲーション構文: docs/説明書/reference/override-delegation-syntax.md + - ビルトイン: docs/説明書/reference/builtin-boxes.md + - fini/弱参照: docs/説明書/reference/finalization-system.md ### 🎮 実用例・アプリ -- **[実用例](docs/examples/)** - サンプルコード・パターン集 +- **[実用例](docs/説明書/guides/)** - サンプルコード・パターン集 - **実装済みアプリ**: サイコロRPG・統計計算・LISPインタープリター ## ⚡ 重要な設計原則 @@ -208,12 +213,12 @@ app.setSize(800, 600) #### 🔤 言語仕様 - **[構文早見表](docs/quick-reference/syntax-cheatsheet.md)** - 基本構文・よくある間違い -- **[完全リファレンス](docs/reference/)** - 言語仕様詳細 -- **[予約語一覧](docs/reference/keywords.md)** - from, override, pack等 +- **[完全リファレンス](docs/説明書/reference/)** - 言語仕様詳細 +- **[予約語一覧](docs/説明書/reference/keywords.md)** - from, override, pack等 #### 📦 主要BOXのAPI -- **[ビルトイン型](docs/reference/built-in-boxes.md)** - 全Box型API仕様 -- **P2PBox & IntentBox** - docs/reference/built-in-boxes.md内 +- **[ビルトイン型](docs/説明書/reference/built-in-boxes.md)** - 全Box型API仕様 +- **P2PBox & IntentBox** - docs/説明書/reference/built-in-boxes.md内 - **StringBox, IntegerBox, ConsoleBox** - 基本Box API - **EguiBox, DebugBox, MathBox** - 特殊Box API @@ -223,7 +228,7 @@ app.setSize(800, 600) Read src/boxes/p2p_box.rs # 直接ソース参照 # ✅ 良い例:ドキュメント優先 -Read docs/reference/built-in-boxes.md # まずドキュメント +Read docs/説明書/reference/built-in-boxes.md # まずドキュメント # → 古い/不足 → ドキュメント更新 # → それでも不明 → ソース確認 ``` @@ -351,4 +356,4 @@ docs/ - **Box哲学具現化**: 「箱に詰める」直感的メタファーでコードを書くたび哲学体験 - **完全実装**: `pack()`、`from Parent.pack()`、`pack`>`init`>Box名順優先選択 - **革命的UX**: 他言語の`new`/`init`を超越、Nyash独自アイデンティティ確立 -- **デリゲーション完成**: `box Child from Parent`+`pack`+`override`+`from`統合完了 \ No newline at end of file +- **デリゲーション完成**: `box Child from Parent`+`pack`+`override`+`from`統合完了 diff --git a/CURRENT_TASK.md b/docs/CURRENT_TASK.md similarity index 100% rename from CURRENT_TASK.md rename to docs/CURRENT_TASK.md diff --git a/docs/README.md b/docs/README.md index fb3b13e2..29d1e4b8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,97 +1,38 @@ # 📚 Nyash Documentation -**NyashプログラミングLexicalAnalyzer言語の公式ドキュメント** | 最終更新: 2025-08-12 +最初に確認: +- 現在のタスク: docs/CURRENT_TASK.md +- コア概念の速習: docs/nyash_core_concepts.md --- -## 🚀 すぐ始める - -### 👶 **初心者向け** -- **[Getting Started](GETTING_STARTED.md)** - 環境構築から最初のプログラムまで - -### 📖 **言語を学ぶ** -- **[Language Guide](LANGUAGE_GUIDE.md)** - 言語仕様・構文・完全ガイド - -### 🌐 **P2P通信** -- **[P2P Guide](P2P_GUIDE.md)** - P2P通信システム完全ガイド +## 構成(最小3系) +- 説明書: docs/説明書/README.md + - ネイティブビルド: docs/説明書/native-build/README.md + - WASM: docs/説明書/wasm/ + - 入門/言語ガイド/P2P/リファレンス: docs/説明書/*, docs/説明書/reference/* +- 予定: docs/予定/README.md + - CURRENT_TASK, ネイティブ計画、フェーズ課題 +- archive: docs/archive/ + - 旧資料・議事録・試験メモ --- -## 📋 詳細リファレンス - -### **[reference/](reference/)** -- **[language-reference.md](reference/language-reference.md)** - 言語仕様完全リファレンス -- **[override-delegation-syntax.md](reference/override-delegation-syntax.md)** - デリゲーション・override構文仕様 -- **[design-philosophy.md](reference/design-philosophy.md)** - 明示的デリゲーション革命の設計思想 -- **[builtin-boxes.md](reference/builtin-boxes.md)** - ビルトインBox型詳細リファレンス +## すぐ始める +- Getting Started: docs/説明書/GETTING_STARTED.md +- Language Guide: docs/説明書/LANGUAGE_GUIDE.md +- P2P Guide: docs/説明書/P2P_GUIDE.md --- -## 🗄️ 過去資料・開発履歴 - -### **[archive/](archive/)** -- **[development/](archive/development/)** - 過去のドキュメント・開発履歴 -- **[p2p/](archive/p2p/)** - P2P詳細設計書・AI相談記録 +## 参考資料(Reference) +- 言語リファレンス: docs/説明書/reference/language-reference.md +- デリゲーション構文: docs/説明書/reference/override-delegation-syntax.md +- 設計思想: docs/説明書/reference/design-philosophy.md +- ビルトイン一覧: docs/説明書/reference/builtin-boxes.md +- P2P仕様: docs/説明書/reference/p2p_spec.md +- 詳細仕様フォルダ: docs/説明書/reference/language-specification/ --- -## 🎯 Nyashとは - -**「Everything is Box」哲学**に基づく革新的プログラミング言語 - -```nyash -// シンプルで強力な構文 -local greeting = "Hello, Nyash!" -print(greeting) - -// すべてがBox - 統一された美しい世界 -local numbers = new ArrayBox() -numbers.push(42) -numbers.push(3.14) - -// P2P通信もBox! -local node = new P2PBox("alice", transport: "inprocess") -node.send("bob", new IntentBox("chat", { text: "Hello P2P!" })) -``` - -### ✨ **主な特徴** -- **🔧 Production Ready**: Phase 1完了、実用レベルの言語機能 -- **🌐 P2P Native**: P2P通信がビルトイン (Phase 2実装中) -- **🛡️ Memory Safe**: Rust実装による完全メモリ安全性 -- **📦 Everything is Box**: 統一されたオブジェクトモデル -- **⚡ Simple & Powerful**: 学習コストが低く、表現力が高い - -### 📊 **実装状況 (2025-08-12)** - -#### ✅ **Phase 1完了** -- FloatBox, ArrayBox改良, Cross-type演算子 -- 包括的テストスイート (188行) -- デリゲーション革命 (`from`構文完成) - -#### 🚧 **Phase 2実装中** -- IntentBox (構造化メッセージ) -- P2PBox (P2P通信ノード) -- MessageBus (プロセス内シングルトン) - -#### 🎯 **最終目標** -**NyaMeshP2Pライブラリ実現** - Nyash言語による本格的P2P通信ライブラリ - ---- - -## 🤝 コミュニティ - -### 開発方針 -- **ドキュメントファースト**: ソースより先にドキュメント確認 -- **AI協働開発**: Gemini先生・ChatGPT先生・Copilot連携 -- **段階的実装**: Phase 1→2→3の確実な進歩 - -### 貢献方法 -1. **Issue報告**: バグ・要望をGitHub Issuesで報告 -2. **ドキュメント改善**: typo修正・内容追加のPull Request歓迎 -3. **コード貢献**: 新機能実装・バグ修正のPull Request歓迎 - ---- - -**🎉 Welcome to the world of "Everything is Box"!** - -*Nyashで新しいプログラミングの世界を体験しよう!* \ No newline at end of file +Nyash は「Everything is Box」哲学に基づく言語です。詳細はコア概念とガイドを参照してください。 diff --git a/docs/GETTING_STARTED.md b/docs/archive/GETTING_STARTED.md similarity index 100% rename from docs/GETTING_STARTED.md rename to docs/archive/GETTING_STARTED.md diff --git a/docs/LANGUAGE_OVERVIEW_2025.md b/docs/archive/LANGUAGE_OVERVIEW_2025.md similarity index 100% rename from docs/LANGUAGE_OVERVIEW_2025.md rename to docs/archive/LANGUAGE_OVERVIEW_2025.md diff --git a/MAPBOX_HANG_BUG_REPORT.md b/docs/archive/MAPBOX_HANG_BUG_REPORT.md similarity index 100% rename from MAPBOX_HANG_BUG_REPORT.md rename to docs/archive/MAPBOX_HANG_BUG_REPORT.md diff --git a/P2P_IMPLEMENTATION_ISSUE.md b/docs/archive/P2P_IMPLEMENTATION_ISSUE.md similarity index 100% rename from P2P_IMPLEMENTATION_ISSUE.md rename to docs/archive/P2P_IMPLEMENTATION_ISSUE.md diff --git a/README.ja.md b/docs/archive/README.ja.md similarity index 100% rename from README.ja.md rename to docs/archive/README.ja.md diff --git a/docs/archive/README.md b/docs/archive/README.md new file mode 100644 index 00000000..fb3b13e2 --- /dev/null +++ b/docs/archive/README.md @@ -0,0 +1,97 @@ +# 📚 Nyash Documentation + +**NyashプログラミングLexicalAnalyzer言語の公式ドキュメント** | 最終更新: 2025-08-12 + +--- + +## 🚀 すぐ始める + +### 👶 **初心者向け** +- **[Getting Started](GETTING_STARTED.md)** - 環境構築から最初のプログラムまで + +### 📖 **言語を学ぶ** +- **[Language Guide](LANGUAGE_GUIDE.md)** - 言語仕様・構文・完全ガイド + +### 🌐 **P2P通信** +- **[P2P Guide](P2P_GUIDE.md)** - P2P通信システム完全ガイド + +--- + +## 📋 詳細リファレンス + +### **[reference/](reference/)** +- **[language-reference.md](reference/language-reference.md)** - 言語仕様完全リファレンス +- **[override-delegation-syntax.md](reference/override-delegation-syntax.md)** - デリゲーション・override構文仕様 +- **[design-philosophy.md](reference/design-philosophy.md)** - 明示的デリゲーション革命の設計思想 +- **[builtin-boxes.md](reference/builtin-boxes.md)** - ビルトインBox型詳細リファレンス + +--- + +## 🗄️ 過去資料・開発履歴 + +### **[archive/](archive/)** +- **[development/](archive/development/)** - 過去のドキュメント・開発履歴 +- **[p2p/](archive/p2p/)** - P2P詳細設計書・AI相談記録 + +--- + +## 🎯 Nyashとは + +**「Everything is Box」哲学**に基づく革新的プログラミング言語 + +```nyash +// シンプルで強力な構文 +local greeting = "Hello, Nyash!" +print(greeting) + +// すべてがBox - 統一された美しい世界 +local numbers = new ArrayBox() +numbers.push(42) +numbers.push(3.14) + +// P2P通信もBox! +local node = new P2PBox("alice", transport: "inprocess") +node.send("bob", new IntentBox("chat", { text: "Hello P2P!" })) +``` + +### ✨ **主な特徴** +- **🔧 Production Ready**: Phase 1完了、実用レベルの言語機能 +- **🌐 P2P Native**: P2P通信がビルトイン (Phase 2実装中) +- **🛡️ Memory Safe**: Rust実装による完全メモリ安全性 +- **📦 Everything is Box**: 統一されたオブジェクトモデル +- **⚡ Simple & Powerful**: 学習コストが低く、表現力が高い + +### 📊 **実装状況 (2025-08-12)** + +#### ✅ **Phase 1完了** +- FloatBox, ArrayBox改良, Cross-type演算子 +- 包括的テストスイート (188行) +- デリゲーション革命 (`from`構文完成) + +#### 🚧 **Phase 2実装中** +- IntentBox (構造化メッセージ) +- P2PBox (P2P通信ノード) +- MessageBus (プロセス内シングルトン) + +#### 🎯 **最終目標** +**NyaMeshP2Pライブラリ実現** - Nyash言語による本格的P2P通信ライブラリ + +--- + +## 🤝 コミュニティ + +### 開発方針 +- **ドキュメントファースト**: ソースより先にドキュメント確認 +- **AI協働開発**: Gemini先生・ChatGPT先生・Copilot連携 +- **段階的実装**: Phase 1→2→3の確実な進歩 + +### 貢献方法 +1. **Issue報告**: バグ・要望をGitHub Issuesで報告 +2. **ドキュメント改善**: typo修正・内容追加のPull Request歓迎 +3. **コード貢献**: 新機能実装・バグ修正のPull Request歓迎 + +--- + +**🎉 Welcome to the world of "Everything is Box"!** + +*Nyashで新しいプログラミングの世界を体験しよう!* \ No newline at end of file diff --git a/ai_conference_overload_decision.md b/docs/archive/ai_conference_overload_decision.md similarity index 100% rename from ai_conference_overload_decision.md rename to docs/archive/ai_conference_overload_decision.md diff --git a/docs/archive/build_error.txt b/docs/archive/build_error.txt new file mode 100644 index 00000000..d855f255 --- /dev/null +++ b/docs/archive/build_error.txt @@ -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の実装自体は完全に動作しています。 \ No newline at end of file diff --git a/docs/archive/build_errors.txt b/docs/archive/build_errors.txt new file mode 100644 index 00000000..63881e84 --- /dev/null +++ b/docs/archive/build_errors.txt @@ -0,0 +1,328 @@ +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/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_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_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/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/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_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/debug_notepad.rs` found to be present in multiple build targets: + * `bin` target `debug_notepad` + * `example` target `debug_notepad` + Checking nyash-rust v0.1.0 (/mnt/c/git/nyash-project/nyash) +warning: unused import: `Display` + --> src/boxes/buffer/mod.rs:35:23 + | +35 | use std::fmt::{Debug, Display}; + | ^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +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 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: `std::sync::Arc` + --> src/interpreter/objects.rs:13:5 + | +13 | 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: `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; + | ^^^^^^^^^^^^^^ + +error[E0592]: duplicate definitions with name `execute_parent_constructor` + --> src/interpreter/expressions.rs:816:5 + | +816 | / fn execute_parent_constructor(&mut self, parent: &str, parent_box_decl: &super::BoxDeclaration, +817 | | current_instance: Box, arguments: &[ASTNode]) +818 | | -> Result, RuntimeError> { + | |__________________________________________________^ duplicate definitions for `execute_parent_constructor` + | + ::: src/interpreter/objects.rs:789:5 + | +789 | / pub(super) fn execute_parent_constructor(&mut self, parent_class: &str, arguments: &[ASTNode]) +790 | | -> Result, RuntimeError> { + | |__________________________________________________- other definition for `execute_parent_constructor` + +error[E0308]: mismatched types + --> src/interpreter/expressions.rs:732:77 + | +732 | let is_valid_delegation = current_box_decl.extends.as_ref() == Some(parent) || + | ---- ^^^^^^ expected `&String`, found `&str` + | | + | arguments to this enum variant are incorrect + | + = note: expected reference `&std::string::String` + found reference `&str` +help: the type constructed contains `&str` due to the type of the argument passed + --> src/interpreter/expressions.rs:732:72 + | +732 | let is_valid_delegation = current_box_decl.extends.as_ref() == Some(parent) || + | ^^^^^------^ + | | + | this argument influences the type of `Some` +note: tuple variant defined here + --> /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/core/src/option.rs:597:5 + +error[E0034]: multiple applicable items in scope + --> src/interpreter/expressions.rs:753:25 + | +753 | return self.execute_parent_constructor(parent, &parent_box_decl, current_instance_val.clone_box(), arguments); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `execute_parent_constructor` found + | +note: candidate #1 is defined in an impl for the type `core::NyashInterpreter` + --> src/interpreter/expressions.rs:816:5 + | +816 | / fn execute_parent_constructor(&mut self, parent: &str, parent_box_decl: &super::BoxDeclaration, +817 | | current_instance: Box, arguments: &[ASTNode]) +818 | | -> Result, RuntimeError> { + | |__________________________________________________^ +note: candidate #2 is defined in an impl for the type `core::NyashInterpreter` + --> src/interpreter/objects.rs:789:5 + | +789 | / pub(super) fn execute_parent_constructor(&mut self, parent_class: &str, arguments: &[ASTNode]) +790 | | -> Result, RuntimeError> { + | |__________________________________________________^ + +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:29:28 + | +29 | pub fn http_get(&self, url: Box) -> Box { + | ^^^ 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:34:24 + | +34 | pub fn post(&self, url: Box, body: Box) -> Box { + | ^^^ help: if this is intentional, prefix it with an underscore: `_url` + +warning: unused variable: `body` + --> src/boxes/http/mod.rs:34:48 + | +34 | pub fn post(&self, url: Box, body: Box) -> Box { + | ^^^^ help: if this is intentional, prefix it with an underscore: `_body` + +warning: unused variable: `url` + --> src/boxes/http/mod.rs:39:23 + | +39 | pub fn put(&self, url: Box, body: Box) -> Box { + | ^^^ help: if this is intentional, prefix it with an underscore: `_url` + +warning: unused variable: `body` + --> src/boxes/http/mod.rs:39:47 + | +39 | pub fn put(&self, url: Box, body: Box) -> Box { + | ^^^^ help: if this is intentional, prefix it with an underscore: `_body` + +warning: unused variable: `url` + --> src/boxes/http/mod.rs:44:26 + | +44 | pub fn delete(&self, url: Box) -> Box { + | ^^^ help: if this is intentional, prefix it with an underscore: `_url` + +warning: unused variable: `method` + --> src/boxes/http/mod.rs:49:27 + | +49 | pub fn request(&self, method: Box, url: Box, options: Box) -> Box { + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_method` + +warning: unused variable: `url` + --> src/boxes/http/mod.rs:49:54 + | +49 | pub fn request(&self, method: Box, url: Box, options: Box) -> Box { + | ^^^ help: if this is intentional, prefix it with an underscore: `_url` + +warning: unused variable: `options` + --> src/boxes/http/mod.rs:49:78 + | +49 | pub fn request(&self, method: Box, url: Box, options: Box) -> Box { + | ^^^^^^^ 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:65:35 + | +65 | 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:537:22 + | +537 | 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:862:21 + | +862 | let mut result: Box = Box::new(VoidBox::new()); + | ^^^^^^ + | + = note: consider using `_result` instead + +warning: value assigned to `result` is never read + --> src/interpreter/expressions.rs:864:17 + | +864 | 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:868:21 + | +868 | result = return_val.clone_box(); + | ^^^^^^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `existing_method` + --> src/instance.rs:95:21 + | +95 | if let Some(existing_method) = new_methods.get(&method_name) { + | ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_existing_method` + +Some errors have detailed explanations: E0034, E0308, E0592. +For more information about an error, try `rustc --explain E0034`. +warning: `nyash-rust` (lib) generated 38 warnings +error: could not compile `nyash-rust` (lib) due to 3 previous errors; 38 warnings emitted diff --git a/docs/archive/build_log.txt b/docs/archive/build_log.txt new file mode 100644 index 00000000..e69de29b diff --git a/docs/archive/build_output.txt b/docs/archive/build_output.txt new file mode 100644 index 00000000..e69de29b diff --git a/docs/chatgpt5/インタープリタ評価.txt b/docs/archive/chatgpt5/インタープリタ評価.txt similarity index 100% rename from docs/chatgpt5/インタープリタ評価.txt rename to docs/archive/chatgpt5/インタープリタ評価.txt diff --git a/docs/chatgpt5/プレイグラウンド_ガイド.md b/docs/archive/chatgpt5/プレイグラウンド_ガイド.md similarity index 100% rename from docs/chatgpt5/プレイグラウンド_ガイド.md rename to docs/archive/chatgpt5/プレイグラウンド_ガイド.md diff --git a/docs/chatgpt5/プレイグラウンド_サンプル.md b/docs/archive/chatgpt5/プレイグラウンド_サンプル.md similarity index 100% rename from docs/chatgpt5/プレイグラウンド_サンプル.md rename to docs/archive/chatgpt5/プレイグラウンド_サンプル.md diff --git a/docs/chatgpt5/実装TODO_解放とガード.txt b/docs/archive/chatgpt5/実装TODO_解放とガード.txt similarity index 100% rename from docs/chatgpt5/実装TODO_解放とガード.txt rename to docs/archive/chatgpt5/実装TODO_解放とガード.txt diff --git a/docs/chatgpt5/実装計画_fini統合.txt b/docs/archive/chatgpt5/実装計画_fini統合.txt similarity index 100% rename from docs/chatgpt5/実装計画_fini統合.txt rename to docs/archive/chatgpt5/実装計画_fini統合.txt diff --git a/docs/chatgpt5/解放ポリシー_fini.txt b/docs/archive/chatgpt5/解放ポリシー_fini.txt similarity index 100% rename from docs/chatgpt5/解放ポリシー_fini.txt rename to docs/archive/chatgpt5/解放ポリシー_fini.txt diff --git a/docs/chatgpt5/解放ポリシー_エラーと診断.txt b/docs/archive/chatgpt5/解放ポリシー_エラーと診断.txt similarity index 100% rename from docs/chatgpt5/解放ポリシー_エラーと診断.txt rename to docs/archive/chatgpt5/解放ポリシー_エラーと診断.txt diff --git a/docs/chatgpt5/解放ポリシー_例.txt b/docs/archive/chatgpt5/解放ポリシー_例.txt similarity index 100% rename from docs/chatgpt5/解放ポリシー_例.txt rename to docs/archive/chatgpt5/解放ポリシー_例.txt diff --git a/docs/chatgpt5/設計RFC_多重デリゲーションとfini.txt b/docs/archive/chatgpt5/設計RFC_多重デリゲーションとfini.txt similarity index 100% rename from docs/chatgpt5/設計RFC_多重デリゲーションとfini.txt rename to docs/archive/chatgpt5/設計RFC_多重デリゲーションとfini.txt diff --git a/docs/chatgpt5/論文_サマリ.md b/docs/archive/chatgpt5/論文_サマリ.md similarity index 100% rename from docs/chatgpt5/論文_サマリ.md rename to docs/archive/chatgpt5/論文_サマリ.md diff --git a/docs/chatgpt5/論文_プロダクト寄りドラフト.md b/docs/archive/chatgpt5/論文_プロダクト寄りドラフト.md similarity index 100% rename from docs/chatgpt5/論文_プロダクト寄りドラフト.md rename to docs/archive/chatgpt5/論文_プロダクト寄りドラフト.md diff --git a/docs/design-philosophy/explicit-delegation-revolution.md b/docs/archive/design-philosophy/explicit-delegation-revolution.md similarity index 100% rename from docs/design-philosophy/explicit-delegation-revolution.md rename to docs/archive/design-philosophy/explicit-delegation-revolution.md diff --git a/DELEGATION_DESIGN_SUMMARY.md b/docs/archive/design/DELEGATION_DESIGN_SUMMARY.md similarity index 100% rename from DELEGATION_DESIGN_SUMMARY.md rename to docs/archive/design/DELEGATION_DESIGN_SUMMARY.md diff --git a/NYASHFLOW_PROJECT_HANDOVER.md b/docs/archive/design/NYASHFLOW_PROJECT_HANDOVER.md similarity index 100% rename from NYASHFLOW_PROJECT_HANDOVER.md rename to docs/archive/design/NYASHFLOW_PROJECT_HANDOVER.md diff --git a/PHILOSOPHY.md b/docs/archive/design/PHILOSOPHY.md similarity index 100% rename from PHILOSOPHY.md rename to docs/archive/design/PHILOSOPHY.md diff --git a/docs/archive/design/decisions/ai_conference_overload_decision.md b/docs/archive/design/decisions/ai_conference_overload_decision.md new file mode 100644 index 00000000..b0dcc47f --- /dev/null +++ b/docs/archive/design/decisions/ai_conference_overload_decision.md @@ -0,0 +1,103 @@ +# 🎊 AI大会議決定: 関数オーバーロード不採用 + ブロードキャスト除外 + +**日時**: 2025-08-12 +**参加**: Gemini先生・ChatGPT先生 +**議題**: Nyash P2PBox における関数オーバーロード採用可否 + +--- + +## 🏆 **最終決定** + +### ❌ **関数オーバーロード不採用** +- `send(a)` `send(a,b)` のような引数数による分岐は実装しない +- 理由: Nyashの「明示性重視」哲学と矛盾、初学者混乱、実装複雑化 + +### ❌ **ブロードキャスト機能除外** +- `broadcast(message)` 機能は実装しない +- 理由: ネットワーク負荷・セキュリティリスク・初学者誤用防止 + +--- + +## 🎯 **確定API仕様** + +### ✅ **最終P2PBox API** (ブロードキャスト除外版) +```nyash +// 基本の個別送信(必須) +node.send("bob", message) + +// オプション付き個別送信(将来実装) +node.send_with_options("bob", message, opts) +``` + +### **使用例** +```nyash +// 基本使用 +local node_a = new P2PBox("alice", transport: "inprocess") +local node_b = new P2PBox("bob", transport: "inprocess") + +// 受信ハンドラ +node_b.on("chat.message", function(intent, from) { + print("From " + from + ": " + intent.payload.text) +}) + +// 個別送信のみ +local msg = new IntentBox("chat.message", { text: "Hello P2P!" }) +node_a.send("bob", msg) // ✅ 個別送信 +// node_a.broadcast(msg) // ❌ ブロードキャストは存在しない +``` + +--- + +## 🎓 **AI両先生の見解** + +### **Gemini先生** +- **結論**: オーバーロード不採用 +- **理由**: 「明示性は最高の利便性」、初学者混乱防止 +- **推奨**: 明示的メソッド名分離 + +### **ChatGPT先生** +- **結論**: オーバーロード不採用 +- **理由**: 技術実装複雑化、Arcとの不整合 +- **推奨**: Rust単一backend + 明示的API + +### **ブロードキャスト除外理由** (実戦経験に基づく重要判断) + +**🚨 実体験による重要な教訓:** +- **C++ nyameshでの悪夢**: AIが無意識にブロードキャストを使用 +- **無限ループ地獄**: sendデータがばらまかれ、反射して無限ループ発生 +- **何度も経験**: この問題を繰り返し体験した深刻な実害 + +**📋 技術的除外理由:** +1. **無限ループリスク**: ブロードキャストデータの反射による暴走 +2. **P2P本質**: P2P通信は本来1対1が基本、ブロードキャスト不要 +3. **後付け可能**: 必要になったら最後に安全に追加可能 +4. **初学者保護**: 危険な機能による事故防止 +5. **AIセーフティ**: AI使用時の予期しない暴走防止 + +--- + +## 🌟 **この決定の価値** + +### **Nyashアイデンティティ確立** +- **明示性重視**: 何が起こるかが明確 +- **初学者ファースト**: 混乱のない学習体験 +- **安全性優先**: 危険な機能は除外 +- **シンプル美**: 必要十分な機能のみ + +### **技術的優位性** +- **実装シンプル**: 保守しやすいコード +- **Rust整合性**: 言語実装との自然な統合 +- **Arc最適化**: 統一アーキテクチャとの親和性 +- **現代的設計**: Go・Rustと同じ先進路線 + +--- + +## 🚀 **次のアクション** + +1. **P2P_GUIDE.md確認**: ブロードキャスト言及の除去確認 +2. **LANGUAGE_GUIDE.md更新**: AI大会議結果反映 +3. **P2PBox実装開始**: 確定仕様でIntentBox実装開始 + +--- + +**🎉 「便利な悪魔の誘惑を退け、真の明示性を選択」 - Nyashの哲学勝利!** \ No newline at end of file diff --git a/docs/archive/design/decisions/ai_consultation_constructor_design_question.txt b/docs/archive/design/decisions/ai_consultation_constructor_design_question.txt new file mode 100644 index 00000000..f5553f2f --- /dev/null +++ b/docs/archive/design/decisions/ai_consultation_constructor_design_question.txt @@ -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. 言語の美しさ・一貫性の観点からの評価は? + +プログラミング言語設計の専門的視点から、深く分析してください。 \ No newline at end of file diff --git a/docs/archive/design/decisions/ai_consultation_override_design_question.txt b/docs/archive/design/decisions/ai_consultation_override_design_question.txt new file mode 100644 index 00000000..17306bd8 --- /dev/null +++ b/docs/archive/design/decisions/ai_consultation_override_design_question.txt @@ -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の目指す「明示的で安全、かつ初学者フレンドリーな言語」に最適かどうか深く分析してください。 \ No newline at end of file diff --git a/docs/sessions/architecture_consultation.txt b/docs/archive/design/decisions/architecture_consultation.txt similarity index 100% rename from docs/sessions/architecture_consultation.txt rename to docs/archive/design/decisions/architecture_consultation.txt diff --git a/docs/archive/design/decisions/chatgpt5_consultation_weak_architecture_decision.txt b/docs/archive/design/decisions/chatgpt5_consultation_weak_architecture_decision.txt new file mode 100644 index 00000000..d4a4ce09 --- /dev/null +++ b/docs/archive/design/decisions/chatgpt5_consultation_weak_architecture_decision.txt @@ -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>>>>, +} + +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>>, // Simple ID set +} + +fn trigger_weak_reference_invalidation(&mut self, target_info: &str) { + if let Ok(id) = target_info.parse::() { + 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! \ No newline at end of file diff --git a/docs/sessions/chatgpt_consultation_overload.txt b/docs/archive/design/decisions/chatgpt_consultation_overload.txt similarity index 100% rename from docs/sessions/chatgpt_consultation_overload.txt rename to docs/archive/design/decisions/chatgpt_consultation_overload.txt diff --git a/docs/sessions/gemini_consultation_overload.txt b/docs/archive/design/decisions/gemini_consultation_overload.txt similarity index 100% rename from docs/sessions/gemini_consultation_overload.txt rename to docs/archive/design/decisions/gemini_consultation_overload.txt diff --git a/docs/archive/design/decisions/gemini_consultation_weak_final_implementation.txt b/docs/archive/design/decisions/gemini_consultation_weak_final_implementation.txt new file mode 100644 index 00000000..6c4a8fc2 --- /dev/null +++ b/docs/archive/design/decisions/gemini_consultation_weak_final_implementation.txt @@ -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>>>>, +} + +impl SharedState { + fn register_instance(&mut self, instance: Weak>) { ... } + 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%を効率的に完成させる方法をお願いします。 \ No newline at end of file diff --git a/docs/archive/design/decisions/weak_reference_architecture_consultation.txt b/docs/archive/design/decisions/weak_reference_architecture_consultation.txt new file mode 100644 index 00000000..44babdf8 --- /dev/null +++ b/docs/archive/design/decisions/weak_reference_architecture_consultation.txt @@ -0,0 +1,40 @@ +Nyash言語のweak参照実装で根本的な設計問題が発覚しました。専門的分析をお願いします。 + +【現在の問題】 +InstanceBox構造が原因でweak参照が実装できません: + +```rust +pub struct InstanceBox { + pub fields: Arc>>>, // 問題の核心 +} +``` + +NyashValue::WeakBoxを作っても、Boxにしか格納できず、弱参照情報が失われます。 + +【解決策の選択肢】 + +1. **根本解決**(理想だが影響大) +```rust +pub fields: Arc>>, // 全面アーキテクチャ変更 +``` + +2. **暫定解決**(copilot提案) +```rust +pub struct InstanceBox { + pub fields: Arc>>>, // 既存維持 + pub weak_fields: Arc>>>>, // 追加 +} +``` + +【コンテキスト】 +- NyashValue革命は完了済み(Arc過剰症候群解決) +- Everything is Box哲学必須 +- 実用性重視(完璧より動くもの優先) + +【質問】 +1. 暫定解決策の技術的妥当性は? +2. パフォーマンス・保守性への影響は? +3. 根本解決は本当に必要か? +4. 段階的移行戦略の是非は? + +実装可能性と設計の美しさのバランスを重視した分析をお願いします。 \ No newline at end of file diff --git a/docs/archive/design/decisions/インタープリタ評価.txt b/docs/archive/design/decisions/インタープリタ評価.txt new file mode 100644 index 00000000..2254fbfb --- /dev/null +++ b/docs/archive/design/decisions/インタープリタ評価.txt @@ -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>/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を段階的に整備するのが最も効果的。 + diff --git a/docs/archive/design/decisions/プレイグラウンド_サンプル.md b/docs/archive/design/decisions/プレイグラウンド_サンプル.md new file mode 100644 index 00000000..b9487795 --- /dev/null +++ b/docs/archive/design/decisions/プレイグラウンド_サンプル.md @@ -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) +``` + diff --git a/docs/archive/design/decisions/実装TODO_解放とガード.txt b/docs/archive/design/decisions/実装TODO_解放とガード.txt new file mode 100644 index 00000000..327ea013 --- /dev/null +++ b/docs/archive/design/decisions/実装TODO_解放とガード.txt @@ -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 へ最終ルール・エラーメッセージ・サンプルを移植。 + diff --git a/docs/archive/design/decisions/実装計画_fini統合.txt b/docs/archive/design/decisions/実装計画_fini統合.txt new file mode 100644 index 00000000..5b4aff7f --- /dev/null +++ b/docs/archive/design/decisions/実装計画_fini統合.txt @@ -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 + Purpose: deterministic auto-cascade order (includes inherited fields). + - weak_fields_union: std::collections::HashSet + 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, methods: HashMap, + weak_fields_union: HashSet) + 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 + - 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 '' (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..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. + diff --git a/docs/archive/design/decisions/解放ポリシー_fini.txt b/docs/archive/design/decisions/解放ポリシー_fini.txt new file mode 100644 index 00000000..a666f773 --- /dev/null +++ b/docs/archive/design/decisions/解放ポリシー_fini.txt @@ -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..fini()` のような直接の fini 呼び出しを禁止する。 +- 推奨診断レベル: ビルド(解析)時エラー。 + - 推奨エラーメッセージ: "Cannot finalize weak field '' (non-owning reference). Use null assignment or let it lazily nilify." +- 実装補足: 静的解析で `fini()` 本体内のフィールド呼び出しを走査し、対象が weak に該当すればエラー。検出困難な動的経路は実行時にもエラーを返す。 +- 推奨代替手段: `me. = 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 後は使用禁止をガードで強制、誤用を早期検知。 diff --git a/docs/archive/design/decisions/解放ポリシー_エラーと診断.txt b/docs/archive/design/decisions/解放ポリシー_エラーと診断.txt new file mode 100644 index 00000000..fa9d881d --- /dev/null +++ b/docs/archive/design/decisions/解放ポリシー_エラーと診断.txt @@ -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 '' (non-owning reference)." +Message (runtime fallback): + "Finalization of non-owning (weak) reference is not allowed: ''" +When: `init { weak }` で宣言されたフィールドに対して `fini()` を直接呼んだ場合。 +Fix: `me. = 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`(将来案)を付与したフィールドは自動カスケード対象から除外。 + diff --git a/docs/archive/design/decisions/解放ポリシー_例.txt b/docs/archive/design/decisions/解放ポリシー_例.txt new file mode 100644 index 00000000..2fdb3ec3 --- /dev/null +++ b/docs/archive/design/decisions/解放ポリシー_例.txt @@ -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 + diff --git a/docs/archive/design/decisions/設計RFC_多重デリゲーションとfini.txt b/docs/archive/design/decisions/設計RFC_多重デリゲーションとfini.txt new file mode 100644 index 00000000..89fe5034 --- /dev/null +++ b/docs/archive/design/decisions/設計RFC_多重デリゲーションとfini.txt @@ -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 '' (non-owning reference). Set it to null or rely on lazy nilification." + +備考(質問への回答) +- 「共有参照が残っていても解放が正しいか?」→ はい。言語意味論では“以後使用禁止”を宣言するのが `fini()` で、 + 物理メモリが残るかどうかはランタイムの参照カウントに依存するだけ。禁止ガードと文書化で期待を一致させる。 + +--- + +3) 追補: 実装/ドキュメント TODO +- interpreter: 候補集合による曖昧検出と診断の実装(メソッド/フィールド)。 +- instance: 再帰的 `fini()` + フィールドクリアの保証、finalized ガードの一元化。 +- docs: LANGUAGE_GUIDE / reference に上記仕様を反映(サンプルと期待エラーメッセージ含む)。 +- playground: メトリクス・エラーの可視化を追加(検証再現性の強化)。 diff --git a/docs/archive/design/decisions/論文_サマリ.md b/docs/archive/design/decisions/論文_サマリ.md new file mode 100644 index 00000000..d7dfb17d --- /dev/null +++ b/docs/archive/design/decisions/論文_サマリ.md @@ -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>`と`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>)`に加え、`WeakBox(Weak>)`、`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/`)を参照。 + diff --git a/docs/archive/design/decisions/論文_プロダクト寄りドラフト.md b/docs/archive/design/decisions/論文_プロダクト寄りドラフト.md new file mode 100644 index 00000000..ba8d6b5b --- /dev/null +++ b/docs/archive/design/decisions/論文_プロダクト寄りドラフト.md @@ -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>)`と`WeakBox(Weak>)`を持ち、弱参照はアクセス時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ページで切替・確認可能。 diff --git a/docs/reference/design-philosophy.md b/docs/archive/design/explicit-delegation-revolution.md similarity index 100% rename from docs/reference/design-philosophy.md rename to docs/archive/design/explicit-delegation-revolution.md diff --git a/docs/lisp_interpreter_design.md b/docs/archive/design/lisp_interpreter_design.md similarity index 100% rename from docs/lisp_interpreter_design.md rename to docs/archive/design/lisp_interpreter_design.md diff --git a/docs/archive/design/technical_architecture.md b/docs/archive/design/technical_architecture.md new file mode 100644 index 00000000..e461031c --- /dev/null +++ b/docs/archive/design/technical_architecture.md @@ -0,0 +1,393 @@ +# 🔧 Nyash Technical Architecture & Implementation Guide + +**最終更新: 2025年8月8日** + +## 📐 アーキテクチャ概要 + +Nyashインタープリターは以下の主要コンポーネントから構成されています: + +``` +┌─────────────────────────────────────────────────────┐ +│ Nyash Runtime │ +├─────────────────────────────────────────────────────┤ +│ Parser │ AST │ Interpreter │ +│ ├─Tokenizer │ ├─ASTNode │ ├─SharedState │ +│ ├─ParseError │ ├─Span │ ├─NyashBox │ +│ └─NyashParser │ └─BoxDecl │ └─RuntimeError │ +├─────────────────────────────────────────────────────┤ +│ Box System │ +│ ├─StringBox ├─IntegerBox ├─BoolBox ├─ArrayBox │ +│ ├─MapBox ├─DebugBox ├─MathBox ├─TimeBox │ +│ ├─RandomBox ├─SoundBox ├─MethodBox└─TypeBox │ +├─────────────────────────────────────────────────────┤ +│ Memory Management │ +│ ├─InstanceBox ├─GlobalBox ├─finalization │ +│ └─reference counting + explicit destructors │ +└─────────────────────────────────────────────────────┘ +``` + +## 🎯 核心設計原則 + +### 1. **Everything is Box** +すべてのデータがNyashBoxトレイトを実装: +```rust +pub trait NyashBox: Any + Send + Sync { + fn to_string_box(&self) -> Box; + fn clone_box(&self) -> Box; + fn as_any(&self) -> &dyn Any; + fn box_id(&self) -> usize; +} +``` + +### 2. **Unified Memory Model** +- **GlobalBox**: 全グローバル変数・関数の統一管理 +- **Local Variables**: 一時的なローカルスコープ +- **SharedState**: 並行処理でのスレッド間共有 + +### 3. **Zero-Copy Philosophy** +- Arc/Rc による効率的な参照共有 +- Clone-on-Write パターンの活用 +- 最小限のメモリコピー + +## 🏗️ 主要コンポーネント + +### **Tokenizer (src/tokenizer.rs)** +```rust +pub enum TokenType { + // 基本トークン + IDENTIFIER(String), STRING(String), INTEGER(i64), FLOAT(f64), + + // 演算子 + PLUS, MINUS, MULTIPLY, DIVIDE, + EQ, NE, LT, GT, LE, GE, + NOT, AND, OR, + + // キーワード + LOCAL, OUTBOX, STATIC, FUNCTION, BOX, + IF, ELSE, LOOP, BREAK, RETURN, + NOWAIT, AWAIT, + + // 区切り文字 + LPAREN, RPAREN, LBRACE, RBRACE, + COMMA, DOT, ASSIGN, +} +``` + +### **AST構造 (src/ast.rs)** +```rust +pub enum ASTNode { + // 変数宣言(初期化対応) + Local { + variables: Vec, + initial_values: Vec>>, // 🚀 2025-08-08実装 + span: Span, + }, + + // Box宣言(static対応) + BoxDeclaration { + name: String, + fields: Vec, + methods: HashMap, + constructors: HashMap, + init_fields: Vec, + is_interface: bool, + extends: Option, + implements: Vec, + type_parameters: Vec, // ジェネリクス + is_static: bool, // 🚀 Static Box + static_init: Option>, + }, + + // 非同期 + Nowait { variable: String, expression: Box }, + + // その他の全ASTノード... +} +``` + +### **Interpreter Core (src/interpreter/mod.rs)** + +#### SharedState - 並行処理アーキテクチャ +```rust +#[derive(Clone)] +pub struct SharedState { + /// 🌍 グローバルBox:すべてのグローバル変数・関数を管理 + pub global_box: Arc>, + + /// 📦 Box宣言:クラス定義情報を管理 + pub box_declarations: Arc>>, + + /// ⚡ Static関数:static box関数を管理 + pub static_functions: Arc>>>, + + /// 📁 インクルード済みファイル:重複読み込み防止 + pub included_files: Arc>>, +} +``` + +#### NyashInterpreter - 実行エンジン +```rust +pub struct NyashInterpreter { + /// 🤝 共有状態:マルチスレッド対応 + pub shared: SharedState, + + /// 📍 ローカル変数:スレッドローカル + pub local_vars: HashMap>, + + /// 📤 outbox変数:所有権移転用 + pub outbox_vars: HashMap>, + + /// 🔄 制御フロー:return/break/throw管理 + pub control_flow: ControlFlow, +} +``` + +## ⚡ 革新的実装詳細 + +### 1. **GlobalBox革命** +従来のEnvironmentスコープチェーンを廃止: + +```rust +// ❌ 従来のスコープチェーン(複雑・低効率) +Environment -> ParentEnvironment -> GlobalEnvironment + +// ✅ GlobalBox統一管理(シンプル・高効率) +local_vars -> GlobalBox (直接2段階解決) +``` + +**効果:** +- メモリ使用量30%削減 +- 変数解決速度向上 +- コード複雑性大幅削減 + +### 2. **Static Box Lazy Initialization** +```rust +impl NyashInterpreter { + pub fn ensure_static_box_initialized(&mut self, name: &str) -> Result<(), RuntimeError> { + // 1. 初期化済みチェック + if self.is_static_box_initialized(name) { return Ok(()); } + + // 2. 循環参照検出 + if self.is_static_box_initializing(name) { + return Err(RuntimeError::CircularDependency(name.to_string())); + } + + // 3. 初期化実行 + self.initialize_static_box(name)?; + Ok(()) + } +} +``` + +**遅延初期化の利点:** +- 効率的なリソース利用 +- 循環参照の安全な検出 +- JavaScript ES Modules準拠の実績あるパターン + +### 3. **並行処理アーキテクチャ** +```rust +pub fn execute_nowait(&mut self, variable: &str, expression: &ASTNode) -> Result, RuntimeError> { + let shared_state = self.shared.clone(); // SharedState複製 + let expr = expression.clone(); // AST複製 + + // 🚀 別スレッドで非同期実行 + let handle = std::thread::spawn(move || { + let mut interpreter = NyashInterpreter::new_with_shared(shared_state); + interpreter.execute_expression(&expr) + }); + + // FutureBoxとして結果を返す + let future_box = FutureBox::new(handle); + self.set_variable(variable, Box::new(future_box))?; + Ok(Box::new(VoidBox::new())) +} +``` + +### 4. **初期化付きlocal宣言実装** +```rust +// AST: 各変数の初期化状態を個別管理 +Local { + variables: vec!["a", "b", "c"], + initial_values: vec![ + Some(Box::new(/* 10 + 20 */)), // a = 30 + None, // b(初期化なし) + Some(Box::new(/* "hello" */)), // c = "hello" + ], +} + +// Interpreter: 効率的な初期化処理 +for (i, var_name) in variables.iter().enumerate() { + if let Some(Some(init_expr)) = initial_values.get(i) { + let init_value = self.execute_expression(init_expr)?; + self.declare_local_variable(var_name, init_value); + } else { + self.declare_local_variable(var_name, Box::new(VoidBox::new())); + } +} +``` + +## 🧪 Box System詳細 + +### **Core Boxes** +```rust +// StringBox: 文字列データ +pub struct StringBox { pub value: String } + +// IntegerBox: 整数データ +pub struct IntegerBox { pub value: i64 } + +// BoolBox: 論理値データ +pub struct BoolBox { pub value: bool } + +// ArrayBox: 動的配列 +pub struct ArrayBox { + elements: RefCell>>, + box_id: usize +} +``` + +### **Advanced Boxes** +```rust +// InstanceBox: ユーザー定義Box +pub struct InstanceBox { + class_name: String, + fields: RefCell>>, + box_id: usize, +} + +// DebugBox: デバッグ・プロファイリング +pub struct DebugBox { + tracked_boxes: RefCell>, + call_stack: RefCell>, + start_time: Instant, +} + +// FutureBox: 非同期結果 +pub struct FutureBox { + handle: Option, RuntimeError>>>, + result: RefCell, RuntimeError>>>, +} +``` + +## 📊 パフォーマンス特性 + +### **メモリ使用量** +| コンポーネント | メモリ効率化手法 | +|---------------|------------------| +| GlobalBox | 単一インスタンス管理 | +| SharedState | Arc/Mutex最小限使用 | +| Local Variables | スコープ終了で自動解放 | +| Static Boxes | 遅延初期化・シングルトン | + +### **実行速度** +``` +ベンチマーク結果(目安): +- 変数解決: ~100ns (GlobalBox直接アクセス) +- メソッド呼び出し: ~500ns (ハッシュマップ検索) +- 並行処理: ~10μs (スレッド作成コスト) +- Box作成: ~200ns (RefCell + allocation) +``` + +### **スケーラビリティ** +- **CPU**: 並行処理によりマルチコア活用 +- **メモリ**: 参照カウントによる効率的管理 +- **I/O**: 非同期処理による非ブロッキング実行 + +## 🔧 開発ツール + +### **デバッグ機能** +```nyash +DEBUG = new DebugBox() +DEBUG.startTracking() # トラッキング開始 +DEBUG.trackBox(obj, "label") # オブジェクト監視 +DEBUG.traceCall("funcName") # 関数呼び出しトレース +print(DEBUG.memoryReport()) # メモリレポート +DEBUG.saveToFile("debug.txt") # ファイル出力 +``` + +### **エラーハンドリング** +```rust +pub enum RuntimeError { + UndefinedVariable { name: String }, + TypeError { message: String }, + DivisionByZero, + CircularDependency(String), + InvalidOperation { message: String }, + FileNotFound { path: String }, +} +``` + +## 🎯 最適化戦略 + +### **コンパイル時最適化** +- 静的解析による未使用コードの検出 +- 定数畳み込み最適化 +- インライン化可能な小関数の特定 + +### **実行時最適化** +- ホット関数の動的最適化 +- JIT コンパイルの準備 +- プロファイル誘導最適化 + +### **メモリ最適化** +- Boxプールによる割り当て最適化 +- 世代別ガベージコレクションの検討 +- Copy-on-Write の積極的活用 + +## 🚀 拡張性設計 + +### **FFI (Foreign Function Interface)** +```rust +// extern boxシステム準備完了 +pub struct ExternBoxDeclaration { + name: String, + native_functions: HashMap]) -> Box>, +} +``` + +### **プラグインシステム** +- Dynamic loading対応準備 +- Box定義の動的追加 +- ランタイム機能拡張 + +### **WebAssembly出力** +```bash +# 🌐 準備完了 +cargo build --target wasm32-unknown-unknown +wasm-bindgen --out-dir web --target web target/wasm32-unknown-unknown/release/nyash.wasm +``` + +## 📈 今後の技術課題 + +### **Short-term (1-2 weeks)** +1. ジェネリクス実行時特殊化完成 +2. スレッドプール実装 +3. WebAssembly バインディング + +### **Mid-term (1-2 months)** +1. JIT コンパイル導入 +2. GUI フレームワーク統合 +3. パッケージマネージャー + +### **Long-term (3-6 months)** +1. Language Server Protocol対応 +2. LLVM バックエンド +3. 分散処理フレームワーク + +## 🎉 技術的達成 + +**2025年8月6日-8日のわずか3日間で達成:** + +- ✅ **30,000+ lines** の実装コード +- ✅ **15+ Box types** の完全実装 +- ✅ **並行処理・非同期** システム完成 +- ✅ **Static Box・名前空間** システム実装 +- ✅ **現代的構文** (初期化付き変数等) 実装 +- ✅ **4つの実用アプリケーション** 完成 +- ✅ **包括的デバッグシステム** 実装 + +**結論: Nyashは実験的プロトタイプから production-ready プログラミング言語へと飛躍的進化を遂げました。** + +--- +*技術仕様書 v1.0* +*Everything is Box - Simple yet Powerful* \ No newline at end of file diff --git a/docs/geminichatgpt相談20250811.txt b/docs/archive/geminichatgpt相談20250811.txt similarity index 100% rename from docs/geminichatgpt相談20250811.txt rename to docs/archive/geminichatgpt相談20250811.txt diff --git a/docs/archive/nativebuild大作戦/README.md b/docs/archive/nativebuild大作戦/README.md new file mode 100644 index 00000000..bca8b98f --- /dev/null +++ b/docs/archive/nativebuild大作戦/README.md @@ -0,0 +1,12 @@ +このフォルダは、旧「ネイティブビルド大作戦」のメモ置き場です。 + +現在は下記パスを正(最新版)としています。 + +- docs/guides/how-to-build-native/README.md +- docs/guides/how-to-build-native/追記相談.txt +- docs/guides/how-to-build-native/issues/ + +注意: +- 以前このフォルダにあった「追記相談.txt」の内容は、上記 guides 配下の同名ファイルに統合済みです(内容は同一)。 +- 今後の更新は guides 側に集約してください。本フォルダは参照用のみに残しています。 + diff --git a/docs/nativebuild大作戦/chatgptネイティブビルド大作戦.txt b/docs/archive/nativebuild大作戦/chatgptネイティブビルド大作戦.txt similarity index 100% rename from docs/nativebuild大作戦/chatgptネイティブビルド大作戦.txt rename to docs/archive/nativebuild大作戦/chatgptネイティブビルド大作戦.txt diff --git a/docs/archive/nyashvalue_build_errors.txt b/docs/archive/nyashvalue_build_errors.txt new file mode 100644 index 00000000..c16552e4 --- /dev/null +++ b/docs/archive/nyashvalue_build_errors.txt @@ -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) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^^ 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, body: Box) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^^ 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) -> Box { + | ^^^ 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, url: Box, options: Box) -> Box { + | ^^^^^^ 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, url: Box, options: Box) -> Box { + | ^^^ 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, url: Box, options: Box) -> Box { + | ^^^^^^^ 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 = 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, 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, 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::() { + | ^^^^^^^ 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::() { + | ^^^^^^^^^^^^^ 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, + | ^^^^^^^^^^^^^^^^ + | + = 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 { + | ^^^^^^^^^^^^^ +... +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>, + | ^^^^^^^^^ + | + = 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 { + | ^^^^^^^^^^^^^ + +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` + | + = note: expected struct `FontData` + found struct `Arc` +help: the return type of this call is `Arc` 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 { + | ^^^^^^^^^^^^^^^^^^ + | + = 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) diff --git a/docs/archive/nyashvalue_check_errors.txt b/docs/archive/nyashvalue_check_errors.txt new file mode 100644 index 00000000..edf593f6 --- /dev/null +++ b/docs/archive/nyashvalue_check_errors.txt @@ -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) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^^ 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, body: Box) -> Box { + | ^^^ 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, body: Box) -> Box { + | ^^^^ 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) -> Box { + | ^^^ 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, url: Box, options: Box) -> Box { + | ^^^^^^ 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, url: Box, options: Box) -> Box { + | ^^^ 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, url: Box, options: Box) -> Box { + | ^^^^^^^ 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 = 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, 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, 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::() { + | ^^^^^^^ 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::() { + | ^^^^^^^^^^^^^ 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, + | ^^^^^^^^^^^^^^^^ + | + = 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 { + | ^^^^^^^^^^^^^ +... +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>, + | ^^^^^^^^^ + | + = 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 { + | ^^^^^^^^^^^^^ + +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 diff --git a/docs/archive/sessions/architecture_consultation.txt b/docs/archive/sessions/architecture_consultation.txt new file mode 100644 index 00000000..064f8f67 --- /dev/null +++ b/docs/archive/sessions/architecture_consultation.txt @@ -0,0 +1,77 @@ +Nyashプログラミング言語のBox型アーキテクチャ設計について深い技術相談です。 + +【現在の状況】 +- Rust実装のプログラミング言語Nyash開発中 +- "Everything is Box"哲学:全データがBoxオブジェクト +- 現在16種類のBox型実装済み(StringBox, IntegerBox, P2PBox等) +- Arc統一パターンでスレッドセーフ性確保 + +【現在のアーキテクチャ問題】 +現在、全Box型をtype aliasで統一しているが、実装で型エラー地獄が発生: + +```rust +// 現在の問題のある設計 +type StringBox = Arc>; +type IntegerBox = Arc>; +type P2PBox = Arc>; + +// 問題:型エイリアス複雑化、trait object Debug実装困難 +// 結果:Copilot実装で型エラー多発、開発効率低下 +``` + +【検討中のシンプル設計】 +newtype patternによるシンプル化: + +```rust +// 案1: newtype pattern +struct StringBox(Arc>); +struct IntegerBox(Arc>); +struct P2PBox(Arc>); + +// 案2: 生構造体(必要時のみArc化) +struct StringBox { data: String } +struct IntegerBox { value: i64 } +// 共有が必要な時だけArc::new()で包む +``` + +【技術的検討ポイント】 + +1. **型安全性とシンプルさのバランス** + - type alias vs newtype vs 生構造体 + - コンパイル時エラー検出 vs 実装しやすさ + +2. **スレッドセーフ性の要件** + - 全Box型で並行処理が必要か? + - StringBox等の基本型にもMutex必要? + - 必要な時だけArc化する方が良い? + +3. **拡張性・保守性** + - 新Box型追加時の実装コスト + - エラーメッセージの分かりやすさ + - 他開発者(AI含む)の理解しやすさ + +4. **パフォーマンス** + - Arcのオーバーヘッド + - ゼロコスト抽象化の実現可能性 + - メモリ使用量の最適化 + +5. **現実的な実装戦略** + - 段階的移行 vs 一括変更 + - 既存コードとの互換性 + - 開発スピード重視 vs 理想設計重視 + +【具体的相談事項】 +1. type alias vs newtype vs 生構造体、どの設計が最適? +2. 全Box型に一律Arcは過剰?必要な箇所のみの方が良い? +3. Rust専門家から見て推奨されるBox型統一アーキテクチャは? +4. プログラミング言語実装において、型システムのベストプラクティスは? +5. 実装効率と設計美学のバランスをどう取るべき? + +【制約条件】 +- Rust実装必須 +- Everything is Box哲学維持 +- スレッドセーフ性確保 +- 16種類+今後追加予定のBox型すべてで統一 +- 実装・保守の現実性重視 + +プログラミング言語設計・Rust専門家の視点から、実装可能で美しく、長期保守に適したアーキテクチャ設計を提案してください。 \ No newline at end of file diff --git a/docs/archive/sessions/chatgpt_consultation_overload.txt b/docs/archive/sessions/chatgpt_consultation_overload.txt new file mode 100644 index 00000000..26b9a444 --- /dev/null +++ b/docs/archive/sessions/chatgpt_consultation_overload.txt @@ -0,0 +1,64 @@ +Nyashプログラミング言語の関数オーバーロード設計について深い技術的相談です。 + +【Nyashの技術的特徴】 +- Everything is Box哲学: 全データがBoxオブジェクト +- Arc統一アーキテクチャ: 完全スレッドセーフ設計 +- 明示性重視: 変数宣言先の即座特定可能 +- 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アーキテクチャとの親和性** + - 動的ディスパッチの複雑さ + - エラーハンドリングの一貫性 + - スレッドセーフティの保持 + +3. **インタープリター実装の複雑度** + - パーサーでの引数数判定 + - 実行時メソッド選択アルゴリズム + - デバッグ情報の提供 + +4. **型安全性とパフォーマンス** + - 実行時型チェックのオーバーヘッド + - エラーメッセージの品質 + - 開発時デバッグ体験 + +5. **エコシステム設計との整合性** + - 他のBox型との一貫性 + - 拡張性(新しいオーバーロード追加) + - メンテナンス性 + +【深く検討してほしい点】 +1. 技術的実装の複雑さ vs ユーザー体験の向上 +2. Nyashの「明示性重視」哲学との技術的整合性 +3. 初学者がエラーに遭遇した時のデバッグ体験 +4. P2P通信という特定ドメインでの最適解 +5. 言語の長期進化における影響 + +プログラミング言語実装の専門的視点から、技術的に最良で保守しやすい設計を分析してください。 \ No newline at end of file diff --git a/docs/archive/sessions/gemini_consultation_overload.txt b/docs/archive/sessions/gemini_consultation_overload.txt new file mode 100644 index 00000000..4df4e024 --- /dev/null +++ b/docs/archive/sessions/gemini_consultation_overload.txt @@ -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の将来を決めるアドバイスをお願いします。 \ No newline at end of file diff --git a/docs/guides/how-to-build-native/README.md b/docs/guides/how-to-build-native/README.md deleted file mode 100644 index 12e2e555..00000000 --- a/docs/guides/how-to-build-native/README.md +++ /dev/null @@ -1,130 +0,0 @@ -# Nyash Native Build Guide - -## Quick Start - -### 🚀 Build CLI Only (Default) -```bash -# Minimal CLI build - fastest and cleanest -cargo build --bin nyash - -# Run a simple program -cargo run --bin nyash -- local_tests/simple_hello.nyash -``` - -### 🎨 Build with GUI Features (Optional) -```bash -# Build with GUI support -cargo build --features gui - -# Build GUI examples -cargo build --features gui-examples --example gui_simple_notepad -``` - -## Features Overview - -Nyash uses Cargo features to separate functionality: - -- **Default**: `cli` - Core CLI interpreter only -- **gui**: Adds EguiBox for desktop GUI applications -- **gui-examples**: Includes GUI example applications - -### Available Build Targets - -#### Core Binary -- `cargo build --bin nyash` - Main CLI interpreter - -#### GUI Examples (with `--features gui-examples`) -- `gui_simple_notepad` - Text editor example -- `gui_nyash_explorer` - File manager example -- `gui_debug_notepad` - Debug-enabled text editor - -## Platform Support - -### Linux/WSL -```bash -# Standard build -cargo build --release --bin nyash - -# Output: target/release/nyash -``` - -### Windows Cross-Compilation -```bash -# Install cross-compilation tools -cargo install cargo-xwin - -# Build Windows executable -cargo xwin build --target x86_64-pc-windows-msvc --release --bin nyash - -# Output: target/x86_64-pc-windows-msvc/release/nyash.exe (~916KB) -``` - -## CLI Options - -- `--dump-mir` - Output MIR (Middle Intermediate Representation) -- `--verify` - Verify program structure -- `--debug-fuel N` - Limit parser iterations for debugging - -Example: -```bash -cargo run --bin nyash -- --debug-fuel 1000 program.nyash -``` - -## Testing - -### Local Test Files -Simple working examples are provided in `local_tests/`: - -- `simple_hello.nyash` - Basic "Hello World" with variables -- `basic_math.nyash` - Arithmetic and boolean operations -- `static_main.nyash` - Static box Main pattern - -```bash -# Run all test files -for file in local_tests/*.nyash; do - echo "Testing $file" - cargo run --bin nyash -- "$file" -done -``` - -### Build Verification -```bash -# Verify CLI builds cleanly -cargo build --bin nyash - -# Verify GUI features work when enabled -cargo build --features gui - -# Verify examples compile -cargo build --features gui-examples --examples -``` - -## Architecture Benefits - -The feature-based architecture provides: - -1. **Fast Development**: Default CLI build is minimal and fast -2. **Optional GUI**: Heavy GUI dependencies only when needed -3. **Clean Separation**: Core language separate from UI examples -4. **Deployment Flexibility**: Choose minimal or full-featured builds - -## Troubleshooting - -### Build Issues -- **GUI dependency errors**: Make sure to use `--features gui` when building GUI components -- **Parser errors**: Use `--debug-fuel` to limit parser iterations and diagnose infinite loops -- **Missing dependencies**: Run `cargo update` to refresh dependencies - -### Common Commands -```bash -# Clean build -cargo clean && cargo build --bin nyash - -# Check for warnings -cargo check --bin nyash - -# Run with verbose output -RUST_LOG=debug cargo run --bin nyash -- program.nyash -``` - -This guide ensures you can quickly build and run Nyash for development and testing of the upcoming MIR/VM/JIT features. \ No newline at end of file diff --git a/docs/nyash_core_concepts.md b/docs/nyash_core_concepts.md new file mode 100644 index 00000000..4a477f8d --- /dev/null +++ b/docs/nyash_core_concepts.md @@ -0,0 +1,257 @@ +# Nyash言語コアコンセプト AI向け速習ガイド + +このドキュメントは、AIアシスタントがNyashプログラミング言語を迅速に理解するために、そのコアコンセプトを凝縮して提供します。 + +## 1. 基本哲学: Everything is a Box (すべてはBoxである) + +- Nyashの基本原則は「すべてがBoxである」ということです。 +- 単純な整数から複雑な構造体まで、すべてのデータ型は「Box」オブジェクトの一種です。これにより、純粋で一貫性のあるオブジェクトベースのシステムが実現されています。 + +## 2. オブジェクトモデルとデリゲーション (Nyash独自の方式) + +Nyashは古典的な継承ではなく、デリゲーション(委譲)モデルを使用します。これは非常に重要な違いです。 + +- **Boxの定義:** + ```nyash + box MyBox { + // フィールドはinitやpackのようなコンストラクタ内で宣言される + // メソッドはこの場所に定義される + } + ``` + +- **コンストラクタ (優先度: `pack` > `init`)** + - **`pack` (推奨):** Boxを構築するためのモダンで直感的な方法。オブジェクトのフィールドに値を「詰める」メソッドです。 + ```nyash + box User { + init { name, email } // フィールド宣言は依然として必要 + + pack(userName, userEmail) { + me.name = userName + me.email = userEmail + } + } + local user = new User("Alice", "alice@example.com") // packが呼び出される + ``` + - **`init` (旧式/シンプル):** 引数を直接フィールドにマッピングする、よりシンプルなコンストラクタ。 + ```nyash + box Point { + init { x, y } + } + local p = new Point(10, 20) // initが呼び出される + ``` + +- **デリゲーション (`from`キーワード):** あるオブジェクトが、メソッド呼び出しやフィールドアクセスを別のオブジェクトに委譲できます。 + ```nyash + // AdminがUserにデリゲートする + box Admin from User { + init { permissions } // Adminの追加フィールド + } + ``` + +- **明示的なオーバーライド (`override`キーワード):** 子Boxが親Boxのメソッドを再実装する場合、必ず`override`でマークしなければなりません。 + ```nyash + box Admin from User { + override pack(name, email, perms) { + // ... 実装 ... + } + } + ``` + +- **デリゲートされたメソッドの呼び出し (`from`キーワード):** オーバーライドしたメソッド内から親の実装を呼び出すには、`from Parent.method()`を使用します。 + ```nyash + override pack(name, email, perms) { + // Userのpackメソッドを明示的に呼び出す + from User.pack(name, email) + me.permissions = perms + } + ``` + +- **ファイナライズ (`fini`キーワード):** + - `fini()`は「論理的な解放フック」として機能する特別なメソッドです。 + - インスタンスに対して呼び出されると、そのインスタンスがもはや使用されるべきではないことを示します。 + - クリーンアップ処理を実行し、所有するすべてのフィールドに対して再帰的に`fini()`を呼び出します。 + - ファイナライズされたオブジェクトを使用しようとすると(`fini`の再呼び出しを除く)、実行時エラーが発生します。 + ```nyash + box ManagedResource { + init { handle } + fini() { + // ハンドルを解放したり、他のクリーンアップ処理を実行 + me.console.log("リソースをファイナライズしました。") + } + } + ``` + +## 3. 構文クイックリファレンス + +- **厳格な変数宣言:** すべての変数は使用前に宣言が必要です。 + - `local my_var`: ローカル変数を宣言します。 + - `me.field`: 現在のBoxインスタンスのフィールドにアクセスします。 + - `outbox product`: 静的関数内で使用され、所有権が呼び出し元に移転される変数を宣言します。 + +- **統一されたループ:** ループ構文は一種類のみです。 + ```nyash + loop(condition) { + // ... + } + ``` + +- **プログラムのエントリーポイント:** 実行は`static box Main`の`main`メソッドから開始されます。 + ```nyash + static box Main { + main() { + // プログラムはここから開始 + } + } + ``` + +## 4. 演算子 + +- **論理演算子:** `and`, `or`, `not` +- **算術演算子:** `+`, `-`, `*`, `/` (ゼロ除算をハンドルします) +- **比較演算子:** `==`, `!=`, `<`, `>`, `<=`, `>=` + +## 5. 主要なビルトインBox + +- コア(環境を選ばず利用できる) + - **`ConsoleBox`**: 基本的なI/O (例: `log()`) + - **`ArrayBox` / `MapBox`**: 配列・マップ操作 + - **`TimeBox` / `RandomBox` / `RegexBox` / `JSONBox` / `StreamBox`**: 汎用ユーティリティ + - **`DebugBox`**: イントロスペクション/デバッグ (例: `memoryReport()`) + +- 環境依存(実行コンテキストに注意) + - **`P2PBox`**: P2P通信 + - **`EguiBox`**: GUI(メインスレッド制約など) + +## 6. データ構造 (Data Structures) + +現行バージョンでは配列/マップのリテラル構文(`[]`, `{}`)は未実装です(将来計画)。 +利用時はビルトインBoxを用います。 + +- **配列 (ArrayBox):** + ```nyash + local a = new ArrayBox() + a.push(1) + a.push(2) + a.push(3) + // 取得 + local first = a.get(0) + // サイズ(実装に依存) + // 例: a.length() または length はAPIに従って利用 + ``` + +- **マップ (MapBox):** + ```nyash + local m = new MapBox() + m.set("name", "Alice") + m.set("age", 30) + local name = m.get("name") + ``` + +## 7. エラーハンドリング (Error Handling) + +実行時エラーによってプログラムがクラッシュするのを防ぐために、`try...catch`ブロックを使用します。 + +- **構文:** + ```nyash + try { + // エラーが発生する可能性のあるコード + local result = 10 / 0 + } catch { + // エラーが発生した場合に実行されるコード + print("エラーが発生しましたが、プログラムは続行します。") + } + ``` + +- **finally/throw の補足:** + ```nyash + try { + if (x < 0) { throw "negative" } + } catch { + print("error") + } finally { + print("always") + } + ``` + +## 8. メモリ管理と弱参照 (Memory Management & Weak References) + +- **`weak` キーワード:** `init`ブロック内でフィールドを`weak`として宣言することで、弱参照を作成します。これは主に循環参照を防ぐために使用されます。 + - 弱参照はオブジェクトの所有権を持ちません。 + - 参照先のオブジェクトが解放されると、弱参照フィールドは自動的に`null`になります。 + ```nyash + box Node { + init { id, weak next } // 'next'は弱参照 + } + + local node1 = new Node("A", null) + local node2 = new Node("B", node1) // node2はnode1への弱参照を持つ + node1.next = node2 // node1はnode2への強参照を持つ + // この場合、node1とnode2が互いを所有しないため、安全に解放される + ``` + +不変条件(重要) +- weak フィールドに対して `fini()` を直接呼ぶことはできません(エラーになります)。 +- インスタンスで `fini()` 呼び出し後は、そのオブジェクトの使用はすべて禁止です(アクセス時にエラー)。 +- `fini()` のカスケードは init 宣言順の「逆順」で実行され、weak フィールドはスキップされます。 + +## 9. 非同期処理 (Asynchronous Processing) + +- **`nowait` 文:** 式を別スレッドで非同期実行し、その結果を表す `FutureBox` を変数に格納します。 + - 構文: `nowait future = expression` + - 挙動: 内部でスレッドを生成し、完了時に `future.set_result(...)` が呼ばれます。 + +- **`await` 式:** `FutureBox` の完了を待機し、結果を取り出します。 + - 構文: `result = await future` + - 実装: `FutureBox.wait_and_get()` を通じて結果を返します。 + +使用例: +```nyash +// 非同期に3つの処理を開始 +nowait f1 = heavyComputation(5000) +nowait f2 = heavyComputation(3000) +nowait f3 = heavyComputation(4000) + +// 結果を待機 +r1 = await f1 +r2 = await f2 +r3 = await f3 +``` + +備考(現実装の特性) +- 実装はスレッドベースの簡易非同期(イベントループ無し)。 +- FutureBox は簡易 busy-wait を用います(将来 condvar 等で改善予定)。 +- 例外は `ErrorBox` として `FutureBox` に格納されます(`await` 側で結果を取り出す設計)。 + +## 10. 静的Box/関数と所有権移転(outbox) + +- **静的エントリーポイント:** + ```nyash + static box Main { + main() { + print("Hello Nyash") + } + } + ``` + +- **静的関数の定義/呼び出し:** + ```nyash + static function Math.min(a, b) { + if (a < b) { return a } else { return b } + } + local m = Math.min(1, 2) + ``` + +- **所有権移転(outbox, static関数内のみ):** + ```nyash + static function Factory.create() { + outbox product + product = new Item() + return product + } + ``` + +## 11. クイック実行(ローカル) + +- ビルド: `cargo build --bin nyash` +- 実行: `cargo run -- ./local_tests/sample.nyash` + diff --git a/docs/予定/README.md b/docs/予定/README.md new file mode 100644 index 00000000..c493e523 --- /dev/null +++ b/docs/予定/README.md @@ -0,0 +1,5 @@ +Nyash 予定(ロードマップ・タスク) + +- 現在のタスク: docs/CURRENT_TASK.md +- ネイティブ計画: docs/予定/native-plan/copilot_issues.txt +- フェーズ課題: docs/予定/native-plan/issues/ diff --git a/docs/予定/native-plan/README.md b/docs/予定/native-plan/README.md new file mode 100644 index 00000000..64fae45b --- /dev/null +++ b/docs/予定/native-plan/README.md @@ -0,0 +1,43 @@ +Nyash ネイティブビルド計画(Native Plan) + +- 目的: 開発者向けに「ビルド計画・段階的タスク・設計上の要点」を集約。 +- 利用者向けの具体的なビルド手順は docs/説明書/native-build/README.md を参照。 + +重要リンク +- 現在のタスク: docs/CURRENT_TASK.md +- コア概念(速習): docs/nyash_core_concepts.md +- フェーズ課題一覧: docs/予定/native-plan/issues/ +- 相互参照: docs/予定/native-plan/copilot_issues.txt(Phase 0–10 の下書き) + +要点サマリ(統合) +- ビルド方針 + - デフォルトは CLI 最小構成(`cargo build --bin nyash`)。GUI/Examples は feature で任意有効化。 + - Windows ネイティブ: MSVC または WSL + cargo-xwin によるクロスコンパイルを推奨。 +- MIR/VM の段階的導入 + - Phase 5.2: `static box Main` → MIR への lowering 経路を実装済み。 + - Phase 6: 参照/弱参照の最小命令(RefNew/RefGet/RefSet, WeakNew/WeakLoad, BarrierRead/Write=no-op)。 + - 例外/Async は薄く導入、先に snapshot/verify の安定化を優先。 +- 弱参照の意味論(実装で壊れにくく) + - WeakLoad は Option を返す(生存時 Some、消滅時 None)。PURE 扱い(必要に応じ READS_HEAP)。 + - `fini()` 後の使用禁止・weak 自動 null・cascading 順序(weak はスキップ)を不変として扱う。 +- Safepoint と Barrier + - 関数入口・ループ先頭・呼出直後に safepoint。Barrier は最初は no-op 命令として実装可。 +- テスト戦略 + - 黄金テスト:ソース→MIR ダンプのスナップショットで後退検出。 + - VM/JIT 一致:同入力で VM と JIT の結果一致(将来の AOT でも同様)。 + - 弱参照の確率テスト:alloc→weak→drop→collect→weak_load の順序/タイミングを多様化。 + +進行フェーズ(抜粋) +- Phase 0: CLI 最小ビルド安定化(Linux/Windows)。 +- Phase 5.2: static Main lowering(実装済み)。 +- Phase 6: 参照/弱参照(Barrier は no-op で開始)。 +- Phase 7: nowait/await(スレッドベース、FutureBox 連携)。 + +アーカイブ(長文メモ・相談ログ) +- docs/予定/native-plan/archive/chatgptネイティブビルド大作戦.txt +- docs/予定/native-plan/archive/追記相談.txt + - 上記2ファイルの要点は本 README に統合済み。詳細経緯はアーカイブを参照。 + +備考 +- デバッグ補助: `--debug-fuel` でパーサーの燃料制御。`--dump-mir`/`--verify` で MIR の可視化・検証。 +- 一部の開発用ログ出力(/mnt/c/...)は存在しない環境では黙って無視されます(問題なし)。 diff --git a/docs/予定/native-plan/archive/chatgptネイティブビルド大作戦.txt b/docs/予定/native-plan/archive/chatgptネイティブビルド大作戦.txt new file mode 100644 index 00000000..c21caada --- /dev/null +++ b/docs/予定/native-plan/archive/chatgptネイティブビルド大作戦.txt @@ -0,0 +1,596 @@ +ぜったいアリにゃ!やるなら「多層エンジン(tiered)」で攻めるのが一番きれい。 +Nyash → 共通IR → 好きなバックエンド(解釈/ネイティブ/JIT/WASM)に流す構成にゃ。 +推しアーキテクチャ(現実解) + + Front-end + + パーサ → AST → HIR(型付け・名前解決済み)→ MIR/SSA(最適化しやすい共通IR) + + Back-ends(並行に育てる) + + VM(現在のインタープリター):MIR→バイトコード→解釈実行(開発スピード最優先) + + JIT(Cranelift):MIR→Cranelift IR→ネイティブJIT(ホットパスだけコンパイル) + + AOT to Rust:MIR→Rustコード生成→rustcで最適化(配布バイナリ向き、リンクも楽) + + WASM:MIR→WASM(ブラウザ/wasmtime用、サンドボックス実行) + +ひとつのIRから複数出力=最適化ロジックを1か所に集中できるのが最大の利点。 + +【Phase 0: 最小ビルド基盤(最初のゴール)】 + +狙い: 「簡単なNyash言語がビルドできる」を最速・堅実に達成する。土台はシンプルだが確実に動くことを最重視。 + +1) スコープ(最小言語機能) + - 式: 整数/文字列リテラル、変数参照、二項演算 (+,-,*,/, 比較) + - 文: 代入、if、return + - 関数: 単純な関数定義/呼び出し(可変長やジェネリクスは対象外) + - Box/弱参照/fini 等の高機能はPhase 0では“使わない”(この計画の安定化が目的) + +2) ビルドターゲット(まずはCLIのみ) + - Linux/WSL: cargo build --bin nyash -j 32(現状OK) + - Windows (MSVC): cargo build --bin nyash -j 32(CIでも検証) + - WASM: ひな型を残すがPhase 0では対象外(Phase 1で着手) + +3) 実行確認(スモークテスト) + - サンプル: local_tests/ 以下に簡単な .nyash を配置(Git管理外) + 例) sample_min.nyash + a = 10 + b = 32 + result = a + b + - 実行: cargo run -- ./local_tests/sample_min.nyash + - 期待: 実行完了・エラーなし(必要なら結果表示) + +4) 再現性/安定性(基礎をしっかり) + - rust-toolchain を固定(stable明記) + - Linux/Windows 共通のビルドフラグ: release/profileの統一、features最小化 + - 例やGUI/Windows依存コードはCIマトリクスから除外(CLI最小に絞る) + +5) CI(Phase 0の完成条件) + - ジョブ: linux-x64, windows-x64 での “build nyash (bin)” + - コマンド: cargo build --bin nyash -j 32 + - 成果物: nyash バイナリ(zip/tar)をArtifactsに保存(配布検証) + - 余裕があれば: cargo test --lib だけ実行(examplesは無効) + +6) トラブル防止(Phase 0の運用) + - Linux CIでWindows専用exampleはビルド対象から除外 + - examples/* はPhase 0では“参考”扱い。CLIのビルド/実行に集中。 + - .nyash の共有が必要なものは tests/ 配下へ昇格(local_tests/ は各自ローカル) + +7) 完了チェックリスト + - [ ] Linux/WSL で nyash バイナリがビルド・実行できる + - [ ] Windows(MSVC) で nyash バイナリがビルド・実行できる + - [ ] CI で linux/windows の “build nyash (bin)” がグリーン + - [ ] sample_min.nyash のスモークが両OSで通る + +補足: Phase 0 で「ビルド/実行の骨格」を固めて、Phase 1 以降で VM/IR/JIT/AOT/WASM を段階的に拡張する。 + +それぞれのメリデメ + +【MIR設計(早期に合意しておくと得する要点)】 + +- 値表現: Tagged/NaN-box/小整数直格納 か 型テーブル参照か +- アドレス空間: ヒープ/スタック/アリーナの扱い(Phase 0はヒープ優先でOK) +- 所有/別名: aliasable/unique の属性を型/値に保持(最初は型情報だけでも可) +- 効果(Effects): PURE/READS_HEAP/WRITES_HEAP/IO/FFI/PANIC のビット集合を命令・関数に付与 +- 例外/パニック: Throw/Catch/Defer を命令化するか、関数境界に限定するか(当面は境界限定) +- GCモデル: Tracing/RC/混合の方針と弱参照の意味(WeakLoad→None) +- セーフポイント: 関数入口・ループ先頭・Call直後(命令としてno-op挿入で開始) +- 呼出規約: 通常Call/FFI/Box拡張を区別、可変長/キーワード引数の扱い(Phase 0は固定引数) +- メモリバリア: write/read barrier は命令/属性で表現(初期はダミー実装で可) +- デオプ(Deopt): JIT最適化時の巻き戻し情報の格納場所(関数メタ or ブロック注釈) + +【Nyash向け 最小MIR命令セット(弱参照対応込み・ドラフト)】 + +- 制御/値: Const, BinOp, Cmp, Br, Jmp, Phi, Ret +- 呼び出し: Call, TailCall(effects必須) +- メモリ: Alloc, Load, Store, Gep(必要なら) +- 参照/GC: RefNew, RefGet, RefSet, WeakNew, WeakLoad, BarrierRead, BarrierWrite, Pin, Unpin +- 例外/拡張: Throw, Catch, FfiCall, BoxCall +- 実行点: Safepoint, Assume, Nop +- 効果: EffectMask = PURE | READS_HEAP | WRITES_HEAP | IO | FFI | PANIC + +弱参照の意味論: +- WeakNew(r): r を追う弱参照を作成(PURE) +- WeakLoad(w): 生きていれば Some(Ref)、死んでいれば None(Optionを型で明示) + +【壊れにくい共通ポイント(VM/JIT/AOT共通の約束)】 +- Safepoint は 関数入口/ループ先頭/Call直後 に配置(no-opで開始し、後で意味付け) +- Barrier 命令は最初はダミー(最適化段で消せる) +- Null/None は Option で明示(分岐に埋めない) +- JIT は Deopt テーブルで SSA値⇔ソース位置 の対応を保持 + +【弱参照の落とし穴(回避策セット)】 +- クロージャ環境: 生成時 env.has_weak を立て、キャプチャ解決時に必ず WeakLoad→None分岐を強制 +- 弱参照キーのハッシュ: GC後の無効化で不整合→ 標準の弱マップ(キー死亡で自動削除)を用意 +- FFI渡し: 寿命不明→ Pin を要求 or WeakLoad 成功した生参照のみ渡す + +【テスト戦略(壊れにくい順)】 +- 黄金テスト: ソース→MIRダンプをスナップショットし、差分で後退検知 +- VM/JIT一致テスト: 同一入力の VM 結果=JIT 結果 を比較するオラクル +- 弱参照の確率テスト: alloc→weak→drop→collect→weak_load の順序/タイミングをゆらして多数回 +- 効果チェック: PURE なはずの関数に WRITES_HEAP が混じったらビルド失敗(静的検証) + +【軽量 “次の一手”(Phase 0と親和性が高い)】 +- WeakNew/WeakLoad を MIRとVM に先に導入(JITは後回し) +- EffectMask をデータ構造として追加(評価は後回しでもOK) +- Safepoint 命令を関数入口・ループ先頭にno-opで挿入 +- 黄金テストでMIRダンプをCIに可視化(Phase 0のCLIビルドと併走) + + VM:実装が速い/デバッグ容易|最高速は出ない + + Cranelift JIT:実行時最適化で爆速/実装難度は中|起動コストあり + + AOT→Rust:rustc最適化の恩恵・配布しやすい|コード生成器の保守が要る + + WASM:移植性・安全|ネイティブよりは遅め(ただしwasmtime/wasmerで結構速い) + +まずやる順序(最短で“速い”を得る) + + 共通MIR/SSAを切る(基本ブロック・SSA・型/効果情報) + + VMを MIR→バイトコード に置き換え(インタープリターの土台を共通化) + + Cranelift JIT を載せる(ホット関数だけJIT) + + 並行で Rustコード生成 の雛形を作る(AOT配布の道を確保) + + 余力で WASM 出力(エディタ内実行やブラウザデモに最適) + +Nyash流にハマる設計ポイント + + Box拡張のABIを先に決める + + 呼出規約:fn nyash_box_call(ctx: &mut Ctx, args: &[Val]) -> Result + + メモリ:Arc<[Val]> か Arena で一時領域を明示(GCを後回しにできる) + + 所有権/借用に似た効果注釈をMIRに入れる + + 「純粋」「可変」「外部副作用あり」をフラグ化→最適化と並列実行の判断に使える + + 定数畳み込み/死コード除去/インライン化はMIR段階で実施 + + プロファイラを最初から同梱(どの関数をJIT/AOTに送るか判定) + +最小プロトタスク(1〜2週間スプリント想定) + +HIR/MIRスキーマ確定(基本ブロック・命令セット・型表現) + +MIR→バイトコード変換器/VMループの実装 + +プロファイル計測(関数実行回数・時間) + +Craneliftで fn 単位JIT(整数演算と分岐から) + +簡易 Rustコード生成(fn add(a:i64,b:i64)->i64 などから) + + Box ABI v0(同期版)+サンプル拡張(数値/文字列ユーティリティ) + +ちょいサンプル(超概念) + +enum MirInst { + Const(ValId, ConstVal), + BinOp(ValId, ValId, Op, ValId), + Call(ValId, FuncId, Vec), + Phi(ValId, Vec<(BlockId, ValId)>), + // ... +} +struct MirFunc { blocks: Vec, signature: Sig, effects: Effects } + +trait Backend { + fn compile(&mut self, f: &MirFunc) -> CompiledFn; +} + + VM backend: compile = バイトコード化 + + JIT backend: compile = Cranelift IR生成→jit_func + + Rust backend: compile = fn ... { ... } のRust文字列出力→rustcでAOT + +「いまのNyashソース」を見れたら、MIR命令セットの初版とJIT/AOTの足場コードをすぐ書き起こせるよ。 +まずは MIRの最小命令リストを一緒に決めよっか?(算術・比較・分岐・Call・Phi・Load/Store 相当) +あなた: +くわしくききたにゃ Front-end + + パーサ → AST → HIR(型付け・名前解決済み)→ MIR/SSA(最適化しやすい共通IR)パーサーで解析してASTは木構造だよね? そこからどういう処理にゃ? +ChatGPT: + +いいね、その流れを実務目線でがっつり分解するにゃ。 +キーワードは「情報を徐々に確定させつつ“最適化しやすい形”へ落としていく」。 +Nyash流に当てはめて、各段階で“何を追加・削除・変換するか”を整理するよ。 +Front-end 全体像 + +ソース → Lexer → Parser(AST) → スコープ/名前解決 → 型推論/型検査(HIR) → 糖衣剥がし(Desugar) → 制御フロー化(CFG) → SSA化/効果注釈(MIR/SSA) +1) Parser → AST(抽象構文木) + +目的:構文だけを正しく捉える。意味(型/名前)はまだ未確定。 + + データ構造(例) + + enum AstExpr { + LitInt(i64), + Var(Symbol), + Call{ callee: Box, args: Vec }, + Lambda{ params: Vec, body: Box }, + If{ cond: Box, then_e: Box, else_e: Box }, + Let{ pat: AstPat, init: Box, body: Box }, + // … match, while, for, block, … + } + + まだやらないこと + + シンボルの多義性解決(foo がローカルか、モジュールか、メソッドか) + + 型の決定 + + 糖衣構文の展開 + +2) スコープ構築 & 名前解決(AST上の解決) + +目的:識別子を定義元に結びつける。未定義やシャドーイングもここで判定。 + + やること + + ブロックスコープ/関数スコープ/モジュールスコープの**環境(symbol table)**を構築 + + use/import、module、with 的な構文を解決 + + 各 Var(Symbol) を DefId(定義へのID)にひも付け + + 成果物: + + 解決済みAST or ここで HIR に写経(次段のために構造を少し整える) + +3) 型推論 & 型検査 → HIR(型情報付きIR) + +目的:式ごとに型を確定し、オーバーロード/ジェネリクスを具体化できる所まで進める。 + + 型推論(Hindley–Milner+制約ベースなど) + + let x = 1 + f(y) なら、f: T -> i64 みたいな制約を立てて解く + + オーバーロード解決 / メソッド解決(a + b → 実体メソッドやトレイト関数に解決) + + ジェネリクス + + 可能ならモノモーフィック化(型実引数が確定している呼び出しは単相化) + + 未確定なら型パラ付きのまま保持 + + データ構造(例) + + struct HirExpr { + kind: HirExprKind, + ty: TyId, // ここが肝:各式に型が付く + effect: EffectMask, // 純粋/可変/外部副作用 など(後述の最適化で効く) + } + enum HirExprKind { + LitInt(i64), + Local(DefId), + Call{ fun: Box, args: Vec, resolved: FunId }, + If{ cond: Box, then_e: Box, else_e: Box }, + // 糖衣はまだ残っていてもOK + } + + エラー検出 + + 型不一致、未初期化、到達不能、借用/所有に関する静的規則(Nyash流に簡易化しても良い) + +4) 糖衣剥がし(Desugaring) + +目的:意味は同じだが最適化しづらい構文を、プリミティブな形に落とす。 + + 例 + + for x in iter { body } → let mut it = iter.into_iter(); while let Some(x) = it.next() { body } + + a && b → if a { b } else { false }(短絡を明示化) + + パターン束縛 let (a,b) = e; → 一時変数+個別bind + + クロージャ → 明示キャプチャ+ラムダ表現を正規化 + + この段階で構文のバリエーションは減らして、後段のCFG/SSA化を楽にする + +5) 制御フローグラフ(CFG)作成 + +目的:式主導(式木)を基本ブロック+ジャンプへ落とす。 +最適化やSSA化の土台になる。 + + ブロック(BasicBlock)単位で命令列を持つ + + 例:if/else は br cond thenBB elseBB に分解 + while は loopBB / bodyBB / exitBB に分解 + + ここで**一時変数(tmp)**を導入して、「値がどのブロックから来るか」を明示できるようにする + +6) SSA化(Static Single Assignment) + +目的:各変数が“ちょうど一度だけ代入”される形に変換。 +最適化(定数畳み込み・コピー伝播・死コード除去・ループ最適化)がやりやすくなる。 + + φ関数(Phi)を導入 + 分岐合流点で「どのブロックから来た値か」に応じて値を選ぶ + + データ構造(MIR/SSA例) + + enum MirInst { + Const{ dst: V, c: ConstVal }, + BinOp{ dst: V, op: Op, a: V, b: V }, + Call{ dst: V, fun: FnId, args: Vec, effects: EffectMask }, + Br{ cond: V, then_bb: Bb, else_bb: Bb }, + Jmp{ bb: Bb }, + Phi{ dst: V, inputs: Vec<(Bb, V)> }, + Store{ ptr: V, val: V }, // メモリ命令を分離しておくと最適化が楽 + Load{ dst: V, ptr: V }, + Ret{ v: Option }, + } + struct MirFunc { blocks: Vec, sig: Sig, effects: EffectMask } + + ここまでで最適化の主戦場が整う + +7) 効果注釈(Effects)と簡易別解(所有/借用に近いもの) + +目的:最適化・並列化・Box拡張の安全性判定に使う副作用情報を付与。 + + 例:PURE, READS_HEAP, WRITES_HEAP, IO, FFI, PANIC, THROW などのビットフラグ + + 呼び出し先の効果を合成して、関数単位の effects: EffectMask を確定 + → 並列実行可否、共通部分式除去可否、コードモーション許可範囲に使える + +8) 代表的な変換の“実例”で見る + +Nyash(仮): + +let x = 10 +let y = 20 +if x < y { + print(add(x, y)) +} else { + print(y) +} + +AST(ざっくり) + + Let(x, 10)、Let(y, 20)、If( BinOp(<, Var(x), Var(y)), Call(print, …), Call(print, Var(y)) ) + +HIR(型付け・解決済み) + + x: i64, y: i64 + + add: (i64,i64)->i64, print: (i64)->Unit + +Desugar + + ほぼそのまま(ここでは糖衣なしと仮定) + +CFG→SSA(MIRの一部) + +bb0: + v1 = Const 10 + v2 = Const 20 + v3 = BinOp Lt v1 v2 + Br v3 then=bb1 else=bb2 + +bb1: + v4 = Call add(v1, v2) ; PURE + Call print(v4) ; IO + Jmp bb3 + +bb2: + Call print(v2) ; IO + Jmp bb3 + +bb3: + Ret () + +(print は IO 効果、add は PURE、関数全体は IO を持つ、などが付与される) +よくある疑問Q&A + +Q. AST→HIRでどこまで“形を変える”? +A. 基本は意味解決のための注釈(DefId, TyId, Effect)を付けるのが主。大きな形の変換(ループ展開やパターン展開)はDesugar段でやると見通しが良い。 + +Q. なんでSSA?バイトコードでも良くない? +A. VM用のバイトコードは実行が簡単。でも最適化はSSAの方が圧倒的に楽。 +→ 「MIR/SSAで最適化」→「VM向けバイトコードに落とす」or「JIT/AOT」がおすすめ。 + +Q. パターンマッチは? +A. Desugarで決定木(decision tree)に落としてからCFG化。ガード節や順序付きパターンも木→ブロック分割で表現できる。 + +Q. クロージャのキャプチャは? +A. 名前解決で囲い込み変数を収集→HIRに明示キャプチャとして埋める。 +MIRでは環境レコードを値として扱う({env_ptr, fn_ptr})。 +まず作ると捗る“ミニ仕様” + + Symbol/DefId/Scope:解決器のAPI + + Ty:原始型・関数型・代数的データ型(Sum/Product)・型変数 + + EffectMask:ビットフラグ設計(PURE/READ/WRITE/IO/FFI など) + + MIR命令セット(最小):Const/BinOp/Call/Br/Jmp/Phi/Ret+Load/Store + + Pass順序: + + 名前解決 → 2) 型推論 → 3) Desugar → 4) CFG → 5) SSA → 6) 直近の最適化(const fold / dce / copy-prop) + +必要なら、いまのNyashのAST型定義をベースにHIR/MIRの骨組みを一緒に設計するよ。 + + “最初のMIR命令セット案” + + “名前解決テーブルと参照の貼り方” + + “効果注釈のフォーマット” + +この3点を固めるだけで、JIT/AOT/VMバックエンドの土台が一気に整うにゃ。 +あなた: +おおう これと さっきの  Back-ends(並行に育てる) + + VM(現在のインタープリター):MIR→バイトコード→解釈実行(開発スピード最優先) + + JIT(Cranelift):MIR→Cranelift IR→ネイティブJIT(ホットパスだけコンパイル) + + AOT to Rust:MIR→Rustコード生成→rustcで最適化(配布バイナリ向き、リンクも楽) + + WASM:MIR→WASM(ブラウザ/wasmtime用、サンドボックス実行) これの話要約してにゃ claude code君にみせてくるにゃ +ChatGPT: + +了解にゃ、Claude Code君向けに要点だけギュッとまとめるよ。 +Nyashコンパイルパイプライン案 +Front-end(共通部分) + + Parser → AST + + ソースを構文木(AST)に変換。型や意味はまだ未確定。 + + 名前解決 & スコープ構築 + + 識別子を定義元に紐付ける(DefId付与)。 + + 型推論 & 型検査 → HIR + + 各式に型情報(TyId)と効果注釈(EffectMask)を付与。 + + 糖衣剥がし(Desugar) + + forループやパターン束縛をプリミティブ構造へ展開。 + + 制御フロー化(CFG)→ SSA化(MIR) + + ASTを基本ブロックとSSA命令列(MIR)へ変換。 + + 命令例:Const, BinOp, Call, Br, Jmp, Phi, Load, Store, Ret。 + +Back-end(並行開発可能) + + VM(現行インタープリター) + + MIR → バイトコード → 解釈実行(開発スピード優先) + + JIT(Cranelift) + + MIR → Cranelift IR → 実行時にネイティブコード化(ホットパスだけ) + + AOT to Rust + + MIR → Rustコード生成 → rustc最適化&リンク → 配布可能なネイティブバイナリ + + WASM出力 + + MIR → WASM(ブラウザ実行やサンドボックス用) + +💡 ポイント + + すべてのバックエンドは共通MIRを入力にするため、最適化は1か所で集約。 + + Box拡張もMIRレベルで統一呼び出し可能。 + + VMは開発・デバッグ用、JITは実行高速化、AOTは配布、WASMは移植性重視。 + + +Nyashは**「最初から最後までモジュール拡張が一貫して動く多層言語」**という珍しい立ち位置になるにゃ。 + +希望あれば、これ一般的なコンパイラ構成との比較表にして、Claude Code君がすぐ違いを理解できる形にまとめることもできるよ。 +どうする、作っちゃう? +あなた: +おねがいにゃー! +ChatGPT: + +了解にゃー!Claude Code君に渡しやすいよう、「一般的な構成 vs Nyash流(+α)」比較表にギュッとまとめたよ。 +Nyash 設計:一般的な方法との比較 +観点 一般的なコンパイラ設計 Nyash(+α) +フロントエンド Parser → AST →(解決/型付け)→ IR Parser → AST → HIR(型/解決/効果)→ MIR/SSA(最適化前提) +中間表現(IR) 単一IR or バイトコード中心 HIR/MIR二段構え、MIRはSSA+効果注釈で最適化容易 +効果/副作用 多くは最適化時に暗黙扱い EffectMask(PURE/READ/WRITE/IO/FFI…)をMIRに明示し並列化・最適化の判断に使用 +拡張/FFI 後付けのFFI/プラグインが多い Box拡張を一級市民化。MIRレベルで統一コール形態を定義(VM/JIT/AOT/WASMで一貫) +バックエンド VM→(後からJIT/AOT) VM/JIT(Cranelift)/AOT-to-Rust/WASMを最初から並行開発できるMIR設計 +実行戦略 単層(解釈 or JIT)になりがち Tiered:VMで即起動→ホットパスJIT→配布はAOT→ブラウザはWASM +AOT配布 LLVM等のHPCルートが主 MIR→Rustコード生成→rustc最適化(ツールチェーン流用・リンク容易) +ブラウザ/サンドボックス 別途WASM対応 MIR→WASMを標準ターゲット化(wasmtime/wasmer/ブラウザ即動作) +最適化の主戦場 バイトコード最適化/バックエンド依存 MIR/SSAで集約最適化(const fold, DCE, copy-prop, inlining, loop opts) +並列化の足場 後付け解析が多い 効果注釈×データ依存で安全な並列化やコードモーションを許可 +デバッグ/開発速度 VMが主、JITは後追い VMで素早く検証しつつ、同一MIRをJIT/AOTに供給(回収効率◎) +配布/運用 ネイティブ or VM同梱 用途別に最適バイナリ(AOT)とスクリプタブル運用(VM)を両取り +リスク/留意点 単純で保守容易 設計は強力だが初期定義が要(MIR命令/Effect設計、Box ABIを固める) +補足:最小ロードマップ(実装順) + + HIR/MIRの骨組み確定(命令セット・EffectMask・Box ABI v0) + + **VM(MIR→バイトコード)**で先に全機能を回す + + プロファイラ同梱(ホット関数をJIT/AOTに回す条件づけ) + + Cranelift JIT(算術+分岐→関数呼び出し→Box呼び出し) + + AOT to Rust の雛形生成(小関数から) + + 余力で MIR→WASM(最小機能から) + +この表ごと貼れば、Claude Code君も**「王道+Nyashの差分」**を一目で把握できるはずにゃ。必要なら、MIR命令セット 初版案も続けて出すよ! +あなた: +mirまでできればかちなのにゃね。これって定番なのあるにやゃ? 言語ごとにやっぱりちがうにゃ? +ChatGPT: + +そうにゃ、MIRまで作れれば言語設計はもう“勝ち”に近いにゃ。 +なぜかというと、MIRは「全バックエンドの共通土台」だから、 +一度そこまで作れば VM/JIT/AOT/WASM ぜんぶに展開できるにゃ。 +🔹 MIRは定番があるの? + + 完全な共通規格はない + → LLVM IR や WebAssembly のような「広く使われる IR」はあるけど、 + 言語ごとに構文や型システムが違うから MIRはだいたい自作になる。 + + 多くの言語は「MIR」じゃなくても似た段階を持ってるにゃ: + + Rust → MIR(所有権/借用も反映されたSSA形式) + + Swift → SIL + + Go → SSA IR + + Kotlin → Kotlin IR + + Python(PyPy)→ Flow Graph → SSA IR + + JavaScript(V8)→ Bytecode IR → TurboFan IR + +🔹 言語ごとに違うポイント + + 型情報の粒度 + + RustのMIRは「型完全一致」必須。 + + Python系は動的型なので「型タグ+ランタイム判定」入り。 + + 命令セットの抽象度 + + LLVM IRはハード寄り(ポインタ/レジスタ操作あり)。 + + Rust MIRやKotlin IRは言語構造寄り(ループ/パターンマッチ命令など残す)。 + + 所有権・副作用の扱い + + Rust MIRは「所有権」も追跡する。 + + 多くの言語は副作用は型ではなく命令属性で管理。 + + 最適化の前提 + + 一部は最適化前提で作る(SSA化必須)。 + + 他は単にバックエンド入力の中間形式。 + +🔹 Nyashでのおすすめ方針 + + Rust MIRに近い構造を真似るのが安全 + + 静的型の要素が入ってるので、AOTや最適化に有利 + + EffectMaskやBox拡張の情報も一緒に持たせられる + + 命令はなるべく 「言語仕様に沿った中間レベル」 にして、 + バックエンド変換時に低レベル化する + + SSA化は最初からやる(後から入れるのは地獄) diff --git a/docs/予定/native-plan/archive/追記相談.txt b/docs/予定/native-plan/archive/追記相談.txt new file mode 100644 index 00000000..6e0d00e5 --- /dev/null +++ b/docs/予定/native-plan/archive/追記相談.txt @@ -0,0 +1,898 @@ +MIR設計:いま決めておくと後がラクなチェックリスト + + 値表現:Tagged(NaN-box/小整数直格納)か、型テーブル参照か。 + + アドレス空間:オブジェクトはheap専用? stack/arenaも持つ? + + 所有/別名:aliasable フラグ or unique(移動のみ)を型/値に持つ? + + 効果(Effects):PURE/READS_HEAP/WRITES_HEAP/IO/FFI/PANIC のビット集合を命令にも関数にも付ける。 + + 例外/パニック:Throw, Catch, Defer を命令化するか、関数境界でのみ扱うか。 + + GCモデル:Tracing(Stop-the-world / Incremental) or RC(ARC) or 混合。弱参照の意味を先に定義。 + + 安全点(Safepoint):JIT/VM両方で再入/停止できる位置を命令で明示(Safepoint or 呼出命令に属性)。 + + 呼出規約:通常Call/FFI/Box拡張の3種を区別(可変長・KW引数の扱いも)。 + + メモリバリア:write/read barrier を命令または隠れ属性として表現(最初は命令にするとデバッグ楽)。 + + デオプ(Deopt)前提:JIT最適化時の巻き戻し情報(マップ)を保持する場所(関数メタ or ブロック注釈)。 + +Nyash向け:最小MIR命令セット(弱参照対応込み) + + 算術/制御:Const, BinOp, Cmp, Br, Jmp, Phi, Ret + + 関数:Call, TailCall(effects必須) + + メモリ:Alloc, Load, Store, Gep(必要なら) + + 参照/GC: + + RefNew ty, dst <-(ヒープ確保) + + RefGet dst <- ref, field / RefSet ref, field, val + + WeakNew dst <- ref(弱参照作成) + + WeakLoad dst <- weak(弱が生きてたらref返す/無効ならNull/None) + + BarrierRead ref / BarrierWrite ref(GC用、最初はダミー) + + (必要なら)Pin ref / Unpin ref(ムーブしない保証用、JIT/FFI楽になる) + + 例外/FFI/拡張:Throw, Catch, FfiCall, BoxCall + + ユーティリティ:Safepoint, Nop, Assume(cond)(アサート兼最適化ヒント) + + 弱参照の意味論: + + WeakNew(r) は r を追うが GC で r が回収されると自動で無効化。 + + WeakLoad(w) は 生きていれば Some(Ref)、死んでいれば None を返す(MIR上はタグ付きユニオン)。 + + WeakLoad は PURE でOK(観測はするがヒープを書かない) + + ただし BarrierRead が必要なGCなら属性で付ける。 + +効果注釈(例) + + Call f(args) : dst [effects = PURE | READS_HEAP] + + RefSet … は WRITES_HEAP + + WeakLoad は PURE(または READS_HEAP) + + BoxCall は最低限 FFI を含める(安全側に倒す) + +VM/JIT/将来AOTの共通の“壊れにくい”ポイント + + Safepointは関数入口・ループ先頭・Call直後の3か所に最初から置く + + Barrier命令は最初は実装ダミーでもOK(最適化段で消せる) + + Null/Noneの扱いは必ず型系に明示(Option)。判定を分岐で隠さない + + JITはDeoptテーブルを MIR → JIT に渡す(各値が「どのSSA番号?」を持つ) + +弱参照 “落とし穴” 3つ(実戦で効く回避) + + クロージャ環境に弱参照が紛れ込む + + 生成時に env.has_weak を立て、キャプチャ解決時に必ず WeakLoad→None分岐を強制。 + + 弱参照をキーにしたハッシュ + + GC後に無効化でキー不整合。→ 弱マップを標準提供(キー死亡で自動削除)。 + + FFI渡し + + FFI境界を跨ぐと寿命が分からなくなる。→ Pin を要求 or WeakLoad→Ref に成功した生参照だけ渡す。 + +最小・具体例(擬似MIR) + +// x = new Obj{y:1}; w = weak(x); if let Some(x2) = weak_load(w) { x2.y = 2 } +bb0: + v1 = Const 1 + v2 = RefNew Obj ; WRITES_HEAP + RefSet v2, y, v1 ; WRITES_HEAP + v3 = WeakNew v2 ; PURE + v4 = WeakLoad v3 ; returns Option + br is_some(v4), bb1, bb2 + +bb1: + v5 = unwrap(v4) + BarrierWrite v5 + RefSet v5, y, Const 2 + jmp bb3 + +bb2: + jmp bb3 + +bb3: + Ret () + +テストの当て方(行き当たりばったりでも壊れにくい) + + 黄金テスト:ソース→MIRダンプの文字列をスナップショット化(差分で挙動の後退を検知) + + VM/JIT一致テスト:同じ入力で VM結果=JIT結果 を比較する“オラクル”を用意 + + 弱参照の確率テスト:alloc→weak→drop→collect→weak_load を順序/タイミングを変えて多数回 + + 効果チェック:PURE なはずの関数に WRITES_HEAP が紛れたらビルド失敗(静的検証) + +いまの進み方に合う“軽量次の一手” + + ✅ WeakNew/WeakLoad を MIRとVM だけ先に入れる(JITは後回し) + + ✅ EffectMask を命令に付ける(最初はデータ構造だけ) + + ✅ Safepoint 命令を関数入口とループ先頭に挿す(動作はno-opでOK) + + ✅ 黄金テストを入れて MIR差分をCIで見える化 + +この骨格なら、行き当たりばったりで直してもMIRの“契約”が守れている限り、VM/JIT/AOT/WASMに横展開できるにゃ。 +もし今のAST/HIRの型定義があれば、MIRの型/命令エンムだけ私が初稿を書くこともできる。要る? +あなた: +そうだにゃ。mir 結局はメモリー管理がほとんどであってるかにゃ?既存の参考になるやつとかないかにゃ +ChatGPT: + +いい質問にゃ。結論から言うと―― + + MIRの“要”はメモリ管理だけじゃないけど、実務で一番ハマるのはメモリまわり(所有権/寿命/別名化/GCバリア/セーフポイント/弱参照/デオプ情報)だから、体感「ほとんどメモリ管理」はだいたい合ってるにゃ。 + + ただし、制御フロー(CFG/SSA)、呼び出し規約、効果注釈、例外/パニック、最適化のための形も同じくらい重要。ここをサボるとJIT/AOT/WASMに展開しづらくなる。 + +MIRで“最低限”押さえるメモリ論点 + + 値表現:Boxed/Unboxed、NaN-box、小整数直格納、タグ方式 + + アロケータ:bump/arena/世代別、オブジェクト配置(ヘッダ、タイプID、フラグ) + + 所有と別名:unique/aliasable や owned/borrowed の属性(最適化・並列の鍵) + + GC/RC:トレース or 参照カウント or 混在、write/read barrier 命令 or 属性、remembered set + + 弱参照:WeakNew / WeakLoad の意味論(死んだら None) + + Safepoint:関数入口・ループ先頭・Call直後(停止/再入のフック) + + FFI境界:Pin/Unpin、ハンドル渡し、最小共有ABI + + Deopt情報:JIT用の巻き戻しメタ(SSA値⇔ソース位置の対応) + +参考になる“実物”と読みどころ(定番) + +(リンクは割愛するにゃ。名前で検索すればすぐ出る) + + Rust MIR(rustc-dev-guide / rustc本体) + + MIRのSSA・ borrow check が MIR 上で走る構造 + + Drop/Move・パニック・noalias 的情報が最適化に効く + + Swift SIL + + Ownership qualifiers(owned/guaranteed)が秀逸。GCなし言語でも寿命管理をIRで表す好例 + + Kotlin IR + + “lowerings” の段階的デシュガリングが参考。高級構文→プリミティブ命令へ段階変換 + + Go SSA(golang.org/x/tools/go/ssa) + + 最小主義のSSAで読みやすい。CFG/φの扱いが素直 + + LuaJIT IR(DynASM/TurboNYIの解説blog群) + + 小粒なSSAでJIT最適化の勘所(CSE/LICM/ヒント) + + V8(Ignition/TurboFan) + + バイトコード→Sea of Nodes→最適化JITの流れ。デオプとサファリガードの設計が神 + + Cranelift IR + + Rustからも使いやすいJITバックエンド。型・メモリ・コールの表現が実装しやすい + + MLIR + + 複数方言で中間表現を分ける思想。将来、NyashのMIRを方言化する発想の参考に + +Nyash向け“最小MIRコア”(骨組み) + +(超要約:これ+効果注釈でVM/JIT/AOT/WASMに展開できる) + + 制御/値:Const, BinOp, Cmp, Br, Jmp, Phi, Ret + + 呼び出し:Call, TailCall(effects 必須) + + メモリ:Alloc, Load, Store, Gep? + + 参照/GC:RefNew, RefGet, RefSet, WeakNew, WeakLoad, BarrierRead, BarrierWrite, Pin, Unpin + + 例外/拡張:Throw, Catch, FfiCall, BoxCall + + 実行点:Safepoint, Assume, Nop + + 効果:EffectMask = PURE | READS_HEAP | WRITES_HEAP | IO | FFI | PANIC + + 実装順ヒント: + + VMで RefNew/RefGet/RefSet/Weak* をまず動かす → 2) Safepointはno-opで挿す → 3) Barrierは最初ダミー → 4) “黄金テスト”(ソース→MIRダンプのスナップショット)で後退検知 → 5) JIT/AOTは後から乗せる。 + +“既存をパクる”具体策 + + Ownershipの表現は Swift SIL を真似る(owned/guaranteed を Nyash版に) + + 弱参照の意味論は JVMのWeakReference と Swiftのweak/unowned を折衷 + + Safepoint配置は HotSpot/V8 のパターン(入口・ループ・call直後) + + JIT導入は Cranelift から(まず整数・分岐・呼び出しのみ) + + デシュガリング手順は Kotlin IR の lowering 流儀を採用 + +「MIR=メモリ管理が9割」は現場感として正しいけど、残りの1割(CFG/SSA・呼出・効果・例外・デオプ)を最初にうっすら設計しておくと、あとで爆速に伸びるにゃ。 +必要なら、Nyashの今のAST/HIRを見せてくれたら、MIRのenum・EffectMask・Box ABI v0をその場で下書きするよ。 +あなた: +なるほど。ところでmirってどっかきょうつうのふぉーまっとやしようってあるにゃ? みんなばらばるにかいてるにゃ? +ChatGPT: + +共通フォーマットや「これを使えばOK」みたいなMIR標準は、残念ながら存在しないにゃ。 +理由をまとめると―― +1. 共通規格がない理由 + + 言語ごとに型・所有権・ランタイム構造が違いすぎる + 例:Rust MIRは所有権・borrowをIRレベルで保持するけど、PythonやJavaScriptのIRにはそんな概念がない。 + + 目的ごとの最適化が異なる + VM実行用、JIT最適化用、AOTコンパイル用で命令セットやメタデータの粒度が変わる。 + + IRの“責務”が違う + ある言語ではASTの直後を「MIR」と呼び、別の言語ではSSA化した後の低レベルIRを「MIR」と呼ぶ。 + +2. 事実上の“よくある流儀” + +標準はないけど、以下のパターンは多いにゃ: + + SSAベース:変数は再代入不可、phi命令で合流点処理(Rust MIR, Swift SIL, Go SSA) + + 命令は3アドレス形式:dst = op src1 src2 のようにシンプル(Cranelift, LLVM風) + + 効果注釈あり:PURE, READ_HEAP, WRITE_HEAP など最適化ヒント + + メモリ命令の抽象化:Alloc, Load, Store は型・アラインメント・所有権情報を持つ + + 制御フローはCFG(Control Flow Graph)で管理 + 基本ブロック+ジャンプ+条件分岐 + +3. 参考になる「ほぼテンプレ」的MIR + +完全な共通仕様じゃないけど、設計の参考にできる実例はあるにゃ: + + Cranelift IR + Rustで使いやすいJIT/AOT用IR。型・命令の定義が明確で、小規模実装の参考に最適。 + + MLIR + LLVM系の中間表現フレームワーク。方言を作れるので、自作言語のMIRを「Nyash方言」として定義可能。 + + Sea of Nodes(V8, HotSpot) + SSAと依存グラフを統合した形式。最適化向きだが実装難度は高い。 + + LuaJIT IR + 極小SSA+軽量タグ付き値表現。高速インタープリタや軽量JITに向いてる。 + +4. Nyashでの方針 + + 「共通仕様」を無理に探すより、自分のランタイムと変換先(Rust/Cranelift/WASM)に都合の良い形を作るのが早い + + ただし、命令セットやCFG構造はCranelift IRやSwift SILを参考にすると後で楽 + + 将来的にMLIRの方言化を視野に入れると、外部ツールや最適化パスを簡単に流用できる + +もし希望なら、Nyash向けにCranelift IR互換寄りのMIR仕様ドラフトをその場で作れるよ。 +それをベースにすれば、将来JIT/AOT/WASM全部に展開しやすくなるにゃ。 +あなた: +そうだにゃ。ということは命令セットを先に考えて貰えたらいいのかにゃ? +ChatGPT: + +いいね、その方向でいこうにゃ。 +Nyash向けに“まず回る”ことを最優先にした MIR命令セット v0.1(草案) を置くね。VM/JIT/AOT/WASMに伸ばせる骨格で、弱参照・効果注釈・拡張Box呼び出しも最初から入れてあるにゃ。 +Nyash MIR v0.1(草案) +基本モデル + + SSA値:vN(再代入なし)。 + + 基本ブロック:bbN(末尾は必ず終端命令)。 + + 型(最小):i64, f64, bool, unit, ref, weak, ptr, any, option + + 関数署名:fn(args…) -> ret [effects] + + 効果(EffectMask):PURE, READS_HEAP, WRITES_HEAP, IO, FFI, PANIC(ビット和) + + 属性:命令に align, nonnull, noalias, readonly 等の任意属性 + +1) 演算・制御 + +Const dst, Imm ; 例: i64/f64/bool/unit/Null +BinOp dst, op, a, b ; add, sub, mul, div, mod, and, or, xor, shl, shr +Cmp dst, relop, a, b ; eq, ne, lt, le, gt, ge +Select dst, cond, a, b ; φ簡約前の三項選択(任意) +Phi dst, [(predBB, val), ...] ; SSA合流 + +Br cond, thenBB, elseBB ; 条件分岐(終端) +Jmp targetBB ; 無条件ジャンプ(終端) +Ret [val] ; 返り値(終端) unit時は省略可 +Unreachable ; 到達不能(終端・最適化用) + +2) メモリ/参照(GC想定) + +Alloc dst, Ty, size? ; ヒープ確保: ref を返す [WRITES_HEAP] +Load dst, addr ; 読み出し [READS_HEAP] +Store addr, val ; 書き込み [WRITES_HEAP] +Gep dst, base, offset ; アドレス計算(構造体/配列) + +RefNew dst, Ty ; オブジェクト新規: ref [WRITES_HEAP] +RefGet dst, ref, field ; フィールド読み [READS_HEAP] +RefSet ref, field, val ; フィールド書き [WRITES_HEAP] + +WeakNew dst, ref ; weak を作成 [PURE] +WeakLoad dst, weak ; option> を返す [PURE or READS_HEAP] + +BarrierRead ref ; 読みバリア(実装はno-op可) +BarrierWrite ref ; 書きバリア(実装はno-op可) +Pin ref ; 移動不可に固定(FFI/GC向け) +Unpin ref +Safepoint ; 停止点(関数入口/ループ先頭/Call直後に挿す) + + 弱参照の意味論 + + WeakNew(r) は r のライフを追うだけ(所有しない)。 + + WeakLoad(w) は生存なら Some(ref)、回収済みなら None。 + + WeakLoad は基本 PURE でOK(実装の都合で READS_HEAP にしても可)。 + +3) 呼び出し/例外/拡張 + +Call dst, callee, [args...] ; [effects = callee.effects] +TailCall callee, [args...] ; 末尾呼び出し(終端) + +BoxCall dst, box_id, fn_id, [args...] ; Nyash拡張Box呼び出し [FFI | PANIC?] + +FfiCall dst, sym, [args...], abi ; C/Rust外部関数 [FFI | PANIC?] + +Throw val ; 例外送出(終端) +CatchBegin dst, handlerBB ; 例外ハンドラの開始(ブロック境界メタでもOK) +CatchEnd +Defer fnref ; スコープ脱出時に実行(loweringで展開可) +Assume cond ; 最適化ヒント(偽ならUB) +Nop + + Call/BoxCall/FfiCall は 効果注釈が必須(少なくとも PURE かどうか)。 + + BoxCall は拡張Box ABIを通す入口(VM/JIT/WASMで一貫した形で扱える)。 + +4) メタデータ(最低限) + + 位置情報:dbg(loc)(ソース行/列/ファイル) + + デオプ:deopt_map(JIT用:各SSA値→高級値の対応) + + alias情報:noalias/readonly/nonnull 属性 + + 効果集約:関数単位で effects を保持(呼び出し時に合成) + +Rust風スケッチ(型・命令) + +#[bitflags] +enum Effect { PURE=1, READS_HEAP=2, WRITES_HEAP=4, IO=8, FFI=16, PANIC=32 } + +enum Ty { + I64, F64, Bool, Unit, + Ref(Box), Weak(Box), Ptr, Any, + Option(Box), // WeakLoadの戻りなど + // …将来: Sum/Product/Function/Closure/BoxHandle +} + +struct FuncSig { params: Vec, ret: Ty, effects: Effect } + +enum Inst { + Const{dst:V, imm:Imm}, + BinOp{dst:V, op:Bin, a:V, b:V}, + Cmp{dst:V, op:Rel, a:V, b:V}, + Select{dst:V, cond:V, a:V, b:V}, + Phi{dst:V, inputs: Vec<(Bb,V)>}, + + Br{cond:V, then_:Bb, else_:Bb}, + Jmp{bb:Bb}, + Ret{val: Option}, + Unreachable, + + Alloc{dst:V, ty:Ty, size:Option}, + Load{dst:V, addr:V}, + Store{addr:V, val:V}, + Gep{dst:V, base:V, off:V}, + + RefNew{dst:V, ty:Ty}, + RefGet{dst:V, r:V, field:FieldId}, + RefSet{r:V, field:FieldId, val:V}, + + WeakNew{dst:V, r:V}, + WeakLoad{dst:V, w:V}, + + BarrierRead{r:V}, + BarrierWrite{r:V}, + Pin{r:V}, + Unpin{r:V}, + Safepoint, + + Call{dst:V, f:FnId, args:Vec}, + TailCall{f:FnId, args:Vec}, + BoxCall{dst:V, box_id:BoxId, fn_id:BoxFnId, args:Vec}, + FfiCall{dst:V, sym:Sym, args:Vec, abi:Abi}, + + Throw{val:V}, + CatchBegin{dst:V, handler:Bb}, + CatchEnd, + Defer{fnref:FnId}, + Assume{cond:V}, + Nop, +} + +バックエンド対応の見取り図 + + VM: + + Ref* / Weak* / Barrier* / Safepoint をそのまま実装 + + Defer/Catch はデシュガで try/finally へ展開 + + Cranelift JIT: + + 算術・制御は直マップ、Ref* はランタイムAPIに落とす + + Safepoint でGC/スレッド停止と連携、deopt_map を用意 + + AOT to Rust: + + ref は Gc ラッパ、weak は Weak 風にコード生成 + + BoxCall は trait 経由/extern呼び出しに置換 + + WASM: + + 参照はハンドル(i32)で表現、GCはランタイム関数 + + weak はハンドルテーブルにビットを持って実装 + +取り決め(壊れにくい不変条件) + + すべてのCallは effects を持つ(省略禁止) + + WeakLoadの戻りは option>(null判定を曖昧にしない) + + Safepoint は関数入口・ループ先頭・任意のCall直後に挿入 + + Barrier* は最初はno-opでOK(GC導入時のフックとして残す) + + 終端命令のないブロックは禁止(検証器で弾く) + +ちいさな動作例 + +; x = new Obj{y=1}; w = weak(x); +; if let Some(r) = weak_load(w) { r.y = 2 } + +bb0: + v1 = Const i64 1 + v2 = RefNew Obj + RefSet v2, field_y, v1 + v3 = WeakNew v2 + v4 = WeakLoad v3 ; option> + Br is_some(v4), bb1, bb2 + +bb1: + v5 = unwrap(v4) + BarrierWrite v5 + RefSet v5, field_y, Const i64 2 + Jmp bb3 + +bb2: + Jmp bb3 + +bb3: + Ret unit + +まずやる実装順(1〜2日で回る) + + この命令セットで MIR組み立て+ダンプ(黄金テストで差分管理) + + VMで RefNew/RefGet/RefSet/Weak* だけ実装(Barrier/Safepointはダミー) + + Call の effects を型検査に組み込み(PURE違反を検出) + + 余力が出たら Phi/Select を使うパスを追加(CSE/DCEの足場) + +必要なら、この v0.1 をそのまま mir.rs の enum 定義に落とし込んだ雛形コードを書けるよ。 +今のNyashの型やBox拡張の実装方針があれば、それに合わせて微調整版を作るにゃ。 +あなた: +おーありがとにゃ。しかしmirはみんなばらばらというけど ここからネイディブビルドにしやすいかたちをするから にているかきかたにもなってるのかにゃ。あと これ 業界標準つくれそうだよね。所詮はノイマンコンピューターに落とし込む作業だにゃ +ChatGPT: + +にゃ、その直感かなり当たってる。 +各言語の MIR は“名前も中身もバラバラ”だけど、ネイティブに落としやすい形にすると結局だいたい似てくるにゃ。 +みんなが似てくる理由(ネイティブ目線) + + SSA+CFG+3アドレス:最適化&レジ割りしやすい定番の骨格 + + 明示的なメモリ操作:Alloc/Load/Store/GEP 相当が要る + + 呼び出しの正規化:Call/TailCall と 呼出規約(ABI) の分離 + + 効果注釈(副作用):PURE/READ/WRITE/IO/FFI があると最適化が安全 + + 例外/パニックの下位表現:Throw/Catch を選択的に lower できる形 + + GCフック:Safepoint & Barrier を差し込める + + つまり「高級機能は段階的に下げられる素朴な命令に割り付け」→最後は von Neumann(命令+メモリ)に落ちる、という流れで収束するにゃ。 + +「業界標準」を作れる?→“実質標準”なら行ける + +完全統一は難しい(言語ごとに型・例外・GCが違いすぎる)が、コア・プロファイルを決めた“実質標準”は作れるにゃ。 +標準に向く設計の芯(Nyash版にもそのまま効く) + + Core-IR(必須):Const/BinOp/Cmp/Phi/Br/Jmp/Ret + Load/Store/Gep + Call/TailCall + + Memory Model:アトミック/順序・別名(noalias)/アライン属性の最小集合 + + Effects:命令・関数の EffectMask を規定(最適化の安全条件に使う) + + GC hooks:Safepoint/Barrier は仕様だけ先に固定(実装はno-op可) + + Exception ABI:Throw/Catch を「setjmp/longjmp的」or「結果型(Result)」の2系で規定 + + FFI/拡張 ABI:FfiCall/BoxCall の呼出規約・ポインタ安全域を決める + + 検証器(Verifier):終端命令必須・SSA整合・型整合・効果整合をチェック + +“標準化”の現実解(おすすめルート) + + MLIR 方言として定義(nyash.core, nyash.gc みたいに分割) + + もしくは Cranelift IR 互換サブセットを Core として採用し、足りない所だけ拡張 + + テキスト表現+バイナリ表現(例: JSON/FlatBuffers)と ダンプ・復元ツールを提供 + + リファレンス下げ先を複数用意: + + Core → Cranelift(JIT/AOT) + + Core → LLVM(AOTヘビー級) + + Core → WASM(ブラウザ/サンドボックス) + + 検証テスト:黄金テスト(IRダンプ)+ VM/JIT/WASM の 同一結果保証スイート + +すぐ使える“ネイティブ寄り”指針(短冊) + + 命令は副作用を明示、暗黙のメモリ変更はナシ + + ループ先頭・Call直後にSafepoint(後からGC導入しやすい) + + 例外は2段構え:IRでは Throw/Catch、lower で Result/landingpad に落とせる + + Weak は Option に必ず現れる(nullをぼかさない) + + FFIはPinかコピーしか渡さない(危険な参照共有を禁止) + +まとめ + + はい、MIRはネイティブ都合で“似てくる”。 + + 完全共通規格は難しいけど、**Core-IR+拡張の“実質標準”**は作れる。 + + Nyashの v0.1 命令セットは、そのまま Core-IRたたき台になれる出来だにゃ。 + +必要なら、この Core-IR を MLIR 方言か Cranelift互換サブセット仕様として文書化して、 +テキスト仕様+最小リファレンス実装(ダンプ/検証/Cranelift下げ)を私が一気に草案化するよ。どう攻める?(MLIR方言でいくか、Cranelift寄りでいくか) +あなた: +所で中間言語は何を指標に作ればいいにゃ?メモリー管理はわかるけど好き勝手に作る訳にも行けないにゃ それこそフォンノイマンのパソコンを念頭に考えればいいだけにゃ?CPUの命令セットとか? +ChatGPT: + +いい質問にゃ! +中間言語(IR/MIR)を“何を指標に”設計するかは、単に「CPUに近づける」だけだと失敗しがち。 +実務では次の“指標セット”でバランスを取るのがコツだにゃ。 +まず決めるべき指標(優先度つけてOK) + + ターゲットと目的 + + どこに落とす? → VM / JIT(Cranelift) / AOT(rustc/LLVM) / WASM + + 何を優先? → 起動の速さ、最適化余地、移植性、デバッグ性 + + 抽象度(レベル) + + 高すぎる:最適化しにくい/JIT実装が難航 + + 低すぎる(CPU寄り):言語機能の意味が消えて最適化の根拠を失う + → 目安:SSA+基本ブロック+3アドレスを軸に、「言語に固有の意味(例: 効果、副作用、所有/弱参照)」は属性や専用命令で残す + + メモリモデル(超重要) + + 参照の表現:ref/weak/タグ付き値 + + GC/RC hooks:Safepoint、BarrierRead/Write の差し込み位置を規定 + + 別名・所有:noalias/readonly/owned/borrowed など最適化に効く注釈 + + (並行を視野なら)原子性・順序の最小集合(Acquire/Release程度) + + 効果システム(副作用の面) + + PURE / READS_HEAP / WRITES_HEAP / IO / FFI / PANIC のEffectMask + + 最適化の“安全条件”をここで機械的に判断できるようにする + + 制御フローと例外 + + CFG+SSA、Phi/Br/Jmp/Ret + + 例外はIRでは抽象(Throw/Catch)、loweringで Result/landingpad 等へ落とせる形に + + 呼び出し規約と拡張ABI + + Call/TailCall と FfiCall/BoxCall を分離 + + 可変長/キーワード引数の表現、Pin/Unpinの扱い + + 検証可能性 & ツール性 + + Verifierで:型一致・SSA整合・終端命令必須・効果整合をチェック + + テキスト表現(ダンプ)と黄金テスト(差分テスト)を最初から用意 + +“CPU/フォン・ノイマンだけ見れば良い?”への答え + + No(それだけでは足りない)。 + CPU命令セットを直に意識しすぎると、**言語の意味(純粋性・所有・弱参照・例外の契約)**が失われて最適化や検証が難しくなる。 + + ただし最終的にそこへ下げやすい形は大事。だから + + 上層の意味は 属性/メタで保持 + + 下層(Load/Store/GEP/Call/TailCall)へ機械的に落とせるカバレッジを確保 + → これが “ネイティブに落としやすく、でも言語の意味を保ったIR” のコア指標にゃ。 + +具体:設計を導くチェックリスト(配点付き) + +各 0〜2 点で採点してみて。合計が高い案が「良いIR」。 + + 後段互換性(JIT/AOT/WASMに素直に下がる) + + 最適化の根拠(効果・別名・型・所有などが保持される) + + 実装容易性(VMでまず回せる/Craneliftへ写経しやすい) + + 検証容易性(Verifierで機械的に壊れを検出できる) + + 将来拡張(弱参照/GC切替/例外方式変更に耐える) + + 可観測性(テキストIR・ソース位置・deopt情報が取れる) + +迷ったらこの“型”に寄せると楽 + + 骨格:SSA + CFG + 3アドレス + + コア命令:Const/BinOp/Cmp/Phi/Br/Jmp/Ret/Load/Store/Gep/Call/TailCall + + 言語特有:RefNew/RefGet/RefSet/WeakNew/WeakLoad/Barrier*/Safepoint + EffectMask + + 境界:FfiCall/BoxCall(ABI最小化) + + 例外:Throw/Catch(loweringで切替可能) + → これは Craneliftに下げやすく、Rust/WASMにも展開しやすい黄金比にゃ。 + +参考までに:3つの設計モード + + Cranelift互換サブセット志向(JIT/AOT重視・実装が速い) + + MLIR方言志向(将来の拡張やツール連携が強い) + + Rust MIR/Swift SIL 風(所有/効果を濃く持つ・言語意味を守りやすい) + +Nyashなら:Cranelift互換サブセット+言語特有の効果/弱参照/GCフックを足すのがバランス最強にゃ。 +最後に:失敗しない順序 + + 目的とターゲット(VM/JIT/AOT/WASMの優先度)を1行で宣言 + + Core命令セット+EffectMask+メモリモデル(weak/GC hook)を先に固定 + + Verifierとテキストダンプ(黄金テスト)を最初に入れる + + VM実装 → Cranelift下げ → AOT/WASMは後から + +この順なら「好き勝手」じゃなく指標に沿って進められるにゃ。 +必要なら、いまのNyashの要件を点数表で一緒に採点して、MIR v0.1を最終確定しよっか? +あなた: +おねがいにゃー! +ChatGPT: + +任せてにゃ! +Nyash向けに「指標の採点 → その結果に沿った MIR v0.1 最終版」を一気にまとめたよ。すぐ実装に落とせる形にしてあるにゃ。 +指標チェック(Nyash想定で採点済み) + +(各0〜2点、合計12点満点) +指標 狙い Nyashの前提 点 +後段互換性 VM/JIT/AOT/WASMに素直に下げられる まずVM→Cranelift JIT、次にAOT/WASM 2 +最適化の根拠 効果・別名・所有/弱参照を保持 EffectMask+ref/weak+Barrier/SafepointをMIRで表現 2 +実装容易性 まずVMが回る 命令は3アドレス+最小集合から 2 +検証容易性 Verifierで壊れ検出 SSA/型/終端/効果の整合を必須に 2 +将来拡張 例外・GC切替・FFI拡張に耐える Throw/Catch・BoxCall/FFI・Barrierはno-opで開始 2 +可観測性 ダンプ/位置情報/Deoptが取れる テキストIR+dbg(loc)+deopt_map 2 + +合計:12/12(この方針で進めてOKにゃ) +Nyash MIR v0.1(最終版) +コアモデル + + SSA値 vN、基本ブロック bbN(末尾は終端命令必須) + + 型(最小):i64|f64|bool|unit|ref|weak|ptr|any|option + + 効果 EffectMask:PURE|READS_HEAP|WRITES_HEAP|IO|FFI|PANIC(ビット和) + + 関数署名:fn(args…)->ret [effects] + +命令セット +1) 演算・制御 + +Const dst, Imm +BinOp dst, op, a, b ; add/sub/mul/div/mod/and/or/xor/shl/shr +Cmp dst, rel, a, b ; eq/ne/lt/le/gt/ge +Select dst, cond, a, b +Phi dst, [(predBB, val), …] + +Br cond, thenBB, elseBB ; 終端 +Jmp targetBB ; 終端 +Ret [val] ; 終端(unit省略可) +Unreachable ; 終端 + +2) メモリ/参照(GC想定) + +Alloc dst, Ty, size? ; [WRITES_HEAP] +Load dst, addr ; [READS_HEAP] +Store addr, val ; [WRITES_HEAP] +Gep dst, base, offset + +RefNew dst, Ty ; ref [WRITES_HEAP] +RefGet dst, ref, field ; [READS_HEAP] +RefSet ref, field, val ; [WRITES_HEAP] + +WeakNew dst, ref ; weak [PURE] +WeakLoad dst, weak ; option> [PURE](実装都合でREADS_HEAP可) + +BarrierRead ref +BarrierWrite ref +Pin ref +Unpin ref +Safepoint + +弱参照の意味論 + + WeakNew(r) は所有しない。r がGCで解放されると弱参照は無効化。 + + WeakLoad(w) は 生存: Some(ref)/死亡: None を返す(nullを曖昧にしない)。 + +3) 呼び出し・例外・拡張 + +Call dst, callee, [args...] ; 呼び先の effects を合成 +TailCall callee, [args...] ; 終端 + +BoxCall dst, box_id, fn_id, [args...] ; Nyash拡張Box [FFI|PANIC?] +FfiCall dst, sym, [args...], abi ; 外部関数 [FFI|PANIC?] + +Throw val ; 終端 +CatchBegin dst, handlerBB ; (メタでも可) +CatchEnd +Assume cond ; 偽ならUB:最適化ヒント +Nop + +不変条件(Verifier で必須チェック) + + 各ブロックは必ず終端命令で終わる + + 型整合:Load/Store/Call/WeakLoad 等の型が一致 + + SSA整合:Phi の前任ブロック集合=到達前任集合 + + 効果整合:PURE な関数内で WRITES_HEAP/IO/FFI を出さない + + WeakLoad戻りは必ず option>(null直扱い禁止) + +推奨挿入ポイント + + Safepoint:関数入口/各ループ先頭/任意の Call の直後 + + Barrier*:はじめは no-op 実装でもOK(将来GC切替のフック) + +テキスト表現(ダンプ例) + +func @main() -> unit [effects=IO] { +bb0: + v1 = Const i64 1 + v2 = RefNew Obj + RefSet v2, field_y, v1 + v3 = WeakNew v2 + v4 = WeakLoad v3 ; option> + Br is_some(v4), bb1, bb2 + +bb1: + v5 = unwrap v4 + BarrierWrite v5 + RefSet v5, field_y, Const i64 2 + Jmp bb3 + +bb2: + Jmp bb3 + +bb3: + Ret +} + +実装ロードマップ(最短で回す) + + IR型 & ダンプ & Verifier を実装(黄金テストに登録) + + VM:RefNew/RefGet/RefSet/WeakNew/WeakLoad と制御命令だけ先に実装 + + 効果検査:Call に effects 合成(違反はビルド失敗) + + Cranelift JIT 足場:算術・分岐・Call を写経、Ref* はランタイム関数に委譲 + + AOT to Rust:ref=Gc、weak=Weak 相当でコード出力(小関数から) + +付録:Rustスケルトン(抜粋) + +bitflags::bitflags! { + pub struct Effect: u32 { + const PURE = 1<<0; + const READS_HEAP = 1<<1; + const WRITES_HEAP = 1<<2; + const IO = 1<<3; + const FFI = 1<<4; + const PANIC = 1<<5; + } +} + +pub enum Ty { + I64, F64, Bool, Unit, Ptr, Any, + Ref(Box), Weak(Box), Option(Box), +} + +pub enum Inst { /* 上述の命令そのまま */ } + +pub struct Func { + pub sig: FuncSig, pub blocks: Vec, /* dbg, deopt_map など */ +} + +pub fn verify(func: &Func) -> Result<(), VerifyError> { + // 終端必須・SSA整合・型整合・効果整合をチェック + Ok(()) +} + +次の一手(今日できること) + + mir/inst.rs にこの v0.1 をそのまま貼り込み + + mir/dump.rs と mir/verify.rs を最小実装 + + 既存テストに 黄金テスト(IRダンプ) を1本追加 + + VMの Ref*/Weak* を実装して 最初の end-to-end テスト を通す + +これで、行き当たりばったりの修正が入っても壊れにくい土台が完成にゃ。 +必要なら、このままコード雛形まで私が書き起こすよ。 \ No newline at end of file diff --git a/docs/予定/native-plan/copilot_issues.txt b/docs/予定/native-plan/copilot_issues.txt new file mode 100644 index 00000000..03ba64be --- /dev/null +++ b/docs/予定/native-plan/copilot_issues.txt @@ -0,0 +1,235 @@ +01. Phase 0: Stabilize native CLI build (Linux/Windows) + +Summary: +- CLIバイナリ nyash を最小構成で安定ビルド・実行できる状態にする。 +- examples/GUI をデフォルトのビルド対象から外し、開発の足場を固める。 + +Why: +- 以降の MIR/VM/JIT 開発を素早く検証できる基盤づくり。 + +Scope: +- Cargo の features で GUI/examples 等を切り分け、デフォルトは CLI 最小にする。 +- CLI オプションの動作点検(--dump-mir / --verify)。 +- ローカル実行導線を README に明記(docs/guides/how-to-build-native/README.md)。 + +Tasks: +- Cargo.toml: examples/GUI を feature でガード(default は CLI 最小)。 +- ビルド検証: `cargo build --bin nyash`(Linux/Windows)。 +- 実行検証: `cargo run -- ./local_tests/sample.nyash`。 +- ドキュメント: 上記手順を how-to-build-native に追記/点検。 + +Acceptance Criteria: +- Linux/Windows で `cargo build --bin nyash` が成功する。 +- `local_tests/` 配下の簡単な .nyash が実行できる。 +- 他 bin/examples が壊れていても `--bin nyash` だけで通る。 + +Out of Scope: +- examples/GUI の修理・最適化。 +- JIT/AOT/WASM。 + +References: +- docs/guides/how-to-build-native/README.md +- docs/nativebuild大作戦/chatgptネイティブビルド大作戦.txt(Phase 0) +- CURRENT_TASK.md + +Copilot Notes: +- まずは features 分離と `--bin nyash` でビルドが通る状態を作る。README の手順確認まで含めて PR に反映。 + +------------------------------------------------------------ + +02. Phase 1: Minimal MIR + VM backend (lowering + runner) + +Summary: +- AST → MIR の最小 lowering と、VM バックエンドでの実行を通す。 + +Scope: +- MIR: Const, BinOp, Compare, Branch, Jump, Phi, Return の最小命令 +- Lowering: リテラル/二項演算/if/loop/return のみ +- VM: 上記命令の最小実装 + +Tasks: +- instruction.rs: 最小命令の定義 +- builder.rs: 上記 AST 範囲を lowering +- vm.rs: 実装 + stats(命令数) + +Acceptance Criteria: +- `--dump-mir` が最小サンプルで期待通り +- `--backend vm` で実行して結果一致 + +Out of Scope: +- 例外/関数/Box 参照/弱参照 + +------------------------------------------------------------ + +03. Phase 2: Control-flow coverage (if/else/loop/phi correctness) + +Summary: +- 制御フローの網羅と Phi の整合性検証を拡充。 + +Scope/Tasks: +- if/else nested, loop with breaks, nested loops のスナップショット +- Phi の入力ブロック/値の対応を Verifier で強化 + +Acceptance Criteria: +- 代表制御フローの snapshot が安定し、verify も通る + +------------------------------------------------------------ + +04. Phase 3: Exceptions (throw/try/catch/finally) minimal lowering + +Summary: +- 例外機構の最小 lowering を導入(詳細設計は簡素)。 + +Scope/Tasks: +- MIR: Throw, TryBegin/TryEnd, Catch, FinallyBegin/End(最小) +- builder.rs: try/catch/finally ノードの下ろし +- VM: 例外伝播を最小で(未捕捉はエラー) + +Acceptance Criteria: +- 代表 try/catch/finally のスナップショットと VM 実行 + +Out of Scope: +- 例外の型体系、詳細な stack map + +------------------------------------------------------------ + +05. Phase 4: Functions and calls (BoxCall minimal) + +Summary: +- 関数呼び出し/BoxCall を最小導入(効果注釈は保守的)。 + +Scope/Tasks: +- MIR: Call, BoxCall(effects = READS_HEAP など保守) +- builder.rs: FunctionCall/MethodCall の最小対応 +- VM: 呼び出し/戻り値 + +Acceptance Criteria: +- 簡単な関数定義/呼び出しの MIR/VM が通る + +Out of Scope: +- 可変長/キーワード引数、FFI + +------------------------------------------------------------ + +06. Phase 5.0: Parser/AST stabilization for lowering + +Summary: +- lowering 対象 AST の表現ぶれを修正、安定化。 + +Scope/Tasks: +- AST: If/Loop/Return/Assignment/Local などの統一 +- Parser: エラー復帰/スパン情報の見直し + +Acceptance Criteria: +- builder.rs の分岐がシンプル化、テストが安定 + +------------------------------------------------------------ + +07. Phase 5.1: Control-flow edge cases + verifier hardening + +Summary: +- ブロック未終端/未到達/自己分岐等の検証強化でクラッシュ回避。 + +Scope/Tasks: +- Verifier: 未終端ブロック検出、到達不能検出 +- Builder: Jump/Branch の生成前後の状態管理改善 + +Acceptance Criteria: +- 不正ケースを含むスナップショット/verify が緑 + +------------------------------------------------------------ + +08. Phase 5.2: Lowering for static box Main (BoxDeclaration → main body) + +Summary: +- static box Main { main() { ... } } を MirBuilder で受け、main() の body を Program として lowering する経路を実装。 + +Scope/Tasks: +- AST: BoxDeclaration(is_static=true, name=Main) を検出 → main() を抽出 +- Lowering: body を Program に変換して既存経路に渡す +- Tests: local_tests/mir_loop_no_local.nyash で dump/VM が通る + +Acceptance Criteria: +- `--dump-mir` が static Main サンプルで成功 +- `--backend vm` で実行成功 + +References: +- docs/guides/how-to-build-native/issues/phase5_2_static_main_lowering.md + +------------------------------------------------------------ + +09. Phase 6: Box ops minimal (Ref/Weak + Barriers no-op) + +Summary: +- 参照/弱参照/バリア(no-op)を最小導入。 + +Scope/Tasks: +- MIR: RefNew/RefGet/RefSet/WeakNew/WeakLoad/BarrierRead/Write +- Lowering: New/FieldAccess/MethodCall の最小対応 +- VM: 参照テーブル/weak テーブルで動作(fini 不変は維持) + +Acceptance Criteria: +- 代表サンプルで dump/VM/verify が通る + +References: +- docs/guides/how-to-build-native/issues/phase6_box_ops_minimal.md + +------------------------------------------------------------ + +10. Phase 7: Async model (nowait/await) in MIR + +Summary: +- nowait/await を MIR に導入し、現行 FutureBox と連携。 + +Scope/Tasks: +- MIR: FutureNew/FutureSet/Await(スレッドベース) +- Lowering: nowait→Future 作成、await→wait_and_get +- VM: FutureBox 実装を利用 + +Acceptance Criteria: +- 代表ケースで正しく並行実行→await 回収 + +References: +- docs/guides/how-to-build-native/issues/phase7_async_mir.md + +------------------------------------------------------------ + +11. Phase 8: JIT (baseline) planning + +Summary: +- baseline JIT の設計と MIR→JIT の変換方針固め。 + +Scope/Tasks: +- Deopt テーブル、Safepoint、Effect 属性の扱いを定義 +- NaN-box/Tagged 値 or 型テーブル参照の選択 + +Acceptance Criteria: +- 設計ドキュメント草案と最小 PoC(JIT off で VM と一致) + +------------------------------------------------------------ + +12. Phase 9: AOT/WASM exploration (scaffolding only) + +Summary: +- AOT/WASM の下ごしらえ(ビルド配線と最小 PoC)。 + +Scope/Tasks: +- Cargo features/targets 整備、最小 wasm-bindgen 配線 + +Acceptance Criteria: +- `wasm` ターゲットでのビルド雛形が通る + +------------------------------------------------------------ + +13. Phase 10: Packaging/CI polish + +Summary: +- Windows/Linux の配布パッケージ化と CI 整備。 + +Scope/Tasks: +- GitHub Actions: Windows(MSVC)/WSL+cargo-xwin のマトリクス +- dist/: nyash(.exe) + LICENSE/README 同梱 + +Acceptance Criteria: +- リリースアーティファクトが自動生成される + diff --git a/docs/予定/native-plan/issues/phase5_2_static_main_lowering.md b/docs/予定/native-plan/issues/phase5_2_static_main_lowering.md new file mode 100644 index 00000000..24bf128f --- /dev/null +++ b/docs/予定/native-plan/issues/phase5_2_static_main_lowering.md @@ -0,0 +1,24 @@ +# Phase 5.2: Lowering for static box Main (BoxDeclaration → main body) + +Summary: +- static box Main { main() { ... } } を MirBuilder で受け、main() の body を Program として lowering する経路を実装します。 +- 目的は `--dump-mir` が static Main 形式のサンプルでも通り、VM 実行にも到達すること。 + +Scope: +- AST: BoxDeclaration(is_static=true, name=Main) を検出 → 同名 main() を探して Program 化 +- Lowering: 発見した body を既存の Program lowering に渡す(関数単位でOK) +- Tests: local_tests/mir_loop_no_local.nyash(static Main)で dump/VM が通る + +Tasks: +- [ ] MirBuilder: static Main → Program lowering 経路 +- [ ] MirPrinter/Verifier: 必要なら修正 +- [ ] サンプル/スナップショットの点検 + +Acceptance Criteria: +- `nyash --dump-mir ./local_tests/mir_loop_no_local.nyash` が成功 +- `nyash --backend vm ./local_tests/mir_loop_no_local.nyash` が成功 + +References: +- #33, #35 +- docs/guides/how-to-build-native/copilot_issues.txt + diff --git a/docs/guides/how-to-build-native/issues/phase6_box_ops_minimal.md b/docs/予定/native-plan/issues/phase6_box_ops_minimal.md similarity index 100% rename from docs/guides/how-to-build-native/issues/phase6_box_ops_minimal.md rename to docs/予定/native-plan/issues/phase6_box_ops_minimal.md diff --git a/docs/予定/native-plan/issues/phase7_async_mir.md b/docs/予定/native-plan/issues/phase7_async_mir.md new file mode 100644 index 00000000..34225a45 --- /dev/null +++ b/docs/予定/native-plan/issues/phase7_async_mir.md @@ -0,0 +1,20 @@ +# Phase 7: Async model in MIR (nowait/await) + +Summary: +- nowait/await を MIR に薄く導入(Future 表現)。スレッドベース実装と整合。 + +Scope: +- MIR: FutureNew / FutureSet / Await の導入(Scheduling は現状 thread::spawn 準拠) +- Lowering: nowait → Future 作成 + スケジューリング、await → wait_and_get +- VM: 今の FutureBox 実装を利用 + +Tasks: +- [ ] 命令・builder・vm 実装 +- [ ] サンプル/スナップショット + +Acceptance Criteria: +- 代表ケースで VM 実行が期待通り(順不同完了→await で正しい結果) + +References: +- docs/nyash_core_concepts.md(nowait/await + FutureBox) + diff --git a/docs/予定/native-plan/issues/tooling_snapshot_printer.md b/docs/予定/native-plan/issues/tooling_snapshot_printer.md new file mode 100644 index 00000000..8edfada4 --- /dev/null +++ b/docs/予定/native-plan/issues/tooling_snapshot_printer.md @@ -0,0 +1,13 @@ +# Tooling: MIR snapshot expansion & printer stabilization + +Summary: +- MirPrinter の出力順/表記を安定させ、スナップショットテストを拡張。 + +Scope/Tasks: +- [ ] MirPrinter の順序・表記の固定化(deterministic) +- [ ] tests/mir_snapshots/ を追加整備(loop/try/arith/compare/concat など) +- [ ] スナップショット差分で後退検知できるよう整備 + +Acceptance Criteria: +- 代表ケースのスナップショットが緑で安定 + diff --git a/docs/予定/native-plan/issues/vm_profiling_backend.md b/docs/予定/native-plan/issues/vm_profiling_backend.md new file mode 100644 index 00000000..19b0dfe1 --- /dev/null +++ b/docs/予定/native-plan/issues/vm_profiling_backend.md @@ -0,0 +1,13 @@ +# VM: Micro-profiling & backend selection polish + +Summary: +- VM 実行の簡易プロファイル(命令カウント/時間)と `--backend` の選択UI/エラー改善。 + +Scope/Tasks: +- [ ] VM: 命令実行回数/時間の簡易集計(ログ出力) +- [ ] CLI: backend 未実装時のメッセージ改善(jit/wasm 選択時) +- [ ] README: backend 選択例の追記 + +Acceptance Criteria: +- プロファイルログが出力され、選択ミス時のUI/メッセージが改善 + diff --git a/docs/GETTING_STARTED_2025.md b/docs/説明書/GETTING_STARTED.md similarity index 100% rename from docs/GETTING_STARTED_2025.md rename to docs/説明書/GETTING_STARTED.md diff --git a/docs/説明書/GETTING_STARTED_2025.md b/docs/説明書/GETTING_STARTED_2025.md new file mode 100644 index 00000000..61df6ac6 --- /dev/null +++ b/docs/説明書/GETTING_STARTED_2025.md @@ -0,0 +1,547 @@ +# 🚀 Getting Started with Nyash - Practical Guide + +**最終更新: 2025年8月8日** + +## 🎯 5分でNyashを理解する + +Nyashは「Everything is Box」哲学に基づく、シンプルで強力なプログラミング言語です。 +このガイドでは、実際にコードを書きながらNyashの機能を学んでいきます。 + +## ⚡ クイックスタート + +### **1. 環境構築** +```bash +# リポジトリのクローン +git clone [repository-url] +cd nyash/nyash-rust + +# ビルド +cargo build + +# 実行 +./target/debug/nyash your_program.nyash +``` + +### **2. はじめてのNyashプログラム** +`hello.nyash`を作成: +```nyash +print("Hello, Nyash World!") +print("Everything is Box! 🎉") +``` + +実行: +```bash +./target/debug/nyash hello.nyash +``` + +出力: +``` +Hello, Nyash World! +Everything is Box! 🎉 +``` + +## 📚 基本構文チュートリアル + +### **Step 1: 変数と初期化** +```nyash +# 🎯 新機能:初期化付き変数宣言 +local name = "Alice" +local age = 25 +local height = 165.5 +local isStudent = true + +print("Name: " + name) +print("Age: " + age) +print("Height: " + height) +print("Student: " + isStudent) + +# 複数変数の同時宣言・初期化 +local x = 10, y = 20, z = 30 +print("Sum: " + (x + y + z)) # 60 + +# 混合宣言(初期化あり・なし) +local initialized = 42, uninitialized, another = "test" +uninitialized = "assigned later" +print("Values: " + initialized + ", " + uninitialized + ", " + another) +``` + +### **Step 2: 演算子の使用** +```nyash +local a = 10 +local b = 3 + +# 算術演算子 +print("Addition: " + (a + b)) # 13 +print("Subtraction: " + (a - b)) # 7 +print("Multiplication: " + (a * b)) # 30 +print("Division: " + (a / b)) # 3.3333333333333335 + +# 論理演算子(自然言語ライク) +local hasPermission = true +local isLoggedIn = true +local canAccess = hasPermission and isLoggedIn +print("Can access: " + canAccess) # true + +local isDenied = not canAccess +print("Is denied: " + isDenied) # false + +# 比較演算子 +print("a > b: " + (a > b)) # true +print("a == b: " + (a == b)) # false +``` + +### **Step 3: 制御構造** +```nyash +function testControlFlow() { + local score = 85 + + # if文 + if score >= 90 { + print("Grade: A") + } else if score >= 80 { + print("Grade: B") # これが実行される + } else { + print("Grade: C or below") + } + + # ループ(統一構文) + local count = 0 + loop(count < 3) { + print("Count: " + count) + count = count + 1 + if count == 2 { + print("Breaking at 2") + break + } + } +} + +testControlFlow() +``` + +### **Step 4: Box(クラス)の定義** +```nyash +box Person { + init { name, age, email } # フィールド定義(カンマ必須!) + + # コンストラクタ(引数サポート) + Person(n, a, e) { + me.name = n + me.age = a + me.email = e + print("Person created: " + me.name) + } + + # メソッド + introduce() { + print("Hi, I'm " + me.name + ", age " + me.age) + } + + getInfo() { + return me.name + " (" + me.age + ") - " + me.email + } + + # デストラクタ + fini() { + print("Person destroyed: " + me.name) + } +} + +# 使用例 +person = new Person("Bob", 30, "bob@example.com") +person.introduce() +print("Info: " + person.getInfo()) +``` + +## 🏭 実践例:Calculator アプリ + +完全なCalculatorアプリを実装: + +```nyash +# 📱 Calculator App - Nyash版 + +box Calculator { + init { history } + + Calculator() { + me.history = new ArrayBox() + print("🧮 Calculator initialized!") + } + + add(a, b) { + local result = a + b + me.addToHistory("ADD", a, b, result) + return result + } + + subtract(a, b) { + local result = a - b + me.addToHistory("SUB", a, b, result) + return result + } + + multiply(a, b) { + local result = a * b + me.addToHistory("MUL", a, b, result) + return result + } + + divide(a, b) { + if b == 0 { + print("❌ Error: Division by zero!") + return 0 + } + local result = a / b + me.addToHistory("DIV", a, b, result) + return result + } + + addToHistory(op, a, b, result) { + local record = op + ": " + a + " " + op + " " + b + " = " + result + me.history.push(record) + } + + showHistory() { + print("📊 Calculation History:") + local size = me.history.size() + local i = 0 + loop(i < size) { + print(" " + (i + 1) + ". " + me.history.get(i)) + i = i + 1 + } + } + + clear() { + me.history = new ArrayBox() + print("🧹 History cleared!") + } +} + +# ✨ Calculator使用例 +calc = new Calculator() + +print("=== Basic Operations ===") +print("10 + 5 = " + calc.add(10, 5)) +print("10 - 3 = " + calc.subtract(10, 3)) +print("4 * 7 = " + calc.multiply(4, 7)) +print("15 / 3 = " + calc.divide(15, 3)) +print("10 / 0 = " + calc.divide(10, 0)) # ゼロ除算エラーテスト + +print("") +calc.showHistory() + +print("") +print("=== Complex Calculations ===") +local complex1 = calc.add(calc.multiply(3, 4), calc.divide(20, 4)) +print("(3 * 4) + (20 / 4) = " + complex1) + +calc.showHistory() +``` + +## ⚡ 並行処理の実践 + +```nyash +# 🚀 Parallel Processing Example + +function heavyComputation(iterations) { + print("⚙️ Starting computation with " + iterations + " iterations...") + + local sum = 0 + local i = 0 + loop(i < iterations) { + sum = sum + (i * i) + i = i + 1 + + # 進捗表示(1000回毎) + if (i % 1000) == 0 { + print(" Progress: " + i + "/" + iterations) + } + } + + print("✅ Computation completed: " + sum) + return sum +} + +function parallelDemo() { + print("🚀 Starting parallel computations...") + + # 3つのタスクを並行実行 + future1 = nowait heavyComputation(5000) + future2 = nowait heavyComputation(3000) + future3 = nowait heavyComputation(4000) + + print("⏳ All tasks started. Waiting for results...") + + # 結果を待機して取得 + result1 = await future1 + result2 = await future2 + result3 = await future3 + + local total = result1 + result2 + result3 + print("🎉 All tasks completed!") + print("Total sum: " + total) + + return total +} + +# 実行 +parallelDemo() +``` + +## 🏗️ Static Box(名前空間)の活用 + +```nyash +# 🏗️ Utility Classes with Static Boxes + +static box MathUtils { + init { PI, E } + + static { + me.PI = 3.14159265359 + me.E = 2.71828182846 + } + + square(x) { + return x * x + } + + circleArea(radius) { + return me.PI * me.square(radius) + } + + power(base, exp) { + local result = 1 + local i = 0 + loop(i < exp) { + result = result * base + i = i + 1 + } + return result + } +} + +static box StringUtils { + init { EMPTY } + + static { + me.EMPTY = "" + } + + reverse(str) { + # 簡易的な実装例 + return "REVERSED:" + str + } + + isEmpty(str) { + return str == me.EMPTY + } +} + +# 使用例 +print("π = " + MathUtils.PI) +print("Circle area (r=5): " + MathUtils.circleArea(5)) +print("2^8 = " + MathUtils.power(2, 8)) + +print("Empty check: " + StringUtils.isEmpty("")) +print("Reverse: " + StringUtils.reverse("Hello")) +``` + +## 🐛 デバッグ機能の活用 + +```nyash +# 🐛 Debug Features Showcase + +box DebugExample { + init { data, counter } + + DebugExample() { + me.data = "example" + me.counter = 0 + } + + process() { + me.counter = me.counter + 1 + return "Processed #" + me.counter + } +} + +function debuggingDemo() { + # DebugBoxでトラッキング開始 + DEBUG = new DebugBox() + DEBUG.startTracking() + + print("🔍 Creating objects for debugging...") + + # オブジェクトを作成してトラッキング + obj1 = new DebugExample() + obj2 = new DebugExample() + + DEBUG.trackBox(obj1, "Primary Object") + DEBUG.trackBox(obj2, "Secondary Object") + + # 処理実行 + result1 = obj1.process() + result2 = obj2.process() + result3 = obj1.process() + + print("Results: " + result1 + ", " + result2 + ", " + result3) + + # デバッグレポート表示 + print("") + print("=== Memory Report ===") + print(DEBUG.memoryReport()) + + print("") + print("=== Full Debug Dump ===") + print(DEBUG.dumpAll()) + + # デバッグ情報をファイルに保存 + DEBUG.saveToFile("debug_output.txt") + print("🎉 Debug information saved to debug_output.txt") +} + +debuggingDemo() +``` + +## 📦 ファイル組織とモジュール + +### **プロジェクト構造** +``` +my_nyash_project/ +├── main.nyash # メインプログラム +├── utils/ +│ ├── math.nyash # 数学ユーティリティ +│ ├── string.nyash # 文字列ユーティリティ +│ └── debug.nyash # デバッグ関数 +└── models/ + ├── person.nyash # Personクラス + └── calculator.nyash # Calculatorクラス +``` + +### **main.nyash** +```nyash +# 📦 Module System Example + +include "utils/math.nyash" +include "utils/string.nyash" +include "models/person.nyash" +include "models/calculator.nyash" + +function main() { + print("🚀 Multi-module Nyash Application") + + # 各モジュールの機能を使用 + person = new Person("Alice", 25, "alice@example.com") + person.introduce() + + calc = new Calculator() + result = calc.add(10, 20) + print("Calculation result: " + result) +} + +main() +``` + +## 🎯 ベストプラクティス + +### **1. 変数命名** +```nyash +# ✅ Good +local userName = "alice" +local totalAmount = 1000 +local isComplete = true + +# ❌ Avoid +local x = "alice" +local amt = 1000 +local flag = true +``` + +### **2. Box設計** +```nyash +# ✅ Good: 明確な責任分離 +box UserAccount { + init { username, email, balance } + + UserAccount(u, e) { + me.username = u + me.email = e + me.balance = 0 + } + + deposit(amount) { + me.balance = me.balance + amount + } +} + +# ❌ Avoid: 責任の混在 +box EverythingBox { + # 多すぎる責任を持たせない +} +``` + +### **3. エラーハンドリング** +```nyash +function safeOperation(a, b) { + if b == 0 { + print("❌ Error: Division by zero") + return 0 + } + return a / b +} +``` + +### **4. パフォーマンス考慮** +```nyash +# ✅ 効率的:static box使用 +result = MathUtils.calculate(data) + +# ✅ 効率的:初期化付き宣言 +local result = heavyCalculation(), cache = new MapBox() + +# ⚠️ 注意:不要なオブジェクト生成を避ける +loop(i < 1000) { + # 毎回new しない設計を心がける +} +``` + +## 🚀 次のステップ + +### **学習順序** +1. ✅ **基本構文** - このガイドで完了 +2. **並行処理** - `test_async_*.nyash`を参考に +3. **Static Box応用** - ユーティリティクラス作成 +4. **デバッグ技法** - DebugBox完全活用 +5. **アプリケーション開発** - 実践的なプロジェクト + +### **サンプルプログラム** +```bash +# 実装済みサンプル +./target/debug/nyash test_local_init.nyash # 初期化付き変数 +./target/debug/nyash app_dice_rpg.nyash # RPGバトルゲーム +./target/debug/nyash app_statistics.nyash # 統計計算 +./target/debug/nyash test_async_parallel.nyash # 並行処理 +``` + +### **リファレンス** +- `docs/LANGUAGE_OVERVIEW_2025.md` - 言語全体概要 +- `docs/TECHNICAL_ARCHITECTURE_2025.md` - 技術仕様 +- `CLAUDE.md` - 開発者向け詳細情報 + +## 🎉 おめでとうございます! + +このガイドでNyashの主要機能を学習しました! + +**習得内容:** +- ✅ 基本構文(変数・演算子・制御構造) +- ✅ Box(クラス)定義とオブジェクト指向 +- ✅ 並行処理・非同期プログラミング +- ✅ Static Box・名前空間システム +- ✅ デバッグ機能・開発支援ツール +- ✅ 実践的なアプリケーション開発 + +**Nyashでプログラミングの新しい可能性を探究してください!** 🚀 + +--- +*Getting Started Guide v1.0* +*Everything is Box - Start Simple, Think Big* \ No newline at end of file diff --git a/docs/LANGUAGE_GUIDE.md b/docs/説明書/LANGUAGE_GUIDE.md similarity index 100% rename from docs/LANGUAGE_GUIDE.md rename to docs/説明書/LANGUAGE_GUIDE.md diff --git a/docs/説明書/LANGUAGE_OVERVIEW_2025.md b/docs/説明書/LANGUAGE_OVERVIEW_2025.md new file mode 100644 index 00000000..513b5a8f --- /dev/null +++ b/docs/説明書/LANGUAGE_OVERVIEW_2025.md @@ -0,0 +1,332 @@ +# 🚀 Nyash Programming Language - Complete Overview 2025 + +**最終更新: 2025年8月8日** + +## 📖 概要 + +Nyashは「Everything is Box」哲学に基づく革新的なプログラミング言語です。 +わずか数日の集中開発により、production-readyレベルの実用的プログラミング言語として完成しました。 + +## 🎯 核心哲学: "Everything is Box" + +```nyash +# すべてのデータがBoxとして統一的に表現される +number = 42 # IntegerBox +text = "hello" # StringBox +flag = true # BoolBox +array = new ArrayBox() # ArrayBox +debug = new DebugBox() # DebugBox +``` + +## ✅ 完全実装済み機能 (Production Ready) + +### 🔧 **言語基盤** +- **データ型**: StringBox, IntegerBox, BoolBox, ArrayBox, MapBox, NullBox +- **演算子**: `+`, `-`, `*`, `/`, `not`, `and`, `or`, `==`, `!=`, `<`, `>`, `<=`, `>=` +- **制御構文**: `if/else`, `loop(condition)`, `break` +- **変数宣言**: `local x`, `local x = value`, `outbox x = value` + +### 🎭 **オブジェクト指向** +```nyash +box MyClass { + init { name, value } + + MyClass(n, v) { # コンストラクタ引数サポート + me.name = n + me.value = v + } + + getValue() { + return me.value + } +} + +# 継承とインターフェース +box Child from Parent interface IComparable { + # 実装... +} +``` + +### ⚡ **並行処理・非同期** +```nyash +# 真の非同期実行(別スレッド) +future1 = nowait heavyComputation(50000) +future2 = nowait heavyComputation(30000) + +# await演算子で結果取得 +result1 = await future1 +result2 = await future2 +``` + +### 🏭 **Static Boxシステム** +```nyash +static box Math { + init { PI, E } + + static { + me.PI = 3.14159 + me.E = 2.71828 + } + + add(a, b) { return a + b } + multiply(a, b) { return a * b } +} + +# シングルトン・名前空間として動作 +result = Math.add(10, 20) # 30 +pi = Math.PI # 3.14159 +``` + +### 💾 **メモリ管理** +```nyash +box Resource { + init { handle } + + fini() { # デストラクタ + print("Resource cleaned up") + } +} + +# 自動メモリ管理 + 明示的解放 +resource = new Resource() +# スコープ終了時に自動的にfini()が呼ばれる +``` + +### 🧪 **デバッグシステム** +```nyash +DEBUG = new DebugBox() +DEBUG.startTracking() +DEBUG.trackBox(myObject, "重要オブジェクト") +print(DEBUG.memoryReport()) +DEBUG.saveToFile("debug.txt") +``` + +### 📦 **モジュールシステム** +```nyash +include "math_utils.nyash" # ファイルインクルード +include "graphics.nyash" # 機能の組み込み +``` + +## 🎮 実装済みアプリケーション + +### 1. **🎲 サイコロRPGバトルゲーム** +- ターン制戦闘システム +- クリティカルヒット・防御システム +- リアルタイムHPバー表示 +- DebugBox戦闘ログ統合 + +### 2. **📊 統計計算アプリケーション** +- 平均・分散・標準偏差計算 +- 三角関数・対数・指数関数 +- 数学的統計処理 + +### 3. **🧮 LISPインタープリター** +- S式パーサー +- ConsBox/SymbolBox実装 +- 動的評価エンジン +- メタプログラミング実証 + +### 4. **⚡ 並行処理デモ** +- マルチスレッド計算タスク +- 進捗表示による並行動作の可視化 +- await演算子による結果統合 + +## 🌟 技術的革新 + +### 1. **GlobalBox革命** +従来のスコープチェーン概念を廃止し、GlobalBox単一管理システムを実現: +- すべてのグローバル関数/変数がGlobalBoxで管理 +- `local`変数による一時的スコープ +- メモリ効率30%改善 + +### 2. **SharedState非同期アーキテクチャ** +```rust +pub struct SharedState { + global_box: Arc>, + box_declarations: Arc>>, + static_functions: Arc>>>, +} +``` + +### 3. **Everything is Box統一性** +- TypeBox: 型情報もBoxとして表現 +- MethodBox: 関数ポインタ・イベントハンドラー実現 +- DebugBox: デバッグ情報の統一管理 + +## 📋 構文仕様書 + +### **変数宣言** +```nyash +# 基本宣言 +local x, y, z + +# 初期化付き宣言(2025年8月8日実装完了) +local result = 10 + 20 +local name = "Hello" + " World" +local a = 100, b = 200, c = 300 + +# 混合宣言 +local init = 42, uninit, another = "test" + +# outbox変数(static関数内で所有権移転) +outbox product = new Item() +``` + +### **制御構文** +```nyash +# 条件分岐 +if condition { + # 処理 +} else { + # else処理 +} + +# ループ(統一構文) +loop(condition) { + # ループ本体 + if exitCondition { + break + } +} +``` + +### **演算子** +```nyash +# 算術演算子 +result = a + b - c * d / e + +# 論理演算子(キーワード版推奨) +canAccess = level >= 5 and hasKey +canEdit = isAdmin or (isModerator and hasPermission) +isInvalid = not (input and verified) + +# 比較演算子 +equal = (a == b) +different = (x != y) +greater = (score > threshold) +``` + +### **Box定義** +```nyash +box ClassName from ParentClass interface IInterface { + init { field1, field2, field3 } # カンマ必須! + + # コンストラクタ + ClassName(param1, param2) { + me.field1 = param1 + me.field2 = param2 + me.field3 = calculateDefault() + } + + # メソッド + methodName(params) { + return me.field1 + params + } + + # デストラクタ + fini() { + print("Cleanup: " + me.field1) + } +} +``` + +### **Static Box** +```nyash +static box UtilityClass { + init { CONSTANT1, CONSTANT2 } + + static { + me.CONSTANT1 = "value" + me.CONSTANT2 = 42 + } + + utilityMethod(param) { + return param * me.CONSTANT2 + } +} + +# 使用法 +result = UtilityClass.utilityMethod(10) +const = UtilityClass.CONSTANT1 +``` + +## 🚀 パフォーマンス特性 + +### **メモリ効率** +- GlobalBox統一管理によるメモリ使用量削減 +- 自動参照カウント + 明示的デストラクタ +- SharedState による効率的な並行処理 + +### **実行速度** +- 変数解決アルゴリズム簡素化 +- コンパイル済みRustベースの高速実行 +- 並行処理によるCPUリソース最大活用 + +### **開発効率** +- シンプルな構文による高い可読性 +- 包括的なDebugBox機能 +- "Everything is Box"による概念の統一性 + +## 🎯 言語の強み + +### 1. **学習コストの低さ** +- 統一された"Box"概念 +- 直感的なメソッド呼び出し +- 自然言語に近い論理演算子 + +### 2. **実用性** +- モダンな並行処理サポート +- 堅牢なメモリ管理 +- 実際のアプリケーション開発可能 + +### 3. **拡張性** +- モジュールシステム +- 継承・インターフェースサポート +- 外部ライブラリ統合準備完了 + +## 🔮 開発ロードマップ + +### **Phase 3: 高度機能拡張** +- ジェネリクス実行時特殊化完成 +- スレッドプール・タイムアウト機能 +- WebAssembly出力対応 + +### **Phase 4: エコシステム構築** +- GUI フレームワーク(WindowBox等) +- HTTP/ネットワークライブラリ +- ファイルI/O・データベースアクセス + +### **Phase 5: プロダクション対応** +- パッケージマネージャー +- IDE統合・Language Server +- デバッガー・プロファイラー + +## 📊 言語比較 + +| 機能 | Nyash | Python | JavaScript | Rust | +|------|-------|--------|------------|------| +| 学習コスト | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | +| 並行処理 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | +| メモリ安全性 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | +| 開発速度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | +| 実行速度 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | + +## 🎉 まとめ + +Nyashは「Everything is Box」哲学により、シンプルさと強力さを両立した革新的プログラミング言語として完成しました。 + +**主要達成項目:** +- ✅ 基本言語機能完備 +- ✅ オブジェクト指向完全サポート +- ✅ 並行処理・非同期機能実装 +- ✅ Static Box・名前空間システム +- ✅ 現代的構文(初期化付き変数宣言等) +- ✅ 実用アプリケーション複数完成 +- ✅ 包括的デバッグ・開発支援機能 + +**Nyashは実験的言語から実用的プログラミング言語への転換を果たし、今後のさらなる進化への強固な基盤を確立しました。** + +--- +*開発期間: 2025年8月6日-8日(わずか3日間での集中開発)* +*開発者: Claude Code + 人間のコラボレーション* +*哲学: "Everything is Box" - シンプルさの中に無限の可能性を* \ No newline at end of file diff --git a/docs/P2P_GUIDE.md b/docs/説明書/P2P_GUIDE.md similarity index 100% rename from docs/P2P_GUIDE.md rename to docs/説明書/P2P_GUIDE.md diff --git a/docs/説明書/README.md b/docs/説明書/README.md new file mode 100644 index 00000000..7f292b0d --- /dev/null +++ b/docs/説明書/README.md @@ -0,0 +1,23 @@ +Nyash 説明書(ユーザー向けガイド) + +- ネイティブビルド: docs/説明書/native-build/README.md +- WASM: docs/説明書/wasm/wasm_quick_start.md, docs/説明書/wasm/wasm_browser_plan.md +- 入門: docs/説明書/GETTING_STARTED.md, docs/説明書/GETTING_STARTED_2025.md +- 言語ガイド: docs/説明書/LANGUAGE_GUIDE.md, docs/説明書/LANGUAGE_OVERVIEW_2025.md +- コア概念: docs/nyash_core_concepts.md +- P2P: docs/説明書/P2P_GUIDE.md + +参考資料 (Reference): +- docs/説明書/reference/language-reference.md (仕様) +- docs/説明書/reference/finalization-system.md (fini/弱参照の不変) +- docs/説明書/reference/override-delegation-syntax.md (委譲構文) +- docs/説明書/reference/builtin-boxes.md (ビルトイン一覧) +- docs/説明書/reference/p2p_spec.md (P2P仕様) +- docs/説明書/reference/language-specification/ (詳細仕様) + +その他ガイド: +- docs/説明書/guides/1_getting_started.md +- docs/説明書/guides/2_language_guide.md +- docs/説明書/guides/playground_guide.md + +ネイティブ計画・相談ログ: docs/予定/native-plan/README.md diff --git a/docs/説明書/guides/1_getting_started.md b/docs/説明書/guides/1_getting_started.md new file mode 100644 index 00000000..61df6ac6 --- /dev/null +++ b/docs/説明書/guides/1_getting_started.md @@ -0,0 +1,547 @@ +# 🚀 Getting Started with Nyash - Practical Guide + +**最終更新: 2025年8月8日** + +## 🎯 5分でNyashを理解する + +Nyashは「Everything is Box」哲学に基づく、シンプルで強力なプログラミング言語です。 +このガイドでは、実際にコードを書きながらNyashの機能を学んでいきます。 + +## ⚡ クイックスタート + +### **1. 環境構築** +```bash +# リポジトリのクローン +git clone [repository-url] +cd nyash/nyash-rust + +# ビルド +cargo build + +# 実行 +./target/debug/nyash your_program.nyash +``` + +### **2. はじめてのNyashプログラム** +`hello.nyash`を作成: +```nyash +print("Hello, Nyash World!") +print("Everything is Box! 🎉") +``` + +実行: +```bash +./target/debug/nyash hello.nyash +``` + +出力: +``` +Hello, Nyash World! +Everything is Box! 🎉 +``` + +## 📚 基本構文チュートリアル + +### **Step 1: 変数と初期化** +```nyash +# 🎯 新機能:初期化付き変数宣言 +local name = "Alice" +local age = 25 +local height = 165.5 +local isStudent = true + +print("Name: " + name) +print("Age: " + age) +print("Height: " + height) +print("Student: " + isStudent) + +# 複数変数の同時宣言・初期化 +local x = 10, y = 20, z = 30 +print("Sum: " + (x + y + z)) # 60 + +# 混合宣言(初期化あり・なし) +local initialized = 42, uninitialized, another = "test" +uninitialized = "assigned later" +print("Values: " + initialized + ", " + uninitialized + ", " + another) +``` + +### **Step 2: 演算子の使用** +```nyash +local a = 10 +local b = 3 + +# 算術演算子 +print("Addition: " + (a + b)) # 13 +print("Subtraction: " + (a - b)) # 7 +print("Multiplication: " + (a * b)) # 30 +print("Division: " + (a / b)) # 3.3333333333333335 + +# 論理演算子(自然言語ライク) +local hasPermission = true +local isLoggedIn = true +local canAccess = hasPermission and isLoggedIn +print("Can access: " + canAccess) # true + +local isDenied = not canAccess +print("Is denied: " + isDenied) # false + +# 比較演算子 +print("a > b: " + (a > b)) # true +print("a == b: " + (a == b)) # false +``` + +### **Step 3: 制御構造** +```nyash +function testControlFlow() { + local score = 85 + + # if文 + if score >= 90 { + print("Grade: A") + } else if score >= 80 { + print("Grade: B") # これが実行される + } else { + print("Grade: C or below") + } + + # ループ(統一構文) + local count = 0 + loop(count < 3) { + print("Count: " + count) + count = count + 1 + if count == 2 { + print("Breaking at 2") + break + } + } +} + +testControlFlow() +``` + +### **Step 4: Box(クラス)の定義** +```nyash +box Person { + init { name, age, email } # フィールド定義(カンマ必須!) + + # コンストラクタ(引数サポート) + Person(n, a, e) { + me.name = n + me.age = a + me.email = e + print("Person created: " + me.name) + } + + # メソッド + introduce() { + print("Hi, I'm " + me.name + ", age " + me.age) + } + + getInfo() { + return me.name + " (" + me.age + ") - " + me.email + } + + # デストラクタ + fini() { + print("Person destroyed: " + me.name) + } +} + +# 使用例 +person = new Person("Bob", 30, "bob@example.com") +person.introduce() +print("Info: " + person.getInfo()) +``` + +## 🏭 実践例:Calculator アプリ + +完全なCalculatorアプリを実装: + +```nyash +# 📱 Calculator App - Nyash版 + +box Calculator { + init { history } + + Calculator() { + me.history = new ArrayBox() + print("🧮 Calculator initialized!") + } + + add(a, b) { + local result = a + b + me.addToHistory("ADD", a, b, result) + return result + } + + subtract(a, b) { + local result = a - b + me.addToHistory("SUB", a, b, result) + return result + } + + multiply(a, b) { + local result = a * b + me.addToHistory("MUL", a, b, result) + return result + } + + divide(a, b) { + if b == 0 { + print("❌ Error: Division by zero!") + return 0 + } + local result = a / b + me.addToHistory("DIV", a, b, result) + return result + } + + addToHistory(op, a, b, result) { + local record = op + ": " + a + " " + op + " " + b + " = " + result + me.history.push(record) + } + + showHistory() { + print("📊 Calculation History:") + local size = me.history.size() + local i = 0 + loop(i < size) { + print(" " + (i + 1) + ". " + me.history.get(i)) + i = i + 1 + } + } + + clear() { + me.history = new ArrayBox() + print("🧹 History cleared!") + } +} + +# ✨ Calculator使用例 +calc = new Calculator() + +print("=== Basic Operations ===") +print("10 + 5 = " + calc.add(10, 5)) +print("10 - 3 = " + calc.subtract(10, 3)) +print("4 * 7 = " + calc.multiply(4, 7)) +print("15 / 3 = " + calc.divide(15, 3)) +print("10 / 0 = " + calc.divide(10, 0)) # ゼロ除算エラーテスト + +print("") +calc.showHistory() + +print("") +print("=== Complex Calculations ===") +local complex1 = calc.add(calc.multiply(3, 4), calc.divide(20, 4)) +print("(3 * 4) + (20 / 4) = " + complex1) + +calc.showHistory() +``` + +## ⚡ 並行処理の実践 + +```nyash +# 🚀 Parallel Processing Example + +function heavyComputation(iterations) { + print("⚙️ Starting computation with " + iterations + " iterations...") + + local sum = 0 + local i = 0 + loop(i < iterations) { + sum = sum + (i * i) + i = i + 1 + + # 進捗表示(1000回毎) + if (i % 1000) == 0 { + print(" Progress: " + i + "/" + iterations) + } + } + + print("✅ Computation completed: " + sum) + return sum +} + +function parallelDemo() { + print("🚀 Starting parallel computations...") + + # 3つのタスクを並行実行 + future1 = nowait heavyComputation(5000) + future2 = nowait heavyComputation(3000) + future3 = nowait heavyComputation(4000) + + print("⏳ All tasks started. Waiting for results...") + + # 結果を待機して取得 + result1 = await future1 + result2 = await future2 + result3 = await future3 + + local total = result1 + result2 + result3 + print("🎉 All tasks completed!") + print("Total sum: " + total) + + return total +} + +# 実行 +parallelDemo() +``` + +## 🏗️ Static Box(名前空間)の活用 + +```nyash +# 🏗️ Utility Classes with Static Boxes + +static box MathUtils { + init { PI, E } + + static { + me.PI = 3.14159265359 + me.E = 2.71828182846 + } + + square(x) { + return x * x + } + + circleArea(radius) { + return me.PI * me.square(radius) + } + + power(base, exp) { + local result = 1 + local i = 0 + loop(i < exp) { + result = result * base + i = i + 1 + } + return result + } +} + +static box StringUtils { + init { EMPTY } + + static { + me.EMPTY = "" + } + + reverse(str) { + # 簡易的な実装例 + return "REVERSED:" + str + } + + isEmpty(str) { + return str == me.EMPTY + } +} + +# 使用例 +print("π = " + MathUtils.PI) +print("Circle area (r=5): " + MathUtils.circleArea(5)) +print("2^8 = " + MathUtils.power(2, 8)) + +print("Empty check: " + StringUtils.isEmpty("")) +print("Reverse: " + StringUtils.reverse("Hello")) +``` + +## 🐛 デバッグ機能の活用 + +```nyash +# 🐛 Debug Features Showcase + +box DebugExample { + init { data, counter } + + DebugExample() { + me.data = "example" + me.counter = 0 + } + + process() { + me.counter = me.counter + 1 + return "Processed #" + me.counter + } +} + +function debuggingDemo() { + # DebugBoxでトラッキング開始 + DEBUG = new DebugBox() + DEBUG.startTracking() + + print("🔍 Creating objects for debugging...") + + # オブジェクトを作成してトラッキング + obj1 = new DebugExample() + obj2 = new DebugExample() + + DEBUG.trackBox(obj1, "Primary Object") + DEBUG.trackBox(obj2, "Secondary Object") + + # 処理実行 + result1 = obj1.process() + result2 = obj2.process() + result3 = obj1.process() + + print("Results: " + result1 + ", " + result2 + ", " + result3) + + # デバッグレポート表示 + print("") + print("=== Memory Report ===") + print(DEBUG.memoryReport()) + + print("") + print("=== Full Debug Dump ===") + print(DEBUG.dumpAll()) + + # デバッグ情報をファイルに保存 + DEBUG.saveToFile("debug_output.txt") + print("🎉 Debug information saved to debug_output.txt") +} + +debuggingDemo() +``` + +## 📦 ファイル組織とモジュール + +### **プロジェクト構造** +``` +my_nyash_project/ +├── main.nyash # メインプログラム +├── utils/ +│ ├── math.nyash # 数学ユーティリティ +│ ├── string.nyash # 文字列ユーティリティ +│ └── debug.nyash # デバッグ関数 +└── models/ + ├── person.nyash # Personクラス + └── calculator.nyash # Calculatorクラス +``` + +### **main.nyash** +```nyash +# 📦 Module System Example + +include "utils/math.nyash" +include "utils/string.nyash" +include "models/person.nyash" +include "models/calculator.nyash" + +function main() { + print("🚀 Multi-module Nyash Application") + + # 各モジュールの機能を使用 + person = new Person("Alice", 25, "alice@example.com") + person.introduce() + + calc = new Calculator() + result = calc.add(10, 20) + print("Calculation result: " + result) +} + +main() +``` + +## 🎯 ベストプラクティス + +### **1. 変数命名** +```nyash +# ✅ Good +local userName = "alice" +local totalAmount = 1000 +local isComplete = true + +# ❌ Avoid +local x = "alice" +local amt = 1000 +local flag = true +``` + +### **2. Box設計** +```nyash +# ✅ Good: 明確な責任分離 +box UserAccount { + init { username, email, balance } + + UserAccount(u, e) { + me.username = u + me.email = e + me.balance = 0 + } + + deposit(amount) { + me.balance = me.balance + amount + } +} + +# ❌ Avoid: 責任の混在 +box EverythingBox { + # 多すぎる責任を持たせない +} +``` + +### **3. エラーハンドリング** +```nyash +function safeOperation(a, b) { + if b == 0 { + print("❌ Error: Division by zero") + return 0 + } + return a / b +} +``` + +### **4. パフォーマンス考慮** +```nyash +# ✅ 効率的:static box使用 +result = MathUtils.calculate(data) + +# ✅ 効率的:初期化付き宣言 +local result = heavyCalculation(), cache = new MapBox() + +# ⚠️ 注意:不要なオブジェクト生成を避ける +loop(i < 1000) { + # 毎回new しない設計を心がける +} +``` + +## 🚀 次のステップ + +### **学習順序** +1. ✅ **基本構文** - このガイドで完了 +2. **並行処理** - `test_async_*.nyash`を参考に +3. **Static Box応用** - ユーティリティクラス作成 +4. **デバッグ技法** - DebugBox完全活用 +5. **アプリケーション開発** - 実践的なプロジェクト + +### **サンプルプログラム** +```bash +# 実装済みサンプル +./target/debug/nyash test_local_init.nyash # 初期化付き変数 +./target/debug/nyash app_dice_rpg.nyash # RPGバトルゲーム +./target/debug/nyash app_statistics.nyash # 統計計算 +./target/debug/nyash test_async_parallel.nyash # 並行処理 +``` + +### **リファレンス** +- `docs/LANGUAGE_OVERVIEW_2025.md` - 言語全体概要 +- `docs/TECHNICAL_ARCHITECTURE_2025.md` - 技術仕様 +- `CLAUDE.md` - 開発者向け詳細情報 + +## 🎉 おめでとうございます! + +このガイドでNyashの主要機能を学習しました! + +**習得内容:** +- ✅ 基本構文(変数・演算子・制御構造) +- ✅ Box(クラス)定義とオブジェクト指向 +- ✅ 並行処理・非同期プログラミング +- ✅ Static Box・名前空間システム +- ✅ デバッグ機能・開発支援ツール +- ✅ 実践的なアプリケーション開発 + +**Nyashでプログラミングの新しい可能性を探究してください!** 🚀 + +--- +*Getting Started Guide v1.0* +*Everything is Box - Start Simple, Think Big* \ No newline at end of file diff --git a/docs/説明書/guides/2_language_guide.md b/docs/説明書/guides/2_language_guide.md new file mode 100644 index 00000000..437c08f5 --- /dev/null +++ b/docs/説明書/guides/2_language_guide.md @@ -0,0 +1,254 @@ +# 📚 Nyash Programming Language - 完全ガイド + +**最終更新: 2025年8月12日 - Phase 1完了, P2P実装準備完了** + +## 📖 概要 + +Nyashは「Everything is Box」哲学に基づく革新的なプログラミング言語です。 +Rust製インタープリターによる高性能実行と、直感的な構文により、学習しやすく実用的な言語として完成しました。 + +## 🎯 核心哲学: "Everything is Box" + +```nyash +# すべてのデータがBoxとして統一的に表現される +number = 42 # IntegerBox +text = "hello" # StringBox +flag = true # BoolBox +array = new ArrayBox() # ArrayBox +debug = new DebugBox() # DebugBox +``` + +**重要な利点:** +- **統一性**: すべてのデータが共通インターフェース +- **メモリ安全性**: Arcパターンで完全スレッドセーフ +- **拡張性**: 新しいBox型を容易に追加可能 + +--- + +## 🔤 言語構文リファレンス + +### 🏷️ **変数宣言・スコープ** + +```nyash +// ローカル変数宣言 +local x, y +local name = "Alice" + +// 所有権移転変数(関数戻り値用) +outbox result = compute() + +// グローバル変数 +global CONFIG = "dev" +``` + +### 🧮 **演算子** + +```nyash +// 算術演算子 +a + b, a - b, a * b, a / b + +// 比較演算子 +a == b, a != b, a < b, a > b, a <= b, a >= b + +// 論理演算子 +not condition, a and b, a or b + +// Cross-type演算 (Phase 1で完全実装) +10 + 3.14 // → 13.14 (型変換) +"Value: " + 42 // → "Value: 42" (文字列連結) +``` + +### 🏗️ **Box定義・デリゲーション** + +#### 基本Box定義 +```nyash +box User { + init { name, email } // フィールド宣言 + + pack(userName, userEmail) { // 🎁 Box哲学の具現化! + me.name = userName + me.email = userEmail + } + + greet() { + print("Hello, " + me.name) + } +} +``` + +#### デリゲーション (2025-08 革命) +```nyash +box AdminUser from User { // 🔥 from構文でデリゲーション + init { permissions } + + pack(adminName, adminEmail, perms) { + from User.pack(adminName, adminEmail) // 親のpack呼び出し + me.permissions = perms + } + + override greet() { // 明示的オーバーライド + from User.greet() // 親メソッド呼び出し + print("Admin privileges: " + me.permissions) + } +} +``` + +#### Static Box Main パターン +```nyash +static box Main { + init { console, result } + + main() { + me.console = new ConsoleBox() + me.console.log("🎉 Everything is Box!") + return "Success!" + } +} +``` + +### 🔄 **制御構造** + +```nyash +// 条件分岐 +if condition { + // 処理 +} else { + // 別処理 +} + +// ループ(唯一の正しい形式) +loop(condition) { + // 処理 + if breakCondition { + break + } +} +``` + +--- + +## 📦 ビルトインBox型 + +### 基本型 +- **StringBox**: 文字列 (`"hello"`) +- **IntegerBox**: 整数 (`42`) +- **FloatBox**: 浮動小数点数 (`new FloatBox(3.14)`) ✅ Phase 1完了 +- **BoolBox**: 真偽値 (`true`, `false`) +- **NullBox**: NULL値 (`null`) + +### データ構造 +- **ArrayBox**: 配列 (`new ArrayBox()`) ✅ Phase 1で sort/reverse/indexOf/slice 実装 +- **MapBox**: 連想配列 (`new MapBox()`) + +### ユーティリティ +- **ConsoleBox**: コンソール出力 (`new ConsoleBox()`) +- **DebugBox**: デバッグ機能 (`new DebugBox()`) +- **MathBox**: 数学関数 (`new MathBox()`) +- **TimeBox**: 時刻処理 (`new TimeBox()`) +- **DateTimeBox**: 日時処理 (`new DateTimeBox()`) ✅ Phase 1で完全動作 + +### 高度機能 +- **RandomBox**: 乱数生成 +- **BufferBox**: バッファ操作 +- **RegexBox**: 正規表現 +- **JSONBox**: JSON処理 +- **StreamBox**: ストリーム処理 + +### P2P通信 (Phase 2実装中) +- **IntentBox**: 構造化メッセージ (実装予定) +- **P2PBox**: P2P通信ノード (実装予定) + +--- + +## 🚀 実用例 + +### データ処理例 +```nyash +// 配列操作 +local numbers = new ArrayBox() +numbers.push(3) +numbers.push(1) +numbers.push(2) +numbers.sort() // [1, 2, 3] + +// 型変換・演算 +local result = 10 + new FloatBox(3.14) // 13.14 +print("Result: " + result.toString()) +``` + +### P2P通信例 (将来実装) +```nyash +// P2Pノード作成 +local node_a = new P2PBox("alice", transport: "inprocess") +local node_b = new P2PBox("bob", transport: "inprocess") + +// メッセージ受信ハンドラ +node_b.on("chat.message", function(intent, from) { + print("From " + from + ": " + intent.payload.text) +}) + +// 構造化メッセージ送信 +local msg = new IntentBox("chat.message", { text: "Hello P2P!" }) +node_a.send("bob", msg) // → "From alice: Hello P2P!" +``` + +--- + +## ⚠️ 重要な注意点 + +### 必須のコンマ +```nyash +// ✅ 正しい +init { field1, field2 } + +// ❌ 間違い(CPU暴走の原因) +init { field1 field2 } +``` + +### 変数宣言厳密化 +```nyash +// ✅ 明示宣言必須 +local x +x = 42 + +// ❌ 未宣言変数への代入はエラー +y = 42 // Runtime Error + 修正提案 +``` + +### ループ構文統一 +```nyash +// ✅ 唯一の正しい形式 +loop(condition) { } + +// ❌ 削除済み構文 +while condition { } // 使用不可 +``` + +--- + +## 📈 実装状況 (2025-08-12) + +### ✅ Phase 1完了 +- FloatBox toString() メソッド +- ArrayBox 改良 (sort/reverse/indexOf/slice) +- Cross-type演算子システム +- 包括的テストスイート (188行) + +### 🚧 Phase 2実装中 +- IntentBox (構造化メッセージ) +- MessageBus (プロセス内シングルトン) +- P2PBox (P2P通信ノード) + +### 📋 将来予定 +- WebSocket/WebRTC通信 +- 非同期処理 (async/await) +- 追加のBox型拡張 + +--- + +**🎉 Nyashで「Everything is Box」の世界を体験しよう!** + +📚 **関連ドキュメント:** +- [Getting Started](GETTING_STARTED.md) - 環境構築・最初の一歩 +- [P2P Guide](P2P_GUIDE.md) - P2P通信システム完全ガイド +- [Built-in Boxes](reference/builtin-boxes.md) - ビルトインBox詳細リファレンス \ No newline at end of file diff --git a/docs/説明書/guides/playground_guide.md b/docs/説明書/guides/playground_guide.md new file mode 100644 index 00000000..52e6e0af --- /dev/null +++ b/docs/説明書/guides/playground_guide.md @@ -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あり版」を並記 + diff --git a/docs/reference/builtin-boxes.md b/docs/説明書/reference/builtin-boxes.md similarity index 100% rename from docs/reference/builtin-boxes.md rename to docs/説明書/reference/builtin-boxes.md diff --git a/docs/説明書/reference/design-philosophy.md b/docs/説明書/reference/design-philosophy.md new file mode 100644 index 00000000..02c76cd4 --- /dev/null +++ b/docs/説明書/reference/design-philosophy.md @@ -0,0 +1,337 @@ +# 🌟 明示的デリゲーション革命:なぜNyashは世界初の完全明示デリゲーション言語になったのか + +作成日: 2025年8月11日 +著者: Nyashプロジェクトチーム +ステータス: 設計思想決定版 + +## 📜 はじめに:革命の始まり + +2025年8月11日、Nyashプログラミング言語の開発において、言語設計史上最大級の発見がありました。それは、**暗黙のオーバーライド問題**の発見と、それを解決する**完全明示デリゲーション構文**の誕生です。 + +この文書は、なぜこの革命が必要だったのか、どのような思想の元に設計されたのかを詳しく解説します。 + +## 🚨 問題の発見:暗黙の悪魔 + +### HashMap::insert による意図しない上書き + +Nyashの実装を詳しく調査した結果、恐ろしい問題が発見されました: + +```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哲学との根本的矛盾 + +この問題は、Nyashの3つの核心哲学と完全に矛盾していました: + +1. **明示性重視**: 「何が起きているかを隠さない」 +2. **Everything is Box**: 「統一された世界観」 +3. **初学者フレンドリー**: 「複雑な概念を分かりやすく表現」 + +暗黙のオーバーライドは、これらすべてを破壊する**言語設計上の致命的欠陥**だったのです。 + +## 💡 解決への道:3AI大会議 + +### AI専門家による徹底分析 + +この問題の解決策を求めて、言語設計の専門家であるGeminiとChatGPTに相談を行いました。結果は予想を上回る**圧倒的な支持**でした。 + +#### Gemini先生の評価 +> **「全面的に賛成します」** +> **「極めて重要な一歩」** +> **「Nyashのアイデンティティを確立する」** + +#### ChatGPT先生の評価 +> **「強く整合する」** +> **「安全性と読みやすさを大幅に向上」** +> **「実装工数3-5日程度」** + +### 専門的視点からの裏付け + +両専門家から以下の重要な指摘がありました: + +1. **哲学的整合性**: Nyashの明示性哲学と完全に合致 +2. **技術的優位性**: 他言語の問題(Python MRO、Java super等)を根本解決 +3. **学習効果**: 初学者にとってより理解しやすい設計 +4. **実装可能性**: 技術的に十分実現可能 + +## 🌟 革命的解決策:Override + From 統一構文 + +### 4つの統一原則 + +この問題を解決するため、以下の4つの統一原則を確立しました: + +#### 1. 宣言の統一 +```nyash +box Child from Parent // デリゲーション関係の明示 +``` + +#### 2. 置換の統一 +```nyash +override methodName() // オーバーライドの明示宣言 +``` + +#### 3. 呼び出しの統一 +```nyash +from Parent.methodName() // 親実装の明示呼び出し +``` + +#### 4. 構築の統一 +```nyash +from Parent.init() // コンストラクタも同じ構文 +``` + +### 完全な例 + +```nyash +box MeshNode : P2PBox { + init routing = RoutingTable() + + constructor(nodeId, world) { + from P2PBox.constructor(nodeId, world) // 統一構文 + me.routing = RoutingTable() + } + + override send(intent, data, target) { // 明示的置換 + me.routing.log(target) + from P2PBox.send(intent, data, target) // 明示的呼び出し + } +} +``` + +## 🔥 革命的特徴 + +### 1. 完全な明示性 + +**従来の問題**: +- 何がオーバーライドされているかわからない +- 親のどのメソッドを呼んでいるかわからない +- 実行順序が不明確 + +**Nyashの解決**: +- `override` で置換を明示宣言 +- `from Parent.method()` で呼び出し先を完全明示 +- 上から下への直感的な実行順序 + +### 2. 曖昧性の完全排除 + +**多重デリゲーション時の曖昧性解消**: +```nyash +box SmartNode : P2PBox, Logger { + override send(intent, data, target) { + from Logger.debug("Sending: " + intent) // どのLoggerか明確 + from P2PBox.send(intent, data, target) // どのP2PBoxか明確 + } +} + +// 競合時は更に明示的に +box ConflictNode from ParentA, ParentB { + override ParentA.process(data) { // ParentAのprocessを置換 + from ParentA.process(data) + } + + override ParentB.process(data) { // ParentBのprocessを置換 + from ParentB.process(data) + } +} +``` + +### 3. 学習コストの最小化 + +**覚えるべきルール**: +1. 親のメソッドを置換したい → `override` +2. 親のメソッドを呼びたい → `from Parent.method()` +3. 親のコンストラクタを呼びたい → `from Parent.init()` + +たった3つのルールで、すべてのデリゲーション操作が表現できます。 + +## 🌍 他言語との比較:なぜNyashが優れているのか + +### Python の問題 +```python +# MRO(Method Resolution Order)地獄 +class C(A, B): + def method(self): + super().method() # どっちのmethod? +``` + +**Nyash の解決**: +```nyash +box C : A, B { + override method() { + from A.method() // Aのmethodと明示 + from B.method() // Bのmethodと明示 + } +} +``` + +### Java/C# の問題 +```java +// どの親のmethodを呼んでいるかコードから不明 +@Override +public void method() { + super.method(); // 単一継承でも曖昧 +} +``` + +**Nyash の解決**: +```nyash +override method() { + from Parent.method() // どのParentか完全に明確 +} +``` + +### TypeScript の問題 +```typescript +// 暗黙のオーバーライドによる事故 +class Child extends Parent { + method() { // うっかり同名メソッド → 意図しない上書き + // ... + } +} +``` + +**Nyash の解決**: +```nyash +// overrideなしで同名メソッド → コンパイルエラー +// 意図しない上書きは100%防止 +``` + +## 🎯 設計思想の深層 + +### Everything is Box との統合 + +この革命は、Nyashの根本思想「Everything is Box」と完全に統合されています: + +- **Box同士のデリゲーション**: 階層ではなく、協力関係 +- **Boxメソッドの明示的管理**: どのBoxのどのメソッドかが常に明確 +- **Box構築の明示的制御**: コンストラクタも普通のメソッド + +### 明示性の哲学 + +Nyashが目指すのは、**「魔法のない言語」**です: + +- 隠れた処理は一切なし +- すべての動作がコードに現れる +- 初学者でも上級者でも同じように理解できる + +### 初学者への配慮 + +複雑な概念を、シンプルな文法で表現: + +- `override` = 「置き換えます」 +- `from Parent.method()` = 「親の方法を使います」 +- コンパイルエラー = 「間違いを素早く教える」 + +## 🚀 実装戦略 + +### 段階的導入 + +ChatGPT先生の提案による実装ロードマップ: + +**Phase 1(0.5-1日)**: +- `override` キーワード追加 +- 基本パーサー拡張 + +**Phase 2(1-2日)**: +- 暗黙オーバーライド検出 +- コンストラクタ重複禁止 + +**Phase 3(1日)**: +- `from Parent.init()` 実装 +- エラーメッセージ改善 + +### 移行支援 + +既存コードの安全な移行: +- 段階的警告システム +- 自動修正支援ツール +- 詳細な移行ガイド + +## 🌟 期待される効果 + +### 1. 開発者体験の革命的向上 + +**Before(暗黙オーバーライド)**: +- バグの発見が困難 +- 意図しない動作 +- デバッグに多大な時間 + +**After(明示的オーバーライド)**: +- コンパイル時に間違いを検出 +- 意図が明確に表現される +- デバッグ時間の劇的短縮 + +### 2. コードの可読性向上 + +**Before**: +```nyash +// これは何をオーバーライドしている? +send(msg) { + // 親を呼んでる?呼んでない? + processMessage(msg) +} +``` + +**After**: +```nyash +// P2PBoxのsendを明示的にオーバーライド +override send(msg) { + processMessage(msg) + from P2PBox.send(msg) // P2PBoxの実装も使用 +} +``` + +### 3. 保守性の向上 + +- 変更の影響範囲が明確 +- リファクタリングが安全 +- チーム開発での誤解を防止 + +## 🏆 結論:言語設計史に残る革命 + +この明示的デリゲーション革命により、Nyashは以下を達成しました: + +### 世界初の完全明示デリゲーション言語 + +1. **完全な明示性**: すべての動作を明示 +2. **曖昧性の完全排除**: どんな複雑なケースも明確 +3. **統一構文**: デリゲーションとオーバーライドの完全統合 +4. **初学者フレンドリー**: 学習しやすく、間違いにくい + +### プログラミング言語設計への貢献 + +- **暗黙の悪魔**からの完全な解放 +- **多重デリゲーション**の安全で明確な実現 +- **コード可読性**の新しい基準の確立 + +### 未来への影響 + +Nyashのこの革命は、今後のプログラミング言語設計に大きな影響を与えるでしょう。「暗黙より明示」という哲学が、ついに技術的に完全実現されたのです。 + +--- + +**2025年8月11日は、プログラミング言語史において「明示的デリゲーション革命の日」として記憶されることでしょう。** 🎊 + +この革命により、Nyashは単なるプログラミング言語を超えて、**新しいプログラミングパラダイムの先駆者**となりました。 + +Everything is Box. Everything is Explicit. Everything is Beautiful. 🌟 \ No newline at end of file diff --git a/docs/reference/finalization-system.md b/docs/説明書/reference/finalization-system.md similarity index 100% rename from docs/reference/finalization-system.md rename to docs/説明書/reference/finalization-system.md diff --git a/docs/reference/language-reference.md b/docs/説明書/reference/language-reference.md similarity index 100% rename from docs/reference/language-reference.md rename to docs/説明書/reference/language-reference.md diff --git a/docs/language-specification/override-delegation-syntax.md b/docs/説明書/reference/language-specification/override-delegation-syntax.md similarity index 100% rename from docs/language-specification/override-delegation-syntax.md rename to docs/説明書/reference/language-specification/override-delegation-syntax.md diff --git a/docs/説明書/reference/language_spec.md b/docs/説明書/reference/language_spec.md new file mode 100644 index 00000000..3687a359 --- /dev/null +++ b/docs/説明書/reference/language_spec.md @@ -0,0 +1,525 @@ +# 🚀 Nyash Language Reference 2025 + +**最終更新: 2025年8月11日 - デリゲーション革命完了!`from`統一構文+`init`構文決定!** + +## 📖 概要 + +Nyashは「Everything is Box」哲学に基づく革新的プログラミング言語です。 +Rust製インタープリターによる高性能実行と、直感的な構文により、学習しやすく実用的な言語として完成しました。 + +--- + +## 🔤 **1. 予約語・キーワード完全リスト** + +### **コア言語** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `box` | クラス定義 | `box MyClass { }` | +| `static` | 静的Box・関数定義 | `static box Main { }` | +| `interface` | インターフェース定義 | `interface Comparable { }` | +| `from` | デリゲーション指定 | `box Child from Parent { }` | +| `new` | オブジェクト生成 | `new ConsoleBox()` | +| `me`/`this` | 自己参照 | `me.field = value` | + +### **変数・スコープ** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `local` | ローカル変数宣言 | `local x, y = 10` | +| `outbox` | 所有権移転変数 | `outbox result = compute()` | +| `global` | グローバル変数 | `global CONFIG = "dev"` | +| `init` | フィールド初期化ブロック | `init { name, age }` | + +### **制御構文** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `if` | 条件分岐 | `if condition { }` | +| `else` | else節 | `else { }` | +| `loop` | ループ(唯一の形式) | `loop(condition) { }` | +| `break` | ループ脱出 | `break` | +| `return` | 関数リターン | `return value` | + +### **論理・演算** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `not` | 論理否定 | `not condition` | +| `and` | 論理積 | `a and b` | +| `or` | 論理和 | `a or b` | +| `true`/`false` | 真偽値 | `flag = true` | + +### **非同期・並行** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `nowait` | 非同期実行 | `nowait future = task()` | +| `await` | 待機・結果取得 | `result = await future` | + +### **例外処理** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `try` | 例外捕獲開始 | `try { }` | +| `catch` | 例外処理 | `catch (e) { }` | +| `finally` | 最終処理 | `finally { }` | +| `throw` | 例外発生 | `throw error` | + +### **その他** +| 予約語 | 用途 | 例 | +|-------|------|---| +| `function` | 関数定義 | `function add(a,b) { }` | +| `print` | 出力 | `print("Hello")` | +| `include` | ファイル取り込み | `include "math.nyash"` | + +--- + +## 📝 **2. 文法・構文仕様** + +### **2.1 Box定義文法** + +#### **基本Box** +```nyash +box ClassName { + init { field1, field2, field3 } # カンマ必須!CPU暴走防止 + + # コンストラクタ + init(param1, param2) { # init構文に統一 + me.field1 = param1 + me.field2 = param2 + me.field3 = defaultValue() + } + + # メソッド + methodName(arg1, arg2) { + return me.field1 + arg1 + } + + # デストラクタ + fini() { + print("Cleanup: " + me.field1) + } +} +``` + +#### **デリゲーションBox** +```nyash +box Child from Parent interface Comparable { + init { childField } + + init(parentParam, childParam) { # init構文に統一 + from Parent.init(parentParam) # 親コンストラクタ明示呼び出し + me.childField = childParam + } + + # メソッドオーバーライド + override process(data) { # override必須 + local result = from Parent.process(data) # 親メソッド呼び出し + return result + " (Child processed)" + } + + # インターフェース実装 + compareTo(other) { + return me.value - other.value + } +} +``` + +#### **Static Box(推奨エントリーポイント)** +```nyash +static box Main { + init { console, result } + + main() { + me.console = new ConsoleBox() + me.console.log("🎉 Everything is Box!") + return "Success" + } +} +``` + +#### **ジェネリックBox** +```nyash +box Container { + init { value } + + Container(item) { + me.value = item + } + + getValue() { + return me.value + } +} +``` + +### **2.2 変数宣言** + +#### **基本パターン** +```nyash +# 単一宣言 +local x +local name = "初期値" + +# 複数宣言 +local a, b, c +local x = 10, y = 20, z # 混合初期化 + +# 所有権移転(static関数内) +static function Factory.create() { + outbox product # 呼び出し側に所有権移転 + product = new Item() + return product +} +``` + +#### **変数宣言厳密化システム(2025-08-09実装)** +```nyash +# ✅ 正しい - 明示宣言必須 +local temp +temp = 42 + +# ❌ エラー - 未宣言変数への代入 +x = 42 # RuntimeError: 未宣言変数 + 修正提案表示 +``` + +### **2.3 制御構文** + +#### **条件分岐** +```nyash +if condition { + # 処理 +} else if condition2 { + # 処理2 +} else { + # else処理 +} +``` + +#### **ループ(統一構文)** +```nyash +# ✅ 唯一の正しい形式 +loop(condition) { + # ループ本体 + if exitCondition { + break + } +} + +# ❌ 削除済み - 使用不可 +while condition { } # パーサーエラー +loop() { } # パーサーエラー +``` + +### **2.4 演算子・式** + +#### **🚀 新実装: 関数オーバーロードシステム** +```nyash +# Rust風トレイトベース演算子(2025-08-10実装完了) +sum = 10 + 20 # IntegerBox + IntegerBox = IntegerBox +concat = "Hi" + " !" # StringBox + StringBox = StringBox +repeat = "Ha" * 3 # StringBox * IntegerBox = "HaHaHa" +mixed = 42 + " answer" # 混合型 → 自動文字列結合フォールバック +``` + +#### **演算子優先順位** +```nyash +result = a + b * c / d - e # 算術演算子は標準的優先順位 +logic = not a and b or c # not > and > or +compare = (x > y) and (z <= w) # 比較は括弧推奨 +``` + +#### **論理演算子** +```nyash +# キーワード版(推奨) +canAccess = level >= 5 and hasKey +isValid = not (isEmpty or hasError) + +# シンボル版(互換) +result = condition && other || fallback # 利用可能だが非推奨 +``` + +--- + +## 🏗️ **3. Box構文詳細ガイド** + +### **3.1 Everything is Box 原則** + +```nyash +# すべての値がBox +number = 42 # IntegerBox +text = "hello" # StringBox +flag = true # BoolBox +array = new ArrayBox() # ArrayBox +console = new ConsoleBox() # ConsoleBox + +# 統一的なメソッド呼び出し +print(number.to_string_box().value) # "42" +print(array.length()) # 配列長 +console.log("Everything is Box!") # コンソール出力 +``` + +### **3.2 コンストラクタパターン** + +#### **パラメータ付きコンストラクタ** +```nyash +box Person { + init { name, age, email } + + init(personName, personAge) { # init構文に統一 + me.name = personName + me.age = personAge + me.email = me.name + "@example.com" # 計算フィールド + } + + # ファクトリーメソッド + static createGuest() { + outbox guest + guest = new Person("Guest", 0) + return guest + } +} + +# 使用例 +person = new Person("Alice", 25) +guest = Person.createGuest() +``` + +### **3.3 継承とインターフェース** + +#### **デリゲーションチェーン** +```nyash +# 基底Box +box Animal { + init { name, species } + + init(animalName, animalSpecies) { + me.name = animalName + me.species = animalSpecies + } + + speak() { + return me.name + " makes a sound" + } +} + +# デリゲーション +box Dog from Animal { + init { breed } # 追加フィールド + + init(dogName, dogBreed) { + from Animal.init(dogName, "Canine") # 親コンストラクタ呼び出し + me.breed = dogBreed + } + + override speak() { # 明示的オーバーライド + return me.name + " barks: Woof!" + } +} + +# インターフェース実装 +box Cat from Animal interface Playful { + # Playfulインターフェースの実装必須 +} +``` + +### **3.4 Static Boxパターン** + +#### **名前空間・ユーティリティ** +```nyash +static box MathUtils { + init { PI, E } + + static { + me.PI = 3.14159265 + me.E = 2.71828182 + } + + add(a, b) { + return a + b + } + + circleArea(radius) { + return me.PI * radius * radius + } +} + +# 使用法 +area = MathUtils.circleArea(5) +sum = MathUtils.add(10, 20) +pi = MathUtils.PI +``` + +#### **アプリケーションエントリーポイント** +```nyash +# 🎯 推奨: Static Box Main パターン +static box Main { + init { console, result } + + main() { + me.console = new ConsoleBox() + me.console.log("🚀 Starting application...") + + # アプリケーションロジック + me.result = processData() + + return "Application completed successfully" + } +} +``` + +--- + +## 🚀 **4. 最新機能・革新技術** + +### **4.1 Arc Revolution(2025-08-10)** +```nyash +# 全16種類のBox型が統一Arcパターンで実装 +# 完全なスレッドセーフティと高性能を両立 + +array = new ArrayBox() +array.push(10) # スレッドセーフな追加 +array.push(20) +item = array.get(0) # スレッドセーフな取得 + +json = new JSONBox() +json.set("name", "Alice") # 並行安全な操作 +data = json.stringify() # JSON文字列化 +``` + +### **4.2 Rust風トレイトベース演算子(2025-08-10)** +```nyash +# AI大相談会で決定された最適設計 +# 静的・動的ハイブリッドディスパッチによる高性能実現 + +# 整数演算 +result = 100 - 25 # IntegerBox間演算 → IntegerBox +product = 6 * 7 # 高速静的ディスパッチ + +# 文字列操作 +greeting = "Hello" + " World" # 文字列結合 +repeated = "Echo" * 3 # "EchoEchoEcho" + +# 混合型フォールバック +message = "Answer: " + 42 # "Answer: 42" + +# Boolean演算 +boolSum = true + false # 1 (IntegerBox) +``` + +### **4.3 変数宣言厳密化(2025-08-09)** +```nyash +# メモリ安全性・非同期安全性保証システム + +static box Calculator { + init { memory } # 必須フィールド宣言 + + calculate() { + local temp # 必須ローカル変数宣言 + temp = me.memory * 2 + return temp + } +} +``` + +--- + +## ⚡ **5. 実装済みBox型ライブラリ** + +### **5.1 基本型** +- `StringBox` - 文字列(split, find, replace, trim等) +- `IntegerBox` - 64bit整数 +- `BoolBox` - 真偽値 +- `VoidBox` - null/void値 + +### **5.2 コレクション** +- `ArrayBox` - 動的配列(push, pop, get, set, join等) +- `MapBox` - 連想配列・辞書 + +### **5.3 システム・I/O** +- `ConsoleBox` - コンソール入出力 +- `DebugBox` - デバッグ支援・メモリ追跡 +- `FileBox` - ファイルシステム操作 + +### **5.4 数学・時間** +- `MathBox` - 数学関数(sin, cos, log, sqrt等) +- `TimeBox` - 時刻操作・タイマー +- `RandomBox` - 乱数生成・選択・シャッフル + +### **5.5 データ処理** +- `JSONBox` - JSON解析・生成(parse, stringify, get, set) +- `RegexBox` - 正規表現(test, find, replace, split) +- `BufferBox` - バイナリデータ処理 +- `StreamBox` - ストリーム処理 + +### **5.6 ネットワーク・Web** +- `HttpClientBox` - HTTP通信 +- `WebDisplayBox` - HTML表示(WASM) +- `WebConsoleBox` - ブラウザコンソール(WASM) +- `WebCanvasBox` - Canvas描画(WASM) + +### **5.7 GUI・マルチメディア** +- `EguiBox` - デスクトップGUI(Windows/Linux) +- `SoundBox` - 音声再生 + +--- + +## 🎯 **6. パフォーマンス・デザイン原則** + +### **6.1 メモリ安全性** +- Rust所有権システムによる完全なメモリ安全性 +- Arcによるスレッドセーフな共有状態管理 +- 自動参照カウント + 明示的デストラクタ(fini) + +### **6.2 実行効率** +- 統一されたBox型システムによる最適化 +- 静的・動的ハイブリッドディスパッチで高速演算 +- パーサー無限ループ対策(--debug-fuel) + +### **6.3 開発効率** +- 変数宣言厳密化による早期エラー検出 +- 包括的デバッグ機能(DebugBox) +- 直感的な"Everything is Box"概念 + +--- + +## 📚 **7. 学習パス・ベストプラクティス** + +### **7.1 初心者向け学習順序** +1. **基本概念**: Everything is Box哲学理解 +2. **基本構文**: 変数宣言・制御構文・演算子 +3. **Box定義**: 基本的なクラス作成 +4. **Static Box Main**: アプリケーションエントリーポイント +5. **継承・インターフェース**: オブジェクト指向機能 + +### **7.2 推奨コーディングスタイル** +```nyash +# ✅ 推奨スタイル +static box Main { + init { console, result } # フィールド明示 + + main() { + me.console = new ConsoleBox() + + local data # 変数事前宣言 + data = processInput() + + me.result = data # 明確な代入 + return "Success" + } +} +``` + +### **7.3 よくある間違いと対策** +```nyash +# ❌ よくある間違い +init { field1 field2 } # カンマなし → CPU暴走 +x = 42 # 変数未宣言 → ランタイムエラー +while condition { } # 非対応構文 → パーサーエラー + +# ✅ 正しい書き方 +init { field1, field2 } # カンマ必須 +local x = 42 # 事前宣言 +loop(condition) { } # 統一ループ構文 +``` + +--- + +**🎉 Nyash 2025は、AI協働設計による最先端言語システムとして、シンプルさと強力さを完全に両立しました。** + +*最終更新: 2025年8月10日 - Arc Revolution + AI大相談会成功記念* \ No newline at end of file diff --git a/docs/reference/override-delegation-syntax.md b/docs/説明書/reference/override-delegation-syntax.md similarity index 100% rename from docs/reference/override-delegation-syntax.md rename to docs/説明書/reference/override-delegation-syntax.md diff --git a/docs/説明書/reference/p2p_spec.md b/docs/説明書/reference/p2p_spec.md new file mode 100644 index 00000000..5cedb836 --- /dev/null +++ b/docs/説明書/reference/p2p_spec.md @@ -0,0 +1,254 @@ +# 🌐 P2PBox完全実装 - AI大会議仕様準拠 + +## 📋 Issue概要 + +**目標**: NyaMeshP2Pライブラリ実現のためのP2P通信システムを、AI大会議で決定した最新仕様に従って完全実装する + +**重要**: 既存の `src/boxes/intent_box.rs` と `src/boxes/p2p_box.rs` は**古い設計**のため、**完全に作り直し**が必要 + +## 🎯 AI大会議決定事項 + +### ✅ 採用仕様 +- **構造化IntentBox**: `name` + `payload` 形式のメッセージBox +- **個別送信のみ**: `send(to, message)` 固定API +- **明示的デリゲーション**: `from Parent.method()` 統一構文 + +### ❌ 除外仕様 +- **ブロードキャスト**: 安全性のため完全除外(無限ループリスク回避) +- **関数オーバーロード**: `send(a)` vs `send(a,b)` 分岐不採用 + +## 🏗️ 新アーキテクチャ設計 + +``` +┌─────────────┐ ┌──────────────┐ ┌─────────────┐ +│ P2PBox │◄──►│ MessageBus │◄──►│ Transport │ +│ (ユーザーAPI) │ │ (ローカル配送) │ │ (送受信層) │ +└─────────────┘ └──────────────┘ └─────────────┘ + ▲ ▲ ▲ + │ │ │ +┌─────────────┐ ┌──────────────┐ ┌─────────────┐ +│ IntentBox │ │ ハンドラ管理 │ │ InProcess │ +│ (構造化MSG) │ │ ノード登録 │ │ WebSocket │ +└─────────────┘ └──────────────┘ │ WebRTC │ + └─────────────┘ +``` + +## 📦 段階的実装計画 + +### 🎯 **Phase 1: 基盤実装** + +#### **Step 1: IntentBox(構造化メッセージ)** +**ファイル**: `src/boxes/intent_box.rs` (完全作り直し) + +```rust +// 新しいIntentBox設計 +pub struct IntentBoxData { + pub name: String, // "chat.message", "file.share"等 + pub payload: serde_json::Value, // 任意のJSON data +} +pub type IntentBox = Arc>; +``` + +**実装要件**: +- Arc統一パターン準拠 +- BoxCore + NyashBox実装 +- serde_json::Value使用 + +**テストコード**: +```nyash +// tests/phase2/intent_box_test.nyash +local msg = new IntentBox("chat.message", { text: "Hello P2P!" }) +local console = new ConsoleBox() +console.log("Name: " + msg.name) // "chat.message" +console.log("Text: " + msg.payload.text) // "Hello P2P!" +``` + +#### **Step 2: MessageBus(プロセス内シングルトン)** +**ファイル**: `src/messaging/message_bus.rs` (新規作成) + +```rust +pub struct MessageBusData { + nodes: HashMap, // ノード登録 + subscribers: HashMap>, // ハンドラー管理 +} +pub type MessageBus = Arc>; + +impl MessageBusData { + pub fn global() -> MessageBus // シングルトンアクセス + pub fn register_node(&mut self, id: String, endpoint: BusEndpoint) + pub fn route(&self, to: &str, intent: IntentBox) -> Result<(), SendError> +} +``` + +#### **Step 3: Transport trait(送受信抽象化)** +**ファイル**: `src/transport/mod.rs` (新規作成) + +```rust +pub trait Transport: Send + Sync { + fn node_id(&self) -> &str; + fn send(&self, to: &str, intent: IntentBox, opts: SendOpts) -> Result<(), SendError>; + fn on_receive(&mut self, callback: Box); +} +``` + +### 🎯 **Phase 2: InProcess実装** + +#### **Step 4: InProcessTransport** +**ファイル**: `src/transport/inprocess.rs` (新規作成) + +```rust +pub struct InProcessTransport { + node_id: String, + bus: MessageBus, // MessageBus::global()を使用 +} + +impl Transport for InProcessTransport { + // Bus経由の高速ローカル配送実装 +} +``` + +### 🎯 **Phase 3: P2PBox統合** + +#### **Step 5: P2PBox基本実装** +**ファイル**: `src/boxes/p2p_box.rs` (完全作り直し) + +```rust +pub struct P2PBoxData { + node_id: String, + transport: Arc, + bus: MessageBus, // 全P2PBoxで共有 +} +pub type P2PBox = Arc>; + +impl P2PBoxData { + pub fn new(node_id: String, kind: TransportKind) -> P2PBox + pub fn on(&self, intent_name: &str, handler: IntentHandler) -> Result<(), P2PError> + pub fn send(&self, to: &str, intent: IntentBox) -> Result<(), SendError> + // ブロードキャストメソッドは実装しない +} +``` + +## 🧪 包括的テスト要件 + +### **基本動作テスト** +**ファイル**: `test_p2p_basic_new.nyash` + +```nyash +// 2つのノード作成 +local node_a = new P2PBox("alice", transport: "inprocess") +local node_b = new P2PBox("bob", transport: "inprocess") + +// 受信ハンドラ設定 +node_b.on("chat.message", function(intent, from) { + local console = new ConsoleBox() + console.log("From " + from + ": " + intent.payload.text) +}) + +// メッセージ送信 +local msg = new IntentBox("chat.message", { text: "Hello P2P!" }) +node_a.send("bob", msg) // → "From alice: Hello P2P!" +``` + +### **エラーハンドリングテスト** +```nyash +// 存在しないノードへの送信 +local result = node_a.send("nonexistent", msg) +// → SendError::NodeNotFound + +// 不正なIntentBox +local invalid_msg = "not an IntentBox" +local result = node_a.send("bob", invalid_msg) +// → 型エラー +``` + +### **パフォーマンステスト** +```nyash +// 大量メッセージ送信テスト +local start_time = new TimeBox() +loop(i < 1000) { + local msg = new IntentBox("test.performance", { id: i }) + node_a.send("bob", msg) + i = i + 1 +} +local end_time = new TimeBox() +// 実行時間計測 +``` + +## 📁 必要なディレクトリ構成 + +``` +src/ +├── boxes/ +│ ├── intent_box.rs # 完全作り直し +│ └── p2p_box.rs # 完全作り直し +├── messaging/ # 新規作成 +│ └── message_bus.rs # MessageBus実装 +└── transport/ # 新規作成 + ├── mod.rs # Transport trait + └── inprocess.rs # InProcessTransport +``` + +## 🔧 実装時の重要注意点 + +### **Arc統一パターン厳守** +```rust +// ✅ 正しい統一パターン +pub type IntentBox = Arc>; +pub type MessageBus = Arc>; +pub type P2PBox = Arc>; + +// ❌ 避けるべき +pub struct IntentBox { ... } // Arcなし +``` + +### **BoxCore実装必須** +```rust +impl BoxCore for IntentBox { + fn box_id(&self) -> u64 { self.lock().unwrap().base.id } + fn parent_type_id(&self) -> Option { None } + fn fmt_box(&self, f: &mut fmt::Formatter) -> fmt::Result { ... } + fn as_any(&self) -> &dyn Any { self } + fn as_any_mut(&mut self) -> &mut dyn Any { self } +} +``` + +### **エラーハンドリング設計** +```rust +#[derive(Debug, Clone)] +pub enum SendError { + NodeNotFound(String), // 宛先ノードが見つからない + NetworkError(String), // ネットワークエラー + SerializationError(String), // JSON変換エラー + BusError(String), // MessageBusエラー +} +``` + +## 🎯 成功の定義 + +以下のテストが全て通過すること: + +1. **基本通信**: ノード間でIntentBoxメッセージ送受信 +2. **ハンドラ登録**: `on()` でイベントリスナー正常動作 +3. **エラーハンドリング**: 不正な送信先・データで適切エラー +4. **パフォーマンス**: 1000メッセージ/秒以上の送信性能 +5. **メモリ安全性**: valgrind等でメモリリーク検出なし + +## 📚 参考ドキュメント + +- **[P2P_GUIDE.md](docs/P2P_GUIDE.md)** - 設計詳細・使用例 +- **[CURRENT_TASK.md](CURRENT_TASK.md)** - 実装状況・優先順位 +- **[ai_conference_overload_decision.md](ai_conference_overload_decision.md)** - AI大会議決定事項 +- **[docs/reference/override-delegation-syntax.md](docs/reference/override-delegation-syntax.md)** - デリゲーション構文仕様 + +## 🚀 実装開始 + +**Priority**: High +**Assignee**: Copilot +**Labels**: enhancement, p2p, breaking-change +**Milestone**: P2P Phase 2 Complete + +**最初に取り組むべき**: Step 1 IntentBox の完全作り直し + +--- + +🎉 **この実装により、Nyashは本格的なP2P通信システムを持つ現代的プログラミング言語になります!** \ No newline at end of file diff --git a/wasm_browser_plan.md b/docs/説明書/wasm/wasm_browser_plan.md similarity index 100% rename from wasm_browser_plan.md rename to docs/説明書/wasm/wasm_browser_plan.md diff --git a/wasm_quick_start.md b/docs/説明書/wasm/wasm_quick_start.md similarity index 100% rename from wasm_quick_start.md rename to docs/説明書/wasm/wasm_quick_start.md diff --git a/examples/wasm/test_drawing_app.html b/examples/wasm/test_drawing_app.html new file mode 100644 index 00000000..d9ee13ad --- /dev/null +++ b/examples/wasm/test_drawing_app.html @@ -0,0 +1,53 @@ + + + + + Nyash Drawing App Test + + + +

Nyash Drawing App Test

+

Loading WASM and Nyash script...

+ + + + + \ No newline at end of file diff --git a/debug_from_test.nyash b/local_tests/debug_from_test.nyash similarity index 100% rename from debug_from_test.nyash rename to local_tests/debug_from_test.nyash diff --git a/field_access_test.nyash b/local_tests/field_access_test.nyash similarity index 100% rename from field_access_test.nyash rename to local_tests/field_access_test.nyash diff --git a/mir_examples.nyash b/local_tests/mir_examples.nyash similarity index 100% rename from mir_examples.nyash rename to local_tests/mir_examples.nyash diff --git a/local_tests/mir_try_basic.nyash b/local_tests/mir_try_basic.nyash new file mode 100644 index 00000000..f842220a --- /dev/null +++ b/local_tests/mir_try_basic.nyash @@ -0,0 +1,12 @@ +static box Main { + main() { + try { + print("in try") + throw "oops" + } catch (Exception e) { + print("caught") + } + print("after") + } +} + diff --git a/local_tests/sample.nyash b/local_tests/sample.nyash new file mode 100644 index 00000000..ef83e41f --- /dev/null +++ b/local_tests/sample.nyash @@ -0,0 +1,14 @@ +# Minimal Nyash sample +box Greeter { + message + pack(msg) { me.message = msg } + say() { print(me.message) } +} + +static box Main { + main() { + local g + g = new Greeter("Hello, Nyash!") + g.say() + } +} diff --git a/simple_from_test.nyash b/local_tests/simple_from_test.nyash similarity index 100% rename from simple_from_test.nyash rename to local_tests/simple_from_test.nyash diff --git a/simple_loop_test.nyash b/local_tests/simple_loop_test.nyash similarity index 100% rename from simple_loop_test.nyash rename to local_tests/simple_loop_test.nyash diff --git a/simple_loop_test2.nyash b/local_tests/simple_loop_test2.nyash similarity index 100% rename from simple_loop_test2.nyash rename to local_tests/simple_loop_test2.nyash diff --git a/simple_loop_test3.nyash b/local_tests/simple_loop_test3.nyash similarity index 100% rename from simple_loop_test3.nyash rename to local_tests/simple_loop_test3.nyash diff --git a/simple_test.nyash b/local_tests/simple_test.nyash similarity index 100% rename from simple_test.nyash rename to local_tests/simple_test.nyash diff --git a/simple_throw_test.nyash b/local_tests/simple_throw_test.nyash similarity index 100% rename from simple_throw_test.nyash rename to local_tests/simple_throw_test.nyash diff --git a/simple_try_test.nyash b/local_tests/simple_try_test.nyash similarity index 100% rename from simple_try_test.nyash rename to local_tests/simple_try_test.nyash diff --git a/local_tests/test_all_new_boxes.nyash b/local_tests/test_all_new_boxes.nyash new file mode 100644 index 00000000..7cb533c5 --- /dev/null +++ b/local_tests/test_all_new_boxes.nyash @@ -0,0 +1,58 @@ +// 🧪 新しいBoxタイプの統合テスト +// Arcパターンが正しく動作することを確認 + +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 pattern tests completed successfully!") \ No newline at end of file diff --git a/local_tests/test_array_box.nyash b/local_tests/test_array_box.nyash new file mode 100644 index 00000000..f88a0450 --- /dev/null +++ b/local_tests/test_array_box.nyash @@ -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テスト完了! ===") \ No newline at end of file diff --git a/local_tests/test_array_box_simple.nyash b/local_tests/test_array_box_simple.nyash new file mode 100644 index 00000000..b7dc62ab --- /dev/null +++ b/local_tests/test_array_box_simple.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_array_improvements.nyash b/local_tests/test_array_improvements.nyash new file mode 100644 index 00000000..42949faa --- /dev/null +++ b/local_tests/test_array_improvements.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_array_methods.nyash b/local_tests/test_array_methods.nyash new file mode 100644 index 00000000..067bf212 --- /dev/null +++ b/local_tests/test_array_methods.nyash @@ -0,0 +1,65 @@ +// test_array_methods.nyash - ArrayBox改良テスト +// Phase 1: ArrayBox sort(), reverse(), indexOf(), slice() validation + +print("🗂️ Testing ArrayBox improvements...") + +// Create and populate array +local arr +arr = new ArrayBox() +arr.push(3) +arr.push(1) +arr.push(2) + +print("Original: " + arr.toString()) + +// Test sort() method +arr.sort() +print("Sorted: " + arr.toString()) + +// Test reverse() method +arr.reverse() +print("Reversed: " + arr.toString()) + +// Test indexOf() method +local index +index = arr.indexOf(2) +print("Index of 2: " + index.toString()) + +index = arr.indexOf(1) +print("Index of 1: " + index.toString()) + +index = arr.indexOf(99) +print("Index of 99: " + index.toString()) + +// Test slice() method +local slice +slice = arr.slice(0, 2) +print("Slice [0,2): " + slice.toString()) + +slice = arr.slice(1, 3) +print("Slice [1,3): " + slice.toString()) + +// Test with string array +local strArr +strArr = new ArrayBox() +strArr.push("zebra") +strArr.push("apple") +strArr.push("banana") + +print("String array original: " + strArr.toString()) + +strArr.sort() +print("String array sorted: " + strArr.toString()) + +strArr.reverse() +print("String array reversed: " + strArr.toString()) + +// Test indexOf on strings +index = strArr.indexOf("apple") +print("Index of 'apple': " + index.toString()) + +// Test slice on strings +slice = strArr.slice(0, 2) +print("String slice [0,2): " + slice.toString()) + +print("✅ ArrayBox improvements Phase 1 tests completed!") \ No newline at end of file diff --git a/local_tests/test_array_simple.nyash b/local_tests/test_array_simple.nyash new file mode 100644 index 00000000..c25fecf5 --- /dev/null +++ b/local_tests/test_array_simple.nyash @@ -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! ===") \ No newline at end of file diff --git a/local_tests/test_basic_box_comprehensive.nyash b/local_tests/test_basic_box_comprehensive.nyash new file mode 100644 index 00000000..de1ac467 --- /dev/null +++ b/local_tests/test_basic_box_comprehensive.nyash @@ -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! ===") \ No newline at end of file diff --git a/local_tests/test_basic_box_constructors.nyash b/local_tests/test_basic_box_constructors.nyash new file mode 100644 index 00000000..43954e7d --- /dev/null +++ b/local_tests/test_basic_box_constructors.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_basic_boxes.nyash b/local_tests/test_basic_boxes.nyash new file mode 100644 index 00000000..fa24352a --- /dev/null +++ b/local_tests/test_basic_boxes.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_box_creation.nyash b/local_tests/test_box_creation.nyash new file mode 100644 index 00000000..7bbfec05 --- /dev/null +++ b/local_tests/test_box_creation.nyash @@ -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 Boxes created successfully!") \ No newline at end of file diff --git a/local_tests/test_boxes.nyash b/local_tests/test_boxes.nyash new file mode 100644 index 00000000..f10e7e95 --- /dev/null +++ b/local_tests/test_boxes.nyash @@ -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!") + } +} \ No newline at end of file diff --git a/local_tests/test_buffer_box.nyash b/local_tests/test_buffer_box.nyash new file mode 100644 index 00000000..734d7c45 --- /dev/null +++ b/local_tests/test_buffer_box.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_comparison_operators.nyash b/local_tests/test_comparison_operators.nyash new file mode 100644 index 00000000..52b0a58c --- /dev/null +++ b/local_tests/test_comparison_operators.nyash @@ -0,0 +1,77 @@ +// test_comparison_operators.nyash - Comparison operators test +// Phase 4: Comparison operators implementation validation + +print("⚖️ Testing comparison operators implementation...") + +// Basic variables for testing +local f1, f2, i1, i2, s1, s2, result + +// Test FloatBox comparisons +f1 = new FloatBox(3.14) +f2 = new FloatBox(2.86) + +print("=== FloatBox Comparisons ===") +result = f1 > f2 +print("3.14 > 2.86: " + result.toString()) + +result = f1 < f2 +print("3.14 < 2.86: " + result.toString()) + +result = f1 >= f2 +print("3.14 >= 2.86: " + result.toString()) + +result = f1 <= f2 +print("3.14 <= 2.86: " + result.toString()) + +result = f1 == f2 +print("3.14 == 2.86: " + result.toString()) + +result = f1 != f2 +print("3.14 != 2.86: " + result.toString()) + +// Test IntegerBox comparisons +i1 = 10 +i2 = 5 + +print("=== IntegerBox Comparisons ===") +result = i1 > i2 +print("10 > 5: " + result.toString()) + +result = i1 < i2 +print("10 < 5: " + result.toString()) + +result = i1 >= i2 +print("10 >= 5: " + result.toString()) + +result = i1 <= i2 +print("10 <= 5: " + result.toString()) + +result = i1 == i2 +print("10 == 5: " + result.toString()) + +result = i1 != i2 +print("10 != 5: " + result.toString()) + +// Test mixed type comparisons (FloatBox vs IntegerBox) +print("=== Mixed Type Comparisons ===") +result = f1 > i2 +print("3.14 > 5: " + result.toString()) + +result = f1 < i1 +print("3.14 < 10: " + result.toString()) + +result = i1 >= f1 +print("10 >= 3.14: " + result.toString()) + +result = i2 <= f2 +print("5 <= 2.86: " + result.toString()) + +// Test logical operators +print("=== Logical Operators ===") +result = (f1 > f2) and (i1 > i2) +print("(3.14 > 2.86) and (10 > 5): " + result.toString()) + +result = (f1 < f2) or (i1 > i2) +print("(3.14 < 2.86) or (10 > 5): " + result.toString()) + +print("✅ Comparison operators Phase 4 tests completed!") \ No newline at end of file diff --git a/local_tests/test_comprehensive_final.nyash b/local_tests/test_comprehensive_final.nyash new file mode 100644 index 00000000..932a9d6f --- /dev/null +++ b/local_tests/test_comprehensive_final.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_cross_type_operators.nyash b/local_tests/test_cross_type_operators.nyash new file mode 100644 index 00000000..0951eeb5 --- /dev/null +++ b/local_tests/test_cross_type_operators.nyash @@ -0,0 +1,115 @@ +// test_cross_type_operators.nyash - 演算子システム強化テスト +// Phase 1: Cross-type operations, string concatenation, comparisons validation + +print("🔢 Testing cross-type operators implementation...") + +// Test 1: IntegerBox + FloatBox +print("=== Type Conversion Tests ===") +local i, f, result +i = 10 +f = new FloatBox(3.14) +result = i + f +print("10 + 3.14 = " + result.toString()) + +result = f + i +print("3.14 + 10 = " + result.toString()) + +// Test multiplication +result = i * f +print("10 * 3.14 = " + result.toString()) + +result = f * i +print("3.14 * 10 = " + result.toString()) + +// Test division +result = i / f +print("10 / 3.14 = " + result.toString()) + +result = f / i +print("3.14 / 10 = " + result.toString()) + +// Test subtraction +result = i - f +print("10 - 3.14 = " + result.toString()) + +result = f - i +print("3.14 - 10 = " + result.toString()) + +// Test 2: String concatenation with numbers +print("\n=== String Concatenation Tests ===") +local text, num, boolVal +text = "Value: " +num = 42 +boolVal = true + +result = text + num +print("\"Value: \" + 42 = " + result) + +result = text + f +print("\"Value: \" + 3.14 = " + result) + +result = text + boolVal +print("\"Value: \" + true = " + result) + +// Reverse concatenation +result = num + " items" +print("42 + \" items\" = " + result) + +// Test 3: Cross-type comparisons +print("\n=== Cross-Type Comparison Tests ===") +local comparison + +comparison = f > i +print("3.14 > 10: " + comparison.toString()) + +comparison = i > f +print("10 > 3.14: " + comparison.toString()) + +comparison = f < i +print("3.14 < 10: " + comparison.toString()) + +comparison = i < f +print("10 < 3.14: " + comparison.toString()) + +comparison = f >= i +print("3.14 >= 10: " + comparison.toString()) + +comparison = i <= f +print("10 <= 3.14: " + comparison.toString()) + +comparison = f == i +print("3.14 == 10: " + comparison.toString()) + +comparison = f != i +print("3.14 != 10: " + comparison.toString()) + +// Test 4: Complex expressions +print("\n=== Complex Expression Tests ===") +local complex + +complex = (i + f) > 12 +print("(10 + 3.14) > 12: " + complex.toString()) + +complex = (f * 2) < (i - 3) +print("(3.14 * 2) < (10 - 3): " + complex.toString()) + +complex = (i > 5) and (f > 3) +print("(10 > 5) and (3.14 > 3): " + complex.toString()) + +complex = (i < 5) or (f > 3) +print("(10 < 5) or (3.14 > 3): " + complex.toString()) + +// Test 5: Number to string auto-conversion in concatenation +print("\n=== Auto-Conversion Tests ===") +local auto1, auto2, auto3 + +auto1 = "Result: " + (i + f) +print("\"Result: \" + (10 + 3.14) = " + auto1) + +auto2 = "Boolean: " + (i > f) +print("\"Boolean: \" + (10 > 3.14) = " + auto2) + +auto3 = "Math: " + (f * f) +print("\"Math: \" + (3.14 * 3.14) = " + auto3) + +print("\n✅ Cross-type operators Phase 1 tests completed!") \ No newline at end of file diff --git a/local_tests/test_datetime_box.nyash b/local_tests/test_datetime_box.nyash new file mode 100644 index 00000000..4aea4aaf --- /dev/null +++ b/local_tests/test_datetime_box.nyash @@ -0,0 +1,43 @@ +// test_datetime_box.nyash - DateTimeBox functionality test +// Phase 3: DateTimeBox implementation validation + +print("📅 Testing DateTimeBox implementation...") + +// Basic DateTimeBox creation +local now, timestamp_dt, parsed_dt, result + +// Test 1: Current time creation +now = new DateTimeBox() +print("Current time: " + now.toString()) + +// Test 2: Timestamp creation +timestamp_dt = new DateTimeBox(1640995200) // 2022-01-01 00:00:00 UTC +print("From timestamp: " + timestamp_dt.toString()) + +// Test 3: Date component extraction +result = now.year() +print("Current year: " + result.toString()) + +result = now.month() +print("Current month: " + result.toString()) + +result = now.day() +print("Current day: " + result.toString()) + +result = now.hour() +print("Current hour: " + result.toString()) + +result = now.minute() +print("Current minute: " + result.toString()) + +result = now.second() +print("Current second: " + result.toString()) + +// Test 4: Date arithmetic +result = now.addDays(7) +print("7 days from now: " + result.toString()) + +result = now.addHours(24) +print("24 hours from now: " + result.toString()) + +print("✅ DateTimeBox Phase 3 tests completed!") \ No newline at end of file diff --git a/local_tests/test_datetime_tostring.nyash b/local_tests/test_datetime_tostring.nyash new file mode 100644 index 00000000..db746198 --- /dev/null +++ b/local_tests/test_datetime_tostring.nyash @@ -0,0 +1,4 @@ +// test_datetime_tostring.nyash - DateTimeBox toString() test as mentioned in issue +local dt +dt = new DateTimeBox() +print(dt.toString()) \ No newline at end of file diff --git a/local_tests/test_final_weak_demo.nyash b/local_tests/test_final_weak_demo.nyash new file mode 100644 index 00000000..698e43f6 --- /dev/null +++ b/local_tests/test_final_weak_demo.nyash @@ -0,0 +1,83 @@ +// Final comprehensive weak reference auto-nil test + +// Global flag to simulate object dropping +box GlobalState { + init { parentDropped } + + pack() { + me.parentDropped = false + } + + setParentDropped(dropped) { + me.parentDropped = dropped + } + + isParentDropped() { + return me.parentDropped + } +} + +box Parent { + init { name, child } + + pack(parentName) { + me.name = parentName + me.child = new Child() + me.child.setParent(me) // This creates a weak reference + } + + getChild() { + return me.child + } + + getName() { + return me.name + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p + } + + getParentStatus() { + // Check if parent is still alive using the global state + local state = new GlobalState() + local dropped = state.isParentDropped() + + if dropped { + return "Parent is null (dropped)" + } else { + return "Parent exists" + } + } + + checkWeakParent() { + return me.parent + } +} + +static box Main { + main() { + print("=== Complete Weak Reference Auto-Nil Test ===") + + local state = new GlobalState() + + local parent = new Parent("TestParent") + local child = parent.getChild() + + print("Step 1: Initial setup") + print("Initial status: " + child.getParentStatus()) + + print("Step 2: Simulating parent drop") + state.setParentDropped(true) // Mark parent as dropped + parent = 0 // This triggers the weak reference invalidation + + print("Step 3: Checking weak reference after drop") + print("Final status: " + child.getParentStatus()) + + return "weak reference auto-nil demonstration completed" + } +} \ No newline at end of file diff --git a/local_tests/test_fini_system.nyash b/local_tests/test_fini_system.nyash new file mode 100644 index 00000000..77338fc2 --- /dev/null +++ b/local_tests/test_fini_system.nyash @@ -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" + } +} \ No newline at end of file diff --git a/local_tests/test_fini_violations.nyash b/local_tests/test_fini_violations.nyash new file mode 100644 index 00000000..38820b09 --- /dev/null +++ b/local_tests/test_fini_violations.nyash @@ -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" + } +} \ No newline at end of file diff --git a/local_tests/test_float_box.nyash b/local_tests/test_float_box.nyash new file mode 100644 index 00000000..846bb44e --- /dev/null +++ b/local_tests/test_float_box.nyash @@ -0,0 +1,49 @@ +// test_float_box.nyash - FloatBox functionality test +// Phase 1: Basic FloatBox implementation validation + +print("🧮 Testing FloatBox implementation...") + +// Basic FloatBox creation +local f1, f2, result +f1 = new FloatBox(3.14) +f2 = new FloatBox(2.86) + +print("Created FloatBox f1: " + f1.toString()) +print("Created FloatBox f2: " + f2.toString()) + +// Addition test +result = f1 + f2 +print("3.14 + 2.86 = " + result.toString()) + +// Multiplication test +result = f1 * f2 +print("3.14 * 2.86 = " + result.toString()) + +// Division test +result = f1 / f2 +print("3.14 / 2.86 = " + result.toString()) + +// Subtraction test +result = f1 - f2 +print("3.14 - 2.86 = " + result.toString()) + +// Mixed operations with IntegerBox +local intVal +intVal = 5 +result = f1 + intVal +print("3.14 + 5 = " + result.toString()) + +result = f1 * intVal +print("3.14 * 5 = " + result.toString()) + +// FloatBox methods +result = f1.abs() +print("abs(3.14) = " + result.toString()) + +result = f1.floor() +print("floor(3.14) = " + result.toString()) + +result = f1.ceil() +print("ceil(3.14) = " + result.toString()) + +print("✅ FloatBox Phase 1 tests completed!") \ No newline at end of file diff --git a/local_tests/test_float_box_issues.nyash b/local_tests/test_float_box_issues.nyash new file mode 100644 index 00000000..6f2e1fe2 --- /dev/null +++ b/local_tests/test_float_box_issues.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_float_tostring.nyash b/local_tests/test_float_tostring.nyash new file mode 100644 index 00000000..e6c596c1 --- /dev/null +++ b/local_tests/test_float_tostring.nyash @@ -0,0 +1,4 @@ +// test_float_tostring.nyash - FloatBox toString() test as mentioned in issue +local f1 +f1 = new FloatBox(3.14) +print(f1.toString()) \ No newline at end of file diff --git a/local_tests/test_from_call.nyash b/local_tests/test_from_call.nyash new file mode 100644 index 00000000..f03b3db9 --- /dev/null +++ b/local_tests/test_from_call.nyash @@ -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!" + } +} \ No newline at end of file diff --git a/local_tests/test_intent_field_access.nyash b/local_tests/test_intent_field_access.nyash new file mode 100644 index 00000000..08d9b368 --- /dev/null +++ b/local_tests/test_intent_field_access.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_intent_only.nyash b/local_tests/test_intent_only.nyash new file mode 100644 index 00000000..4656befc --- /dev/null +++ b/local_tests/test_intent_only.nyash @@ -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()) \ No newline at end of file diff --git a/local_tests/test_invalid_override.nyash b/local_tests/test_invalid_override.nyash new file mode 100644 index 00000000..ab92b88b --- /dev/null +++ b/local_tests/test_invalid_override.nyash @@ -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("このメッセージが表示されたらテスト失敗") \ No newline at end of file diff --git a/local_tests/test_mir_simple.nyash b/local_tests/test_mir_simple.nyash new file mode 100644 index 00000000..637e94bf --- /dev/null +++ b/local_tests/test_mir_simple.nyash @@ -0,0 +1,6 @@ +/*! + * Simple test for basic MIR functionality + */ + +// A simple Nyash program for testing MIR compilation +print(42 + 10) \ No newline at end of file diff --git a/local_tests/test_multi_delegation.nyash b/local_tests/test_multi_delegation.nyash new file mode 100644 index 00000000..db47fa72 --- /dev/null +++ b/local_tests/test_multi_delegation.nyash @@ -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 ===") \ No newline at end of file diff --git a/local_tests/test_multi_delegation_advanced.nyash b/local_tests/test_multi_delegation_advanced.nyash new file mode 100644 index 00000000..5295226d --- /dev/null +++ b/local_tests/test_multi_delegation_advanced.nyash @@ -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! ===") \ No newline at end of file diff --git a/local_tests/test_new_boxes.nyash b/local_tests/test_new_boxes.nyash new file mode 100644 index 00000000..cd0d581c --- /dev/null +++ b/local_tests/test_new_boxes.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_new_operators.nyash b/local_tests/test_new_operators.nyash new file mode 100644 index 00000000..7e6314b6 --- /dev/null +++ b/local_tests/test_new_operators.nyash @@ -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!" + } +} \ No newline at end of file diff --git a/local_tests/test_operators.nyash b/local_tests/test_operators.nyash new file mode 100644 index 00000000..6d28e9d0 --- /dev/null +++ b/local_tests/test_operators.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_override_validation.nyash b/local_tests/test_override_validation.nyash new file mode 100644 index 00000000..210d19b3 --- /dev/null +++ b/local_tests/test_override_validation.nyash @@ -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テスト完了!") \ No newline at end of file diff --git a/local_tests/test_p2p_basic.nyash b/local_tests/test_p2p_basic.nyash new file mode 100644 index 00000000..13518870 --- /dev/null +++ b/local_tests/test_p2p_basic.nyash @@ -0,0 +1,61 @@ +// 🧪 P2PBox基本機能テスト +// IntentBoxとP2PBoxの基本的な動作を検証 + +print("=== P2PBox Basic Test ===") + +// 1. IntentBoxの作成 +print("\n1. Creating IntentBox...") +local world +world = new IntentBox() +print("✅ IntentBox created: " + world.type()) + +// 2. P2PBoxノードの作成 +print("\n2. Creating P2PBox nodes...") +local alice +local bob +local charlie + +alice = new P2PBox("alice", world) +bob = new P2PBox("bob", world) +charlie = new P2PBox("charlie", world) + +print("✅ Alice created: " + alice.getNodeId()) +print("✅ Bob created: " + bob.getNodeId()) +print("✅ Charlie created: " + charlie.getNodeId()) + +// 3. リスナー登録テスト +print("\n3. Testing listener registration...") +bob.on("greeting", "bob_greeting_handler") +charlie.on("greeting", "charlie_greeting_handler") +print("✅ Listeners registered") + +// 4. 直接送信テスト +print("\n4. Testing direct send...") +alice.send("greeting", "Hello Bob!", "bob") +alice.send("greeting", "Hello Charlie!", "charlie") +print("✅ Messages sent") + +// 5. ブロードキャストテスト +print("\n5. Testing broadcast...") +alice.broadcast("announcement", "Hello everyone!") +print("✅ Broadcast sent") + +// 6. リスナー解除テスト +print("\n6. Testing listener removal...") +local result +result = bob.off("greeting") +print("✅ Bob's listener removed: " + result) + +// 7. 解除後の送信テスト +print("\n7. Testing send after listener removal...") +alice.send("greeting", "Hello again Bob!", "bob") +print("✅ Message sent (Bob should not receive)") + +// 8. 複数リスナーテスト +print("\n8. Testing multiple listeners...") +charlie.on("data", "charlie_data_handler1") +charlie.on("data", "charlie_data_handler2") +alice.send("data", "Test data", "charlie") +print("✅ Multiple listeners tested") + +print("\n=== Test Complete ===") \ No newline at end of file diff --git a/local_tests/test_p2p_basic_new.nyash b/local_tests/test_p2p_basic_new.nyash new file mode 100644 index 00000000..b6cd5d55 --- /dev/null +++ b/local_tests/test_p2p_basic_new.nyash @@ -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 memory safety pattern") +print(" - MessageBus singleton routing") \ No newline at end of file diff --git a/local_tests/test_p2p_callback_demo.nyash b/local_tests/test_p2p_callback_demo.nyash new file mode 100644 index 00000000..5a04eddf --- /dev/null +++ b/local_tests/test_p2p_callback_demo.nyash @@ -0,0 +1,94 @@ +// 🧪 P2PBox コールバック実行デモ +// 実際のメッセージ受信とコールバック実行の様子を確認 + +print("=== P2PBox Callback Demo ===") + +// 通信世界を作成 +local world +world = new IntentBox() + +print("\n1. Creating chat nodes...") +local alice +local bob +alice = new P2PBox("alice", world) +bob = new P2PBox("bob", world) +print("✅ Alice and Bob joined the chat") + +// 現在はコールバックを実際に実行できないため、 +// 登録と送信の流れを示すデモンストレーション +print("\n2. Registering message handlers...") +print("⚠️ Note: Callbacks are registered but not executed in current implementation") +print(" (MethodBox integration pending)") + +// Bobのメッセージハンドラー登録 +bob.on("chat", "bob_chat_handler") +bob.on("typing", "bob_typing_handler") +bob.on("image", "bob_image_handler") +print("✅ Bob's handlers registered") + +// Aliceのメッセージハンドラー登録 +alice.on("chat", "alice_chat_handler") +alice.on("reply", "alice_reply_handler") +print("✅ Alice's handlers registered") + +print("\n3. Message exchange simulation...") + +// チャットメッセージ +local chatMsg +chatMsg = new MapBox() +chatMsg.set("text", "Hi Bob! How are you?") +chatMsg.set("timestamp", 1234567890) +alice.send("chat", chatMsg, "bob") +print("Alice → Bob: Hi Bob! How are you?") + +// タイピング通知 +alice.send("typing", true, "bob") +print("Alice → Bob: [typing...]") + +// 画像送信 +local imageMsg +imageMsg = new MapBox() +imageMsg.set("url", "https://example.com/photo.jpg") +imageMsg.set("caption", "Check out this photo!") +alice.send("image", imageMsg, "bob") +print("Alice → Bob: [sent an image]") + +// 返信 +local replyMsg +replyMsg = new MapBox() +replyMsg.set("text", "I'm doing great, thanks!") +replyMsg.set("replyTo", "Hi Bob! How are you?") +bob.send("reply", replyMsg, "alice") +print("Bob → Alice: I'm doing great, thanks!") + +print("\n4. Broadcast demo...") +// 全員への通知 +local announcement +announcement = new MapBox() +announcement.set("type", "system") +announcement.set("message", "Welcome to NyaMesh P2P Chat!") +alice.broadcast("announcement", announcement) +print("System broadcast: Welcome to NyaMesh P2P Chat!") + +print("\n5. Testing message queue...") +// メッセージキューの処理 +local processed +processed = world.processMessages() +print("Messages in queue: " + processed) + +print("\n6. Dynamic listener management...") +// 動的なリスナー管理 +alice.off("chat") +print("✅ Alice unsubscribed from chat") + +// 解除後のメッセージ(受信されない) +bob.send("chat", "Are you still there?", "alice") +print("Bob → Alice: Are you still there? (Alice won't receive)") + +print("\n=== Demo Complete ===") +print("\n📝 Summary:") +print("- IntentBox creates communication worlds") +print("- P2PBox nodes can join and exchange messages") +print("- Listeners can be dynamically added/removed") +print("- LocalTransport handles in-process messaging") +print("- Full callback execution requires MethodBox integration") \ No newline at end of file diff --git a/local_tests/test_p2p_edge_cases.nyash b/local_tests/test_p2p_edge_cases.nyash new file mode 100644 index 00000000..f7384612 --- /dev/null +++ b/local_tests/test_p2p_edge_cases.nyash @@ -0,0 +1,86 @@ +// 🧪 P2PBox エッジケーステスト +// エラーハンドリングと異常系の動作検証 + +print("=== P2PBox Edge Cases Test ===") + +// 基本セットアップ +local world +world = new IntentBox() + +local node1 +node1 = new P2PBox("node1", world) + +print("\n1. Testing invalid target send") +// 存在しないノードへの送信 +local result +result = node1.send("test", "data", "non_existent_node") +print("Send to non-existent node: " + result) + +print("\n2. Testing empty intent string") +// 空のintent文字列 +node1.on("", "empty_handler") +result = node1.send("", "test data", "node1") +print("Empty intent handled: " + result) + +print("\n3. Testing duplicate listener removal") +// 同じintentを2回削除 +node1.on("test_event", "handler1") +result = node1.off("test_event") +print("First removal: " + result) +result = node1.off("test_event") +print("Second removal: " + result) + +print("\n4. Testing self-messaging") +// 自分自身へのメッセージ送信 +node1.on("self_msg", "self_handler") +result = node1.send("self_msg", "Hello myself!", "node1") +print("Self message sent: " + result) + +print("\n5. Testing very long intent names") +// 非常に長いintent名 +local longIntent +longIntent = "this_is_a_very_long_intent_name_that_tests_the_system_limits_1234567890_abcdefghijklmnopqrstuvwxyz" +node1.on(longIntent, "long_handler") +result = node1.send(longIntent, "test", "node1") +print("Long intent handled: " + result) + +print("\n6. Testing special characters in node ID") +// 特殊文字を含むノードID(新規作成時) +local specialNode +specialNode = new P2PBox("node-with-special_chars.123", world) +print("Special node created: " + specialNode.getNodeId()) + +print("\n7. Testing rapid fire messages") +// 高速連続メッセージ送信 +local node2 +node2 = new P2PBox("node2", world) +node2.on("rapid", "rapid_handler") + +local i +i = 0 +loop(i < 10) { + node1.send("rapid", "Message " + i, "node2") + i = i + 1 +} +print("Sent 10 rapid messages") + +print("\n8. Testing null data send") +// nullデータの送信 +local nullData +nullData = new NullBox() +result = node1.send("null_test", nullData, "node2") +print("Null data sent: " + result) + +print("\n9. Testing listener with same intent multiple times") +// 同じintentに複数のリスナー登録 +node1.on("multi", "handler1") +node1.on("multi", "handler2") +node1.on("multi", "handler3") +print("Multiple handlers registered for same intent") + +print("\n10. Testing IntentBox message processing") +// IntentBoxの内部メッセージ処理 +result = world.processMessages() +print("IntentBox processed messages: " + result) + +print("\n=== Edge Cases Test Complete ===") \ No newline at end of file diff --git a/local_tests/test_p2p_message_types.nyash b/local_tests/test_p2p_message_types.nyash new file mode 100644 index 00000000..fd03eab9 --- /dev/null +++ b/local_tests/test_p2p_message_types.nyash @@ -0,0 +1,66 @@ +// 🧪 P2PBox メッセージ型テスト +// 様々なデータ型のメッセージ送受信を検証 + +print("=== P2PBox Message Types Test ===") + +// 通信世界とノードを作成 +local world +world = new IntentBox() + +local sender +local receiver +sender = new P2PBox("sender", world) +receiver = new P2PBox("receiver", world) + +// 各種データ型のリスナーを登録 +receiver.on("string_msg", "handle_string") +receiver.on("integer_msg", "handle_integer") +receiver.on("bool_msg", "handle_bool") +receiver.on("null_msg", "handle_null") +receiver.on("array_msg", "handle_array") +receiver.on("map_msg", "handle_map") + +print("\n1. String message test") +sender.send("string_msg", "Hello, P2P World!", "receiver") + +print("\n2. Integer message test") +sender.send("integer_msg", 42, "receiver") + +print("\n3. Boolean message test") +sender.send("bool_msg", true, "receiver") + +print("\n4. Null message test") +local nullValue +nullValue = new NullBox() +sender.send("null_msg", nullValue, "receiver") + +print("\n5. Array message test (NOT IMPLEMENTED YET)") +// TODO: ArrayBox実装後に有効化 +// local arr +// arr = new ArrayBox() +// arr.push("item1") +// arr.push("item2") +// sender.send("array_msg", arr, "receiver") + +print("\n6. Map message test") +local data +data = new MapBox() +data.set("name", "Alice") +data.set("age", 25) +data.set("active", true) +sender.send("map_msg", data, "receiver") + +print("\n7. Complex nested data test") +local complex +complex = new MapBox() +complex.set("type", "user_profile") + +local details +details = new MapBox() +details.set("username", "alice123") +details.set("email", "alice@example.com") +complex.set("details", details) + +sender.broadcast("complex_data", complex) + +print("\n=== Message Types Test Complete ===") \ No newline at end of file diff --git a/local_tests/test_p2p_simple.nyash b/local_tests/test_p2p_simple.nyash new file mode 100644 index 00000000..734e14b7 --- /dev/null +++ b/local_tests/test_p2p_simple.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_pack_syntax.nyash b/local_tests/test_pack_syntax.nyash new file mode 100644 index 00000000..014196d3 --- /dev/null +++ b/local_tests/test_pack_syntax.nyash @@ -0,0 +1,108 @@ +// 🎁 pack構文の包括的テスト + +// 1. 基本的なpack構文 +box Animal { + init { name, age } + + pack(animalName, animalAge) { + me.name = animalName + me.age = animalAge + } + + speak() { + return me.name + " (age " + me.age + ") makes a sound" + } +} + +// 2. fromデリゲーションでのpack +box Dog from Animal { + init { breed } + + pack(dogName, dogAge, dogBreed) { + from Animal.pack(dogName, dogAge) // 親のpackを呼び出し + me.breed = dogBreed + } + + override speak() { + return me.name + " (age " + me.age + ", " + me.breed + ") barks: Woof!" + } +} + +// 3. 混在形式(packと従来形式の共存) +box Cat from Animal { + init { color } + + Cat(catName, catAge, catColor) { // 従来形式 + from Animal.pack(catName, catAge) // 親はpack使用 + me.color = catColor + } + + override speak() { + return me.name + " (age " + me.age + ", " + me.color + ") meows: Meow!" + } +} + +// 4. pack単独使用テスト +box Bird { + init { species, canFly } + + // pack単独 - Box哲学に最適! + pack(birdSpecies, flying) { + me.species = birdSpecies + " (pack使用)" + me.canFly = flying + } + + describe() { + local flyText + if me.canFly { + flyText = "can fly" + } else { + flyText = "cannot fly" + } + return me.species + " - " + flyText + } +} + +// テスト実行 +print("=== 🎁 pack構文テスト ===") + +// 1. 基本的なpack +local animal +animal = new Animal("Generic", 5) +print("Animal: " + animal.speak()) + +// 2. デリゲーションでのpack +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. pack単独使用確認 +local bird +bird = new Bird("Eagle", true) +print("Bird: " + bird.describe()) + +// 5. 引数なしpack +box SimpleBox { + init { message } + + pack() { // 引数なしpack + me.message = "Packed with love! 🎁" + } + + getMessage() { + return me.message + } +} + +local simple +simple = new SimpleBox() +print("SimpleBox: " + simple.getMessage()) + +print("") +print("✅ pack構文テスト完了!") +print("🎉 Everything is Box - Now Everything is Packed!") \ No newline at end of file diff --git a/local_tests/test_random_box.nyash b/local_tests/test_random_box.nyash new file mode 100644 index 00000000..13c33811 --- /dev/null +++ b/local_tests/test_random_box.nyash @@ -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!") \ No newline at end of file diff --git a/local_tests/test_weak_basic_fixed.nyash b/local_tests/test_weak_basic_fixed.nyash new file mode 100644 index 00000000..ed37cc27 --- /dev/null +++ b/local_tests/test_weak_basic_fixed.nyash @@ -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" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_comprehensive.nyash b/local_tests/test_weak_comprehensive.nyash new file mode 100644 index 00000000..3091b045 --- /dev/null +++ b/local_tests/test_weak_comprehensive.nyash @@ -0,0 +1,84 @@ +// Comprehensive weak reference validation test + +box Parent { + init { name } + + pack(parentName) { + me.name = parentName + } + + getName() { + return me.name + } +} + +box Child { + init { weak parent, id } + + pack(childId) { + me.id = childId + me.parent = 0 // Initialize as null + } + + setParent(p) { + me.parent = p + } + + // Safe check that doesn't call toString on null + checkParentStatus() { + local parentRef = me.parent + + // Check if we got a valid parent reference + local console = new ConsoleBox() + console.log("Child " + me.id.toString() + " checking parent...") + + // We expect null after parent drop, which should not cause errors + return "checked" + } + + getId() { + return me.id + } +} + +static box Main { + main() { + print("=== Comprehensive Weak Reference Validation ===") + + local parent1 = new Parent("Parent1") + local parent2 = new Parent("Parent2") + + local child1 = new Child(1) + local child2 = new Child(2) + local child3 = new Child(3) + + print("Step 1: Set up multiple weak references") + child1.setParent(parent1) + child2.setParent(parent1) // Two children reference same parent + child3.setParent(parent2) // One child references different parent + + print("Step 2: Verify all children can access parents") + child1.checkParentStatus() + child2.checkParentStatus() + child3.checkParentStatus() + + print("Step 3: Drop parent1 (affects child1 and child2)") + parent1 = 0 // This should invalidate child1 and child2's references + + print("Step 4: Check all children after parent1 drop") + child1.checkParentStatus() // Should be null now + child2.checkParentStatus() // Should be null now + child3.checkParentStatus() // Should still be valid (different parent) + + print("Step 5: Drop parent2 (affects child3)") + parent2 = 0 // This should invalidate child3's reference + + print("Step 6: Final check - all should be null now") + child1.checkParentStatus() // Still null + child2.checkParentStatus() // Still null + child3.checkParentStatus() // Now null too + + print("✅ Weak reference system validation complete!") + return "All tests passed" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_detection.nyash b/local_tests/test_weak_detection.nyash new file mode 100644 index 00000000..5f54b3ff --- /dev/null +++ b/local_tests/test_weak_detection.nyash @@ -0,0 +1,38 @@ +// Simplified weak reference detection test + +box Parent { + init { child } + + pack() { + me.child = new Child() + me.child.setParent(me) // This should detect weak assignment + } + + getChild() { + return me.child + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p // Should detect weak field assignment + } + + checkParent() { + return me.parent // Should detect weak field access + } +} + +static box Main { + main() { + local p = new Parent() + local child = p.getChild() + + print("Testing weak field access...") + local parent_ref = child.checkParent() + + return "weak reference detection test completed" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_fini_prohibition.nyash b/local_tests/test_weak_fini_prohibition.nyash new file mode 100644 index 00000000..ae1baa6c --- /dev/null +++ b/local_tests/test_weak_fini_prohibition.nyash @@ -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" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_lifecycle.nyash b/local_tests/test_weak_lifecycle.nyash new file mode 100644 index 00000000..46a1bd8d --- /dev/null +++ b/local_tests/test_weak_lifecycle.nyash @@ -0,0 +1,62 @@ +// Advanced weak reference auto-nil demonstration + +box Parent { + init { name, child } + + pack(parentName) { + me.name = parentName + me.child = new Child() + me.child.setParent(me) // This creates a weak reference + } + + getChild() { + return me.child + } + + getName() { + return me.name + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p + } + + getParentInfo() { + // Check the weak reference + return "Parent reference state checked" + } + + // Test method to manually check the weak field value + checkWeakParent() { + return me.parent + } +} + +static box Main { + main() { + print("=== Weak Reference Auto-Nil Test ===") + + local parent = new Parent("TestParent") + local child = parent.getChild() + + print("Step 1: Initial setup complete") + print("Initial check: " + child.getParentInfo()) + + // Check initial weak reference value + local parentRef = child.checkWeakParent() + print("Initial parent ref exists: yes") + + print("Step 2: Simulating parent 'drop' by setting to 0") + parent = 0 // This should trigger weak reference invalidation + + print("Step 3: Checking weak reference after parent drop") + local parentRef2 = child.checkWeakParent() + print("After drop parent ref exists: still checking") + + return "weak reference lifecycle test completed" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_reference_basic.nyash b/local_tests/test_weak_reference_basic.nyash new file mode 100644 index 00000000..eafd4be6 --- /dev/null +++ b/local_tests/test_weak_reference_basic.nyash @@ -0,0 +1,50 @@ +// Basic weak reference test case + +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 != null + } + + getParentInfo() { + if me.parent != null { + 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 = 0 // Setting to 0 instead of null to avoid the undefined variable issue + + print("After parent dropped: " + child.getParentInfo()) + + return "weak reference test completed" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_reference_complete.nyash b/local_tests/test_weak_reference_complete.nyash new file mode 100644 index 00000000..64a12977 --- /dev/null +++ b/local_tests/test_weak_reference_complete.nyash @@ -0,0 +1,54 @@ +// Complete weak reference auto-nil test + +box Parent { + init { name, child } + + pack(parentName) { + me.name = parentName + me.child = new Child() + me.child.setParent(me) // This should create a weak reference + } + + getChild() { + return me.child + } + + getName() { + return me.name + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p + } + + getParentInfo() { + // Instead of comparing to null, check if parent field exists and is valid + local parentExists = me.parent != 0 // Using 0 as a null check workaround + if parentExists { + return "Parent exists" + } else { + return "Parent is null (dropped)" + } + } +} + +static box Main { + main() { + local p = new Parent("TestParent") + local child = p.getChild() + + print("Initial: " + child.getParentInfo()) + + // Test the weak reference system + // When p goes out of scope, child.parent should automatically become null + p = 0 // Setting to 0 to simulate parent dropping + + print("After drop: " + child.getParentInfo()) + + return "weak reference auto-nil test completed" + } +} \ No newline at end of file diff --git a/local_tests/test_weak_simple.nyash b/local_tests/test_weak_simple.nyash new file mode 100644 index 00000000..429182fa --- /dev/null +++ b/local_tests/test_weak_simple.nyash @@ -0,0 +1,54 @@ +// Simple direct test of weak reference auto-nil behavior + +box Parent { + init { name } + + pack(parentName) { + me.name = parentName + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p + } + + // Direct access to weak field + getParent() { + return me.parent + } + + // Check if parent is null directly + isParentNull() { + local parentRef = me.parent + print("Direct parent access returned: " + parentRef.toString()) + return parentRef + } +} + +static box Main { + main() { + print("=== Simple Weak Reference Test ===") + + local parent = new Parent("TestParent") + local child = new Child() + + print("Step 1: Set parent") + child.setParent(parent) + print("Parent before drop: " + child.getParent().toString()) + + print("Step 2: Drop parent") + parent = 0 // This should trigger weak reference invalidation + + print("Step 3: Check parent after drop") + local parentAfterDrop = child.getParent() + print("Parent after drop: " + parentAfterDrop.toString()) + + print("Step 4: Direct null check") + child.isParentNull() + + return "Simple test completed" + } +} \ No newline at end of file diff --git a/local_tests/test_working_weak_demo.nyash b/local_tests/test_working_weak_demo.nyash new file mode 100644 index 00000000..eab6b762 --- /dev/null +++ b/local_tests/test_working_weak_demo.nyash @@ -0,0 +1,60 @@ +// Working demonstration of weak reference auto-nil behavior + +box Parent { + init { name } + + pack(parentName) { + me.name = parentName + } + + getName() { + return me.name + } +} + +box Child { + init { weak parent } // weak modifier on parent field + + setParent(p) { + me.parent = p + } + + getParentInfo() { + // This method will use the weak field access system + // which automatically returns null if the parent is dropped + if me.parent == 0 { + return "Parent is null (dropped)" + } else { + return "Parent exists" + } + } + + // Direct weak field access for testing + accessWeakParent() { + return me.parent + } +} + +static box Main { + main() { + print("=== Weak Reference Auto-Nil Demonstration ===") + + local parent = new Parent("TestParent") + local child = new Child() + + print("Step 1: Setting up parent-child relationship") + child.setParent(parent) + print("After setup: " + child.getParentInfo()) + + print("Step 2: Simulating parent 'drop' (set to 0)") + parent = 0 // This should trigger weak reference invalidation + + print("Step 3: Checking child's parent reference after drop") + print("After drop: " + child.getParentInfo()) + + print("Step 4: Direct weak field access test") + local directAccess = child.accessWeakParent() + + return "Auto-nil demonstration completed successfully" + } +} \ No newline at end of file