## 🚀 主要機能追加 ### 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>
15 KiB
15 KiB
🎨 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 + NyaMesh(P2P)で実装
- 失敗から学んだこと:
- カプセル化の欠如 → スパゲティコード化
- 役割分担の不明確 → 保守困難
- 過剰な機能 → 複雑化
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: MVP(1-2週間)
- 基本的なノード表示
- 3種類のBox(String, 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のP2PBoxとintentboxから、NyashFlowに活用できる本質的な設計思想:
-
intentbox = 通信世界の定義
- プロセス内、WebSocket、メモリ共有など
- 通信の「場」を抽象化
-
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();
// 後でデータフローを再生・分析可能
設計上の重要な判断
-
最初はローカル実行のみ
- P2P機能は作らない(CharmFlowの教訓)
- でも将来の拡張性は確保
-
インターフェースの統一
- send/onのシンプルなAPIを維持
- 実行コンテキストは隠蔽
-
段階的な複雑性
- 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のサンプルを動かした
- プロジェクトフォルダを作成した
- 最初のコミットをした
頑張ってにゃ〜!🚀