Files
hakorune/NYASHFLOW_PROJECT_HANDOVER.md
Moe Charm e7f6666917 🎨 feat: EguiBox GUI開発基盤完成 + パーサー無限ループバグ修正
## 🚀 主要機能追加
### EguiBox - GUI開発基盤
- Windows版GUIメモ帳アプリ (simple_notepad.rs, nyash_notepad_jp.rs)
- 日本語フォント対応 (NotoSansJP-VariableFont_wght.ttf)
- BMPアイコン表示システム (c_drive_icon.bmp)
- Windowsエクスプローラー風アプリ (nyash_explorer.rs)
- アイコン抽出システム (test_icon_extraction.rs)

### ビジュアルプログラミング準備
- NyashFlow プロジェクト設計完成 (NYASHFLOW_PROJECT_HANDOVER.md)
- ビジュアルノードプロトタイプ基盤
- WebAssembly対応準備

## 🔧 重大バグ修正
### パーサー無限ループ問題 (3引数メソッド呼び出し)
- 原因: メソッドパラメータ解析ループの予約語処理不備
- 修正: src/parser/mod.rs - 非IDENTIFIERトークンのエラーハンドリング追加
- 効果: "from"等の予約語で適切なエラー報告、ハング→瞬時エラー

### MapBoxハング問題調査
- MapBox+3引数メソッド呼び出し組み合わせ問題特定
- バグレポート作成 (MAPBOX_HANG_BUG_REPORT.md)
- 事前評価vs必要時評価の設計問題明確化

## 🧹 コード品質向上
- box_methods.rs を8モジュールに機能分離
- 一時デバッグコード全削除 (eprintln\!, unsafe等)
- 構文チェック通過確認済み

## 📝 ドキュメント整備
- CLAUDE.md にGUI開発セクション追加
- Gemini/ChatGPT先生相談ログ保存 (sessions/)
- 段階的デバッグ手法確立

## 🎯 次の目標
- must_advance\!マクロ実装 (無限ループ早期検出)
- コマンド引数でデバッグ制御 (--debug-fuel)
- MapBox問題の根本修正

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-10 07:54:03 +09:00

15 KiB
Raw Blame History

🎨 NyashFlow プロジェクト引き継ぎドキュメント

📅 作成日: 2025-01-09

👤 作成者: Claude + ユーザー(にゃ〜)


🌟 プロジェクト概要

🎯 NyashFlowとは

Nyashプログラミング言語のビジュアルプログラミング環境

  • 「Everything is Box」の哲学を視覚的に表現
  • Boxをドラッグ&ドロップでつなげてプログラミング
  • 教育的価値の高いツールを目指す

🚀 プロジェクトの経緯

1 始まりegui研究

  • NyashにGUI機能EguiBoxを実装
  • Windows版メモ帳、エクスプローラー風アプリを作成
  • BMPアイコン表示まで成功

2 ビジュアルプログラミングへの発展

  • eguiの可能性を探る中で、ードベースUIの構想が生まれる
  • 「Everything is Box」を視覚化するアイデア
  • 教育現場での活用を想定

3 CharmFlow v5からの学び

  • ユーザーが以前作成した大規模プロジェクト
  • JavaScript + NyaMeshP2Pで実装
  • 失敗から学んだこと
    • カプセル化の欠如 → スパゲティコード化
    • 役割分担の不明確 → 保守困難
    • 過剰な機能 → 複雑化

4 NyashFlowの方向性決定

  • Rust + WebAssemblyで実装
  • Nyashとは別プロジェクトとして独立
  • シンプルさを最優先

🏗️ 技術設計

📐 アーキテクチャ

基本構成

