# Nyash 2モード設計:スクリプトモード vs アプリケーションモード ## 🎯 設計理念 Nyashは「明示性重視」と「使いやすさ」の両方を実現するため、**2つの実行モード**を永続的にサポートする。移行や非推奨化は行わず、それぞれのモードが異なる用途で輝く設計とする。 ## 📊 モード比較 ### スクリプトモード(Script Mode) ```nyash // ファイル:hello.nyash name = "Nyash" count = 42 print("Hello, " + name + "!") print("The answer is " + count) // 関数も自由に定義 function greet(who) { print("Greetings, " + who) } greet("World") ``` ### アプリケーションモード(Application Mode) ```nyash // ファイル:app.nyash static box Main { init { name, count } main() { me.name = "Nyash" me.count = 42 me.greet() } greet() { print("Hello, " + me.name + "!") print("The answer is " + me.count) } } ``` ## 🔍 自動検出ルール ### 基本原則:「見た目で分かる」 1. **`static box`が1つでもある** → アプリケーションモード 2. **`static box`が1つもない** → スクリプトモード 3. **明示的な指定は不要**(ファイル内容で自動判定) ### 検出アルゴリズム ```rust fn detect_mode(ast: &AST) -> ExecutionMode { // ASTを走査してstatic boxの存在をチェック for node in ast.walk() { match node { ASTNode::StaticBoxDeclaration { .. } => { return ExecutionMode::Application; } _ => continue, } } ExecutionMode::Script } ``` ## 🌟 各モードの特徴 ### スクリプトモード #### 利点 - **素早いプロトタイピング** - アイデアをすぐ試せる - **学習曲線が緩やか** - 初心者に優しい - **REPL完全互換** - コピペで動く - **ワンライナー対応** - `nyash -e "print(2+2)"` #### 変数スコープ ```nyash // グローバルスコープに直接定義 x = 10 y = 20 // 関数内でもアクセス可能 function sum() { return x + y // グローバル変数を参照 } // ローカル変数 function calculate() { local temp = 100 // 関数ローカル return temp + x } ``` #### エラーハンドリング ```nyash // 未定義変数アクセス → 実行時エラー print(undefined_var) // Runtime Error: undefined variable 'undefined_var' // 型エラーも実行時 x = "hello" y = x + 10 // Runtime Error: cannot add String and Integer ``` ### アプリケーションモード #### 利点 - **明示的な変数管理** - どこで何が定義されているか明確 - **静的解析可能** - IDEサポートが充実 - **大規模開発対応** - チーム開発で威力を発揮 - **名前空間の分離** - static box単位でスコープ管理 #### 変数スコープ ```nyash static box Calculator { init { x, y, result } // 必ず宣言 calculate() { // me.を通じてアクセス(明示的) me.result = me.x + me.y // ローカル変数 local temp = me.result * 2 return temp } } // ❌ エラー:グローバル変数は定義できない global_var = 10 // Error: Global variables not allowed in application mode ``` #### コンパイル時チェック ```nyash static box TypedCalc { init { value } setValue(v) { // 将来的に型推論や型チェックも可能 me.value = v } calculate() { // 未定義フィールドアクセス → コンパイルエラー return me.undefined_field // Error: 'undefined_field' not declared in init } } ``` ## 🚀 REPL統合 ### REPLの動作 ```bash $ nyash Nyash REPL v1.0 (Script Mode) > x = 42 > print(x) 42 > function double(n) { return n * 2 } > print(double(x)) 84 # アプリケーションモードのコードも貼り付け可能 > static box Counter { . init { count } . increment() { me.count = me.count + 1 } . } > c = new Counter() > c.increment() > print(c.count) 1 ``` ### モード切り替え ```bash # 通常起動(スクリプトモード) $ nyash # アプリケーションモードでREPL起動(将来実装) $ nyash --app-mode Nyash REPL v1.0 (Application Mode) > x = 42 # Error: Global variables not allowed > static box Main { ... } # OK ``` ## 📝 実装詳細 ### パーサーの拡張 ```rust pub struct Parser { mode: ExecutionMode, // スクリプトモードでは緩い解析 // アプリケーションモードでは厳格な解析 } impl Parser { pub fn parse(&mut self, source: &str) -> Result { let ast = self.parse_initial(source)?; self.mode = detect_mode(&ast); match self.mode { ExecutionMode::Script => self.validate_script_mode(&ast), ExecutionMode::Application => self.validate_app_mode(&ast), } } } ``` ### インタープリターの対応 ```rust impl Interpreter { pub fn execute(&mut self, ast: &AST, mode: ExecutionMode) -> Result { match mode { ExecutionMode::Script => { // グローバル変数を許可 self.allow_globals = true; self.execute_script(ast) } ExecutionMode::Application => { // グローバル変数を禁止 self.allow_globals = false; self.execute_application(ast) } } } } ``` ## 🎨 ベストプラクティス ### いつスクリプトモードを使うか 1. **データ処理スクリプト** ```nyash data = readFile("input.csv") lines = data.split("\n") for line in lines { fields = line.split(",") print(fields[0] + ": " + fields[1]) } ``` 2. **設定ファイル** ```nyash # config.nyash server_host = "localhost" server_port = 8080 debug_mode = true ``` 3. **テストコード** ```nyash # test_math.nyash assert(2 + 2 == 4) assert(10 / 2 == 5) print("All tests passed!") ``` ### いつアプリケーションモードを使うか 1. **Webアプリケーション** ```nyash static box WebServer { init { port, routes } start() { me.port = 8080 me.routes = new MapBox() me.setupRoutes() me.listen() } } ``` 2. **ゲーム開発** ```nyash static box Game { init { player, enemies, score } main() { me.initialize() loop(me.isRunning()) { me.update() me.render() } } } ``` 3. **ライブラリ開発** ```nyash static box MathLib { init { precision } static factorial(n) { if n <= 1 { return 1 } return n * MathLib.factorial(n - 1) } } ``` ## 🔮 将来の拡張 ### 混在モード(検討中) ```nyash #!script // ファイルの最初の部分はスクリプトモード config = loadConfig() debug = true #!application // ここからアプリケーションモード static box Main { init { config } main() { // スクリプト部分の変数を参照できる? me.config = ::config // グローバルスコープ参照構文 } } ``` ### プロジェクト設定 ```toml # nyash.toml [project] name = "my-app" default_mode = "application" # プロジェクト全体のデフォルト [scripts] # 特定のファイルはスクリプトモードで実行 mode = "script" files = ["scripts/*.nyash", "tests/*.nyash"] ``` ## 🌈 他言語との比較 ### Python - **類似点**: REPLとファイル実行で同じ動作 - **相違点**: Nyashはモードを明確に分離 ### JavaScript/TypeScript - **類似点**: strictモードの概念 - **相違点**: Nyashは見た目で判定(`"use strict"`不要) ### C# - **優位性**: - トップレベルステートメントより柔軟 - 明示的なモード分離で混乱なし - REPLとの完全な統合 ### Ruby - **類似点**: スクリプトとクラスベースの両対応 - **相違点**: Nyashはより明確なモード分離 ## 🎯 まとめ Nyashの2モード設計は: 1. **移行不要** - 両モード永続サポート 2. **自動判定** - ファイル内容で自動切り替え 3. **REPL対応** - 同じルールで直感的 4. **いいとこ取り** - 用途に応じて最適なモードを選択 この設計により、Nyashは「**初心者に優しく、プロに強力**」な言語となる。