diff --git a/docs/CURRENT_TASK.md b/docs/CURRENT_TASK.md index 99c4b48a..a13b23e4 100644 --- a/docs/CURRENT_TASK.md +++ b/docs/CURRENT_TASK.md @@ -361,8 +361,72 @@ if let TokenType::IDENTIFIER(id) = &self.current_token().token_type { - パフォーマンステスト基盤 --- -**現在状況**: ✅ **Phase 9.75i完了 - 全アプリ動作確認!** 🎉 -**最終更新**: 2025-08-16 19:15 +**現在状況**: 🔬 **WASM Canvas機能研究中** +**最終更新**: 2025-08-16 22:30 + +## 🌐 **WASM研究メモ** + +### **実行フロー: MIR → WAT → WASM** +``` +Nyashソースコード + ↓ (Parser/AST) +MIR (中間表現) + ↓ (WasmCodegen) +WAT (WebAssembly Text形式) + ↓ (wabt::wat2wasm) +WASM (バイナリ形式) +``` + +### **現在の実装状況** +- ✅ **console.log()**: ConsoleBox経由で動作 +- ❌ **canvas操作**: ExternCall定義はあるが、canvasオブジェクトが未実装 +- ✅ **WAT生成**: UTF-8エラー修正済み、正常に出力 + +### **Canvas実装の選択肢** + +#### **Option 1: CanvasBox実装(推奨)** +```nyash +// ConsoleBoxと同様のアプローチ +local canvas = new CanvasBox("canvas_id", 800, 600) +canvas.fillRect(10, 10, 100, 50, "#FF0000") +canvas.fillText("Hello", 50, 100, "#000000", "20px Arial") +``` + +**メリット**: +- Everything is Box哲学に合致 +- 既存のBoxパターンと一貫性 +- 型安全性の確保 + +#### **Option 2: グローバルcanvasオブジェクト** +```nyash +// MIRビルダーで特別扱い +canvas.fillRect(10, 10, 100, 50, 255, 0, 0, 255) +``` + +**メリット**: +- JavaScriptのCanvas APIに近い +- 実装が簡単 + +**デメリット**: +- Everything is Box哲学から逸脱 +- 特殊ケースの増加 + +#### **Option 3: 標準ライブラリ拡張** +```nyash +using nyashstd + +canvas.create("myCanvas", 800, 600) +canvas.fillRect(10, 10, 100, 50) +``` + +**メリット**: +- 名前空間で整理 +- 拡張性が高い + +### **次のステップ** +1. CanvasBox実装の設計 +2. ExternCall統合 +3. WASMブラウザー実行環境の構築 ## 🔧 **Parser リファクタリング完了報告** diff --git a/local_tests/test_canvas_wasm.nyash b/local_tests/test_canvas_wasm.nyash new file mode 100644 index 00000000..35903687 --- /dev/null +++ b/local_tests/test_canvas_wasm.nyash @@ -0,0 +1,14 @@ +// Canvas WASM test - ExternCall経由でCanvas操作 +local result = 42 + +// 赤い矩形を描画 +canvas.fillRect(10, 10, 100, 50, 255, 0, 0, 255) + +// 青い矩形を描画 +canvas.fillRect(120, 10, 100, 50, 0, 0, 255, 255) + +// 黒いテキストを描画 +canvas.fillText("Hello Nyash!", 10, 100, 0, 0, 0, 255, 24, "Arial") + +// コンソールに出力 +console.log("Canvas drawing complete!") \ No newline at end of file diff --git a/local_tests/test_console_wasm.nyash b/local_tests/test_console_wasm.nyash new file mode 100644 index 00000000..43142d28 --- /dev/null +++ b/local_tests/test_console_wasm.nyash @@ -0,0 +1,7 @@ +// Console WASM test - ExternCall経由でconsole操作 +console.log("Hello from Nyash WASM!") + +// 複数の値をテスト +local result = 42 +console.log("The answer is:") +console.log(result.toString()) \ No newline at end of file diff --git a/local_tests/test_wasm_basic.nyash b/local_tests/test_wasm_basic.nyash new file mode 100644 index 00000000..21df0990 --- /dev/null +++ b/local_tests/test_wasm_basic.nyash @@ -0,0 +1,14 @@ +// Basic WASM test with ConsoleBox +static box Main { + init { console } + + main() { + me.console = new ConsoleBox() + me.console.log("Hello from Nyash WASM!") + + local result = 42 + me.console.log("The answer is: " + result.toString()) + + return "WASM test complete" + } +} \ No newline at end of file diff --git a/local_tests/test_wasm_basic.wat b/local_tests/test_wasm_basic.wat new file mode 100644 index 00000000..e13ba5e5 --- /dev/null +++ b/local_tests/test_wasm_basic.wat @@ -0,0 +1,348 @@ +(module + (import "env" "print" (func $print (param i32) )) + (import "env" "print_str" (func $print_str (param i32 i32) )) + (import "env" "console_log" (func $console_log (param i32 i32) )) + (import "env" "canvas_fillRect" (func $canvas_fillRect (param i32 i32 i32 i32 i32 i32 i32 i32) )) + (import "env" "canvas_fillText" (func $canvas_fillText (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) )) + (import "env" "box_to_string" (func $box_to_string (param i32) (result i32))) + (import "env" "box_print" (func $box_print (param i32) )) + (import "env" "box_equals" (func $box_equals (param i32 i32) (result i32))) + (import "env" "box_clone" (func $box_clone (param i32) (result i32))) + (memory (export "memory") 1) + (data (i32.const 4096) "\5f\5f\6d\65\5f\5f") + (data (i32.const 4102) "\43\6f\6e\73\6f\6c\65\42\6f\78") + (data (i32.const 4121) "\49\6e\74\65\67\65\72\42\6f\78") + (data (i32.const 4112) "\53\74\72\69\6e\67\42\6f\78") + (global $heap_ptr (mut i32) (i32.const 2048)) + (func $malloc (param $size i32) (result i32) + (local $ptr i32) + (local $aligned_size i32) + + ;; Align size to 4-byte boundary + local.get $size + i32.const 3 + i32.add + i32.const -4 + i32.and + local.set $aligned_size + + ;; Get current heap pointer + global.get $heap_ptr + local.set $ptr + + ;; Advance heap pointer by aligned size + global.get $heap_ptr + local.get $aligned_size + i32.add + global.set $heap_ptr + + ;; Return allocated pointer + local.get $ptr + ) + (func $box_alloc (param $type_id i32) (param $field_count i32) (result i32) + (local $ptr i32) + (local $total_size i32) + + ;; Calculate total size: header (12) + fields (field_count * 4) + local.get $field_count + i32.const 4 + i32.mul + i32.const 12 + i32.add + local.set $total_size + + ;; Allocate memory + local.get $total_size + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + local.get $type_id + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + local.get $field_count + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_stringbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 20 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4097 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 2 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_integerbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4098 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_boolbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4099 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_databox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4101 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $main (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) (local $6 i32) (local $7 i32) (local $8 i32) (local $9 i32) (local $10 i32) (local $11 i32) (local $12 i32) (local $13 i32) (local $14 i32) (local $15 i32) (local $16 i32) (local $17 i32) (local $18 i32) + nop + call $alloc_stringbox + local.set $0 + local.get $0 + i32.const 12 + i32.add + i32.const 4096 + i32.store + local.get $0 + i32.const 16 + i32.add + i32.const 6 + i32.store + call $alloc_stringbox + local.set $2 + local.get $2 + i32.const 12 + i32.add + i32.const 4102 + i32.store + local.get $2 + i32.const 16 + i32.add + i32.const 10 + i32.store + local.get $2 + local.set $1 + local.get $0 + i32.const 12 + i32.add + local.get $1 + i32.store + call $alloc_stringbox + local.set $3 + local.get $3 + i32.const 12 + i32.add + i32.const 4096 + i32.store + local.get $3 + i32.const 16 + i32.add + i32.const 6 + i32.store + local.get $3 + i32.const 12 + i32.add + i32.load + local.set $4 + call $alloc_stringbox + local.set $6 + local.get $6 + i32.const 12 + i32.add + i32.const 4112 + i32.store + local.get $6 + i32.const 16 + i32.add + i32.const 9 + i32.store + local.get $6 + local.set $5 + ;; log() implementation for ValueId(4) + local.get $4 + local.get $5 + call $console_log + i32.const 0 + local.set $7 + call $alloc_stringbox + local.set $9 + local.get $9 + i32.const 12 + i32.add + i32.const 4121 + i32.store + local.get $9 + i32.const 16 + i32.add + i32.const 10 + i32.store + local.get $9 + local.set $8 + call $alloc_stringbox + local.set $10 + local.get $10 + i32.const 12 + i32.add + i32.const 4096 + i32.store + local.get $10 + i32.const 16 + i32.add + i32.const 6 + i32.store + local.get $10 + i32.const 12 + i32.add + i32.load + local.set $11 + call $alloc_stringbox + local.set $13 + local.get $13 + i32.const 12 + i32.add + i32.const 4112 + i32.store + local.get $13 + i32.const 16 + i32.add + i32.const 9 + i32.store + local.get $13 + local.set $12 + ;; toString() implementation for ValueId(8) + local.get $8 + call $box_to_string + local.set $14 + local.get $12 + local.get $14 + i32.add + local.set $15 + ;; log() implementation for ValueId(11) + local.get $11 + local.get $15 + call $console_log + i32.const 0 + local.set $16 + call $alloc_stringbox + local.set $18 + local.get $18 + i32.const 12 + i32.add + i32.const 4112 + i32.store + local.get $18 + i32.const 16 + i32.add + i32.const 9 + i32.store + local.get $18 + local.set $17 + local.get $17 + return + ) + (export "main" (func $main)) +)