nyashflow/
├── Cargo.toml              # プロジェクト設定
├── src/
│   ├── lib.rs              # ライブラリエントリ
│   ├── main.rs             # デスクトップ版エントリ
│   ├── visual/             # 🎨 ビジュアル表示層
│   │   ├── mod.rs
│   │   ├── node_renderer.rs      # ノード描画
│   │   ├── connection_renderer.rs # 接続線描画
│   │   └── canvas_manager.rs     # キャンバス管理
│   ├── execution/          # ⚡ 実行エンジン層
│   │   ├── mod.rs
│   │   ├── interpreter_bridge.rs  # Nyashインタープリタ連携
│   │   └── data_flow.rs          # データフロー管理
│   ├── interaction/        # 🖱️ ユーザー操作層
│   │   ├── mod.rs
│   │   ├── drag_drop.rs          # ドラッグ&ドロップ
│   │   ├── selection.rs          # 選択処理
│   │   └── context_menu.rs       # 右クリックメニュー
│   ├── model/              # 📦 データモデル層
│   │   ├── mod.rs
│   │   ├── visual_node.rs        # ノード定義
│   │   ├── connection.rs         # 接続定義
│   │   └── project.rs            # プロジェクト管理
│   └── wasm/               # 🌐 WebAssembly層
│       ├── mod.rs
│       └── bridge.rs             # JS連携
├── web/                    # 🌐 Web用リソース
│   ├── index.html
│   ├── style.css
│   └── pkg/                      # wasm-pack出力
└── examples/               # 📚 サンプル
    └── basic_flow.rs

設計原則

1. 徹底的なカプセル化

pub struct VisualNode {
    // 🔒 すべてプライベート
    id: NodeId,
    node_type: BoxType,
    position: Pos2,
    #[serde(skip)]
    internal_state: NodeState,
}

impl VisualNode {
    // 🌍 公開APIは最小限
    pub fn get_id(&self) -> NodeId { self.id }
    pub fn get_type(&self) -> &BoxType { &self.node_type }
    pub fn set_position(&mut self, pos: Pos2) { 
        // バリデーション付き
        if self.validate_position(pos) {
            self.position = pos;
        }
    }
}

2. 明確な責任分離

// ❌ 悪い例CharmFlowの失敗
impl EverythingManager {
    fn handle_everything(&mut self, event: Event) {
        // 描画もイベントも実行も全部...
    }
}

// ✅ 良い例(単一責任)
impl NodeRenderer {
    pub fn render(&self, node: &VisualNode, ui: &mut Ui) {
        // 描画だけ!
    }
}

impl DragDropHandler {
    pub fn handle_drag(&mut self, event: DragEvent) {
        // ドラッグ処理だけ!
    }
}

3. コード品質の維持

  • 各ファイル100行以内を目標
  • 関数は30行以内
  • ネストは3階層まで
  • 必ずテストを書く

💻 実装詳細

🎨 ビジュアルノードシステム

ノードの種類(初期実装)

#[derive(Debug, Clone, PartialEq)]
pub enum BoxType {
    // 基本Box
    StringBox,
    IntegerBox,
    BoolBox,
    
    // 操作Box
    MathBox,
    ConsoleBox,
    
    // コンテナBox
    ArrayBox,
}

impl BoxType {
    pub fn color(&self) -> Color32 {
        match self {
            BoxType::StringBox => Color32::from_rgb(100, 149, 237),
            BoxType::IntegerBox => Color32::from_rgb(144, 238, 144),
            BoxType::MathBox => Color32::from_rgb(255, 182, 193),
            // ...
        }
    }
    
    pub fn icon(&self) -> &str {
        match self {
            BoxType::StringBox => "📝",
            BoxType::IntegerBox => "🔢",
            BoxType::MathBox => "🧮",
            // ...
        }
    }
}

接続システム

pub struct Connection {
    id: ConnectionId,
    from_node: NodeId,
    from_port: PortId,
    to_node: NodeId,
    to_port: PortId,
}

pub struct Port {
    id: PortId,
    name: String,
    port_type: PortType,
    data_type: DataType,
}

#[derive(Debug, Clone, PartialEq)]
pub enum PortType {
    Input,
    Output,
}

実行エンジン

Nyashインタープリタ連携

use nyash::interpreter::{NyashInterpreter, NyashValue};

pub struct ExecutionEngine {
    interpreter: NyashInterpreter,
    node_mapping: HashMap<NodeId, String>, // NodeId → Nyash変数名
}

impl ExecutionEngine {
    pub fn execute_flow(&mut self, nodes: &[VisualNode], connections: &[Connection]) -> Result<(), ExecutionError> {
        // 1. トポロジカルソート
        let sorted_nodes = self.topological_sort(nodes, connections)?;
        
        // 2. Nyashコード生成
        let nyash_code = self.generate_nyash_code(&sorted_nodes, connections);
        
        // 3. 実行
        self.interpreter.execute(&nyash_code)?;
        
        Ok(())
    }
}

🌐 WebAssembly統合

WASM Bridge

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct NyashFlowApp {
    #[wasm_bindgen(skip)]
    nodes: Vec<VisualNode>,
    #[wasm_bindgen(skip)]
    connections: Vec<Connection>,
}

#[wasm_bindgen]
impl NyashFlowApp {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        console_error_panic_hook::set_once();
        Self {
            nodes: vec![],
            connections: vec![],
        }
    }
    
    pub fn add_node(&mut self, node_type: &str, x: f32, y: f32) -> u32 {
        // ノード追加処理
    }
    
    pub fn connect_nodes(&mut self, from_id: u32, to_id: u32) -> Result<(), JsValue> {
        // 接続処理
    }
    
    pub fn execute(&self) -> Result<String, JsValue> {
        // 実行処理
    }
}

🚀 開発ロードマップ

Phase 1: MVP1-2週間

  • 基本的なノード表示
  • 3種類のBoxString, Integer, Console
  • ドラッグでノード移動
  • 接続線の表示
  • 簡単な実行ConsoleBoxでprint

Phase 2: 基本機能2-3週間

  • 全基本Boxタイプ実装
  • 接続の作成/削除
  • 右クリックメニュー
  • プロジェクト保存/読み込みJSON
  • 実行結果の表示

Phase 3: WebAssembly対応2週間

  • wasm-pack設定
  • Web用UI調整
  • ブラウザでの動作確認
  • GitHubPages公開

Phase 4: 高度な機能1ヶ月

  • カスタムBox作成
  • デバッグ機能(ステップ実行)
  • アニメーション(データフロー可視化)
  • テンプレート機能

📝 実装上の注意点

⚠️ CharmFlowの失敗を避ける

1. 過剰な機能を避ける

  • P2P通信 → 不要
  • プラグインシステム → Phase 4以降
  • 複雑なIntent → 直接的なデータフロー

2. コードレビューポイント

// 毎回チェック
- [ ] ファイルが100行を超えていないか?
- [ ] 関数が30行を超えていないか?
- [ ] Private Fieldsを使っているか
- [ ] 責任が単一か?
- [ ] テストを書いたか?

3. 定期的なリファクタリング

  • 週1回はコード全体を見直す
  • 重複を見つけたら即座に統合
  • 複雑になったら分割

🧪 テスト戦略

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_node_creation() {
        let node = VisualNode::new(BoxType::StringBox, Pos2::new(100.0, 100.0));
        assert_eq!(node.get_type(), &BoxType::StringBox);
    }
    
    #[test]
    fn test_connection_validation() {
        // StringBox → ConsoleBoxは接続可能
        assert!(Connection::can_connect(
            &BoxType::StringBox, 
            &PortType::Output,
            &BoxType::ConsoleBox, 
            &PortType::Input
        ));
    }
}

🎯 成功の指標

定量的指標

  • コード行数5,000行以内CharmFlowの1/10
  • ファイル数50個以内
  • テストカバレッジ80%以上
  • 起動時間1秒以内

定性的指標

  • 小学生でも使える直感性
  • Nyashの哲学が伝わる
  • メンテナンスが苦にならない
  • 拡張が容易

🔗 参考資料

技術資料

設計思想

  • CharmFlow v5の経験反面教師
  • 「Everything is Box」哲学
  • シンプル・イズ・ベスト

類似プロジェクト

  • Scratch教育的UI
  • Node-REDフロープログラミング
  • Unreal Engine Blueprintゲーム向け

💬 最後に

このプロジェクトは「プログラミングを視覚的に理解する」という夢を実現するものです。

CharmFlowの失敗から学び、Nyashの哲学を活かし、シンプルで美しいツールを作りましょう。

「Everything is Box」が「Everything is Visible Box」になる瞬間を楽しみにしています

にゃ〜🎨


🔮 P2PBox/intentbox設計の活用2025-01-09追記

🎯 NyaMesh設計から学ぶこと

核心概念の抽出

NyaMeshのP2PBoxintentboxから、NyashFlowに活用できる本質的な設計思想

  1. intentbox = 通信世界の定義

    • プロセス内、WebSocket、メモリ共有など
    • 通信の「場」を抽象化
  2. P2PBox = その世界に参加するノード

    • どのintentboxに所属するかで通信相手が決まる
    • シンプルなsend/onインターフェース

NyashFlowへの応用シンプル版

// ⚡ ローカル実行モードPhase 1-2
pub struct LocalExecutionContext {
    // ビジュアルノード間のデータフロー管理
    data_bus: DataFlowBus,
}

// 🌐 将来の拡張Phase 4以降
pub trait ExecutionContext {
    fn send_data(&mut self, from: NodeId, to: NodeId, data: NyashValue);
    fn on_data(&mut self, node: NodeId, callback: DataCallback);
}

// 異なる実行コンテキストの実装例
impl ExecutionContext for LocalExecutionContext { ... }
impl ExecutionContext for RemoteExecutionContext { ... }  // WebSocket経由
impl ExecutionContext for SharedMemoryContext { ... }     // 高速共有メモリ

段階的な導入計画

Phase 1-2: シンプルなデータフロー

// 最初はシンプルに
pub struct DataFlowEngine {
    nodes: HashMap<NodeId, VisualNode>,
    connections: Vec<Connection>,
}

impl DataFlowEngine {
    pub fn execute(&mut self) {
        // 単純な同期実行
        for connection in &self.connections {
            let data = self.get_output_data(connection.from_node);
            self.set_input_data(connection.to_node, data);
        }
    }
}

Phase 3-4: 抽象化された実行コンテキスト

// P2PBox的な抽象化を導入
pub struct VisualNodeBox {
    id: NodeId,
    context: Box<dyn ExecutionContext>,  // どの「世界」で実行するか
}

impl VisualNodeBox {
    pub fn send(&self, data: NyashValue, to: NodeId) {
        self.context.send_data(self.id, to, data);
    }
    
    pub fn on_receive<F>(&mut self, callback: F) 
    where F: Fn(NyashValue) + 'static {
        self.context.on_data(self.id, Box::new(callback));
    }
}

実用的な応用例

1. マルチスレッド実行(ローカル)

// 重い処理を別スレッドで
let math_context = ThreadedExecutionContext::new();
let math_node = VisualNodeBox::new(BoxType::MathBox, math_context);

2. リアルタイムコラボレーション(将来)

// WebSocketで他のユーザーと共有
let collab_context = WebSocketContext::new("wss://nyashflow.example.com");
let shared_node = VisualNodeBox::new(BoxType::SharedBox, collab_context);

3. デバッグモード

// すべてのデータフローを記録
let debug_context = RecordingContext::new();
// 後でデータフローを再生・分析可能

設計上の重要な判断

  1. 最初はローカル実行のみ

    • P2P機能は作らないCharmFlowの教訓
    • でも将来の拡張性は確保
  2. インターフェースの統一

    • send/onのシンプルなAPIを維持
    • 実行コンテキストは隠蔽
  3. 段階的な複雑性

    • Phase 1-2: 同期的なローカル実行
    • Phase 3: 非同期実行対応
    • Phase 4: リモート実行(必要なら)

実装の指針

// ❌ 避けるべき実装CharmFlow的
struct EverythingNode {
    p2p_manager: P2PManager,
    intent_bus: IntentBus,
    websocket: WebSocket,
    // ... 100個の機能
}

// ✅ 推奨される実装NyashFlow的
struct VisualNode {
    data: NodeData,
    // 実行コンテキストは外部から注入
}

struct ExecutionEngine {
    context: Box<dyn ExecutionContext>,
    // コンテキストを差し替え可能
}

まとめ:「いいとこ取り」の精神

  • P2PBox/intentboxの優れた抽象化を参考に
  • 最初はシンプルに実装
  • 将来の拡張性を設計に組み込む
  • 過剰な機能は避ける

これにより、NyashFlowは

  • 初期は単純なビジュアルプログラミング環境
  • 必要に応じて高度な実行モデルに拡張可能
  • CharmFlowの失敗を繰り返さない

📋 チェックリスト(開発開始時)

  • このドキュメントを読み終えた
  • Nyashプロジェクトをビルドできる
  • eguiのサンプルを動かした
  • プロジェクトフォルダを作成した
  • 最初のコミットをした

頑張ってにゃ〜!🚀