docs: restore docs/private/roadmap from 7b4908f9 (Phase 20.31)

This commit is contained in:
nyash-codex
2025-10-31 18:00:10 +09:00
parent 1d49e24bf0
commit 8fd3a2b509
433 changed files with 108935 additions and 0 deletions

View File

@ -0,0 +1,500 @@
# Phase 21: データベース駆動開発DDD: Database-Driven Development
## 📋 概要
ソースコードをファイルではなくデータベースで管理する革命的開発パラダイム。
Box、メソッド、名前空間を構造化データとして扱い、リファクタリングを瞬時に完了させる。
**「ファイルは1970年代の遺物。21世紀のコードは構造化データベースに住む」**
## 🎯 背景と動機
### 現状の問題
- **ファイルベース**:物理的な区切り(人間の都合)
- **Box/メソッド**:論理的な単位(プログラムの本質)
- **不一致の結果**:リファクタリングが遅い、検索が非効率、依存関係が不透明
### 解決策
- コードをSQLiteデータベースで管理
- Box、メソッド、依存関係を正規化されたテーブルで表現
- SQLクエリでリファクタリング・検索・分析を高速化
### Nyashの決定的優位性2025-09-30追加
- **グローバル変数なし** → 状態が完全に追跡可能、並列リファクタリング安全
- **Everything is Box** → 統一的なテーブル設計、1対1マッピング
- **Static box** → グローバル状態も管理可能、副作用が局所的
- **スコープ明確** → 依存関係が単純、循環参照の検出容易
## 🏗️ データベーススキーマ
### 基本テーブル構造
```sql
-- Boxの定義
CREATE TABLE boxes (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
namespace TEXT,
parent_box_id INTEGER,
box_type TEXT CHECK(box_type IN ('normal', 'static', 'abstract')),
source_code TEXT,
metadata JSON, -- 型情報、アノテーション、ドキュメント
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_box_id) REFERENCES boxes(id)
);
-- メソッド定義
CREATE TABLE methods (
id INTEGER PRIMARY KEY,
box_id INTEGER NOT NULL,
name TEXT NOT NULL,
visibility TEXT CHECK(visibility IN ('public', 'private', 'protected')),
params JSON, -- パラメータ情報
return_type JSON,
body TEXT,
mir_cache BLOB, -- コンパイル済みMIRをキャッシュ
optimization_hints JSON,
FOREIGN KEY (box_id) REFERENCES boxes(id),
UNIQUE(box_id, name) -- 同一Box内でメソッド名は一意
);
-- フィールド定義
CREATE TABLE fields (
id INTEGER PRIMARY KEY,
box_id INTEGER NOT NULL,
name TEXT NOT NULL,
field_type JSON,
default_value TEXT,
metadata JSON,
FOREIGN KEY (box_id) REFERENCES boxes(id)
);
-- 依存関係
CREATE TABLE dependencies (
from_type TEXT CHECK(from_type IN ('box', 'method')),
from_id INTEGER,
to_type TEXT CHECK(to_type IN ('box', 'method')),
to_id INTEGER,
dep_type TEXT CHECK(dep_type IN ('uses', 'extends', 'calls', 'implements')),
metadata JSON, -- 呼び出し位置、使用頻度など
PRIMARY KEY (from_type, from_id, to_type, to_id, dep_type)
);
-- 名前空間
CREATE TABLE namespaces (
id INTEGER PRIMARY KEY,
path TEXT UNIQUE NOT NULL,
parent_id INTEGER,
metadata JSON,
FOREIGN KEY (parent_id) REFERENCES namespaces(id)
);
-- ファイルマッピング2025-09-30追加
CREATE TABLE files (
id INTEGER PRIMARY KEY,
path TEXT UNIQUE NOT NULL, -- 'src/user/auth.nyash'
last_modified TIMESTAMP,
is_generated BOOLEAN DEFAULT FALSE -- DBから生成されたファイルか
);
CREATE TABLE file_boxes (
file_id INTEGER NOT NULL,
box_id INTEGER NOT NULL,
line_start INTEGER, -- 何行目から
line_end INTEGER, -- 何行目まで
PRIMARY KEY (file_id, box_id),
FOREIGN KEY (file_id) REFERENCES files(id),
FOREIGN KEY (box_id) REFERENCES boxes(id)
);
-- コンパイルキャッシュ
CREATE TABLE compile_cache (
id INTEGER PRIMARY KEY,
entity_type TEXT,
entity_id INTEGER,
mir_version INTEGER,
mir_data BLOB,
metadata JSON, -- 最適化レベル、ターゲットなど
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 全文検索用インデックス
CREATE VIRTUAL TABLE code_search USING fts5(
entity_type,
entity_id,
name,
content,
tokenize = 'porter'
);
```
## 🚀 革命的な機能
### 1. 瞬間リファクタリング
```sql
-- 名前変更:トランザクション一発
BEGIN TRANSACTION;
UPDATE boxes SET name = 'NewBoxName' WHERE name = 'OldBoxName';
UPDATE code_search SET name = 'NewBoxName'
WHERE entity_type = 'box' AND name = 'OldBoxName';
-- 依存コードも自動更新(トリガーで実装)
COMMIT;
-- メソッド移動Box間でメソッドを移動
UPDATE methods SET box_id = (SELECT id FROM boxes WHERE name = 'TargetBox')
WHERE id = ? AND box_id = ?;
```
### 2. 高度な検索・分析
```sql
-- 未使用コード検出
SELECT b.namespace || '.' || b.name AS unused_box
FROM boxes b
LEFT JOIN dependencies d ON
(d.to_type = 'box' AND d.to_id = b.id)
WHERE d.from_id IS NULL;
-- 循環依存検出再帰CTE
WITH RECURSIVE dep_path AS (
SELECT from_id, to_id,
from_id || '->' || to_id as path
FROM dependencies
WHERE from_type = 'box' AND to_type = 'box'
UNION ALL
SELECT d.from_id, dp.to_id,
dp.path || '->' || d.to_id
FROM dependencies d
JOIN dep_path dp ON d.to_id = dp.from_id
WHERE d.from_type = 'box' AND d.to_type = 'box'
AND dp.path NOT LIKE '%' || d.to_id || '%'
)
SELECT path FROM dep_path WHERE from_id = to_id;
-- 類似コード検出(全文検索)
SELECT b1.name AS box1, m1.name AS method1,
b2.name AS box2, m2.name AS method2,
similarity_score(m1.body, m2.body) AS similarity
FROM methods m1
JOIN methods m2 ON m1.id < m2.id
JOIN boxes b1 ON m1.box_id = b1.id
JOIN boxes b2 ON m2.box_id = b2.id
WHERE similarity_score(m1.body, m2.body) > 0.8;
```
### 3. ファイル操作とリファクタリング2025-09-30追加
```sql
-- Box抽出して新ファイルへ移動
UPDATE file_boxes
SET file_id = (SELECT id FROM files WHERE path = 'auth/user.nyash')
WHERE box_id = (SELECT id FROM boxes WHERE name = 'UserBox');
-- 関連Boxをまとめて移動依存関係ベース
WITH related_boxes AS (
SELECT DISTINCT to_id as box_id
FROM dependencies
WHERE from_id = ? AND dep_type IN ('uses', 'extends')
)
UPDATE file_boxes
SET file_id = (SELECT id FROM files WHERE path = 'auth/related.nyash')
WHERE box_id IN (SELECT box_id FROM related_boxes);
-- 肥大化ファイルの自動分割提案
SELECT f.path, COUNT(*) as box_count,
GROUP_CONCAT(b.name) as boxes_to_extract
FROM files f
JOIN file_boxes fb ON f.id = fb.file_id
JOIN boxes b ON fb.box_id = b.id
GROUP BY f.path
HAVING COUNT(*) > 10;
```
### 4. インテリジェントなキャッシング
```sql
-- 変更影響分析
CREATE TRIGGER invalidate_cache_on_method_update
AFTER UPDATE ON methods
BEGIN
-- 直接依存するエンティティのキャッシュを無効化
DELETE FROM compile_cache
WHERE entity_id IN (
SELECT from_id FROM dependencies
WHERE to_type = 'method' AND to_id = NEW.id
);
END;
```
### 4. バージョン管理の統合
```sql
-- 変更履歴
CREATE TABLE history (
id INTEGER PRIMARY KEY,
entity_type TEXT,
entity_id INTEGER,
version INTEGER,
change_type TEXT,
old_value TEXT,
new_value TEXT,
changed_by TEXT,
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
commit_message TEXT
);
-- Git風のブランチ管理
CREATE TABLE branches (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
base_version INTEGER,
is_active BOOLEAN DEFAULT TRUE
);
```
## 🎨 実装例
```nyash
box CodeDB {
db: SQLiteBox
cache: MapBox
birth(dbPath) {
me.db = new SQLiteBox(dbPath)
me.cache = new MapBox()
me.initSchema()
}
// Boxを保存
saveBox(box) {
local tx = me.db.beginTransaction()
try {
local boxId = me.db.insert("boxes", {
name: box.name,
namespace: box.namespace,
source_code: box.toString(),
metadata: box.getMetadata()
})
// メソッドも保存
for method in box.methods {
me.saveMethod(boxId, method)
}
tx.commit()
} catch (e) {
tx.rollback()
throw e
}
}
// リファクタリング:名前変更
renameBox(oldName, newName) {
me.db.execute(
"UPDATE boxes SET name = ? WHERE name = ?",
[newName, oldName]
)
// 全文検索インデックスも更新
me.updateSearchIndex()
// キャッシュ無効化
me.invalidateCache(oldName)
}
// 未使用コード検出
findUnusedCode() {
return me.db.query("
SELECT b.namespace || '.' || b.name AS unused
FROM boxes b
LEFT JOIN dependencies d ON d.to_id = b.id
WHERE d.from_id IS NULL
")
}
// AI連携類似コード提案
suggestRefactoring(methodId) {
local similar = me.findSimilarMethods(methodId)
if similar.length() > 3 {
return {
suggestion: "共通Boxに抽出",
methods: similar
}
}
}
}
```
## 🔧 開発ツール
### 1. CLI拡張
```bash
# DBクエリ実行
nyash db query "SELECT * FROM boxes WHERE name LIKE '%Handler'"
# リファクタリング
nyash db refactor rename-box OldName NewName
# 依存関係グラフ生成
nyash db deps --format=dot | dot -Tpng -o deps.png
# 未使用コード削除
nyash db clean --remove-unused --dry-run
```
### 2. VSCode拡張
- **DBエクスプローラー**Box/メソッドをツリー表示
- **リアルタイム検索**SQLクエリで即座に検索
- **依存関係ビュー**:グラフィカルに表示
### 3. Box単位インクリメンタルチェック2025-09-30追加
```bash
# Box単位でのチェックRust cargo checkに相当
nyash check --box UserBox # 特定Boxのみ
nyash check --changed # 変更されたBoxのみ
nyash check --affected # 影響を受けるBoxも含む
# DB内でのMIRキャッシュ活用
SELECT b.name, cc.mir_version, cc.created_at
FROM boxes b
LEFT JOIN compile_cache cc ON b.id = cc.entity_id
WHERE cc.mir_version < (SELECT MAX(mir_version) FROM compile_cache);
```
### 4. Web UI
```nyash
box CodeDBWebUI {
server: WebServerBox
db: CodeDB
birth(dbPath, port) {
me.db = new CodeDB(dbPath)
me.server = new WebServerBox(port)
me.setupRoutes()
}
setupRoutes() {
// コードグラフ表示
me.server.get("/graph") { req, res ->
local deps = me.db.getAllDependencies()
res.json(me.buildD3Graph(deps))
}
// リアルタイムSQL実行
me.server.post("/query") { req, res ->
local result = me.db.query(req.body.sql)
res.json(result)
}
}
}
```
## 💡 実装の容易性2025-09-30追加
### なぜNyashでは簡単なのか
```nyash
# すべてが箱 → テーブル設計が自然
box UserBox { ... } → INSERT INTO boxes VALUES (...)
# グローバル変数なし → 依存関係が明確
static box Config { } → 完全に追跡可能
# local変数もBoxスコープ内 → 状態管理がシンプル
local temp = new Box() → scope_id で管理
```
### 実装見積もり
- **基本DB化**: 1-2週間スキーマ作成とインポート/エクスポート)
- **リファクタリング機能**: 1-2週間SQL操作のラッパー
- **IDE統合**: 2-3週間VSCode拡張
- **合計**: 1-2ヶ月で実用レベル当初予想の9ヶ月より大幅短縮
### 他言語では困難な理由
- **JavaScript**: グローバル汚染、prototype chain、動的すぎる
- **Python**: `__builtins__`、モジュールの副作用、メタクラス
- **Java**: 静的フィールド、クラスローダー、リフレクション
- **Nyash**: **これらの問題がすべて存在しない!**
## 📊 移行戦略
### Phase 1: ハイブリッドモード3ヶ月
- 既存ファイル→DB同期ツール開発
- DB→ファイルエクスポートGit互換性維持
- 開発者が徐々に慣れる期間
### Phase 2: DB優先モード3ヶ月
- 新規開発はDB直接
- ファイルは自動生成
- リファクタリング効率を体感
### Phase 3: 完全DB化3ヶ月
- ファイルシステムは配布用のみ
- 開発は100% DB駆動
- 新しい開発パラダイムの確立
## 🌟 期待される効果
### 開発効率
- **リファクタリング**: 100倍高速化秒単位→ミリ秒単位
- **検索**: SQLによる高度な検索正規表現、構造検索
- **分析**: 依存関係、複雑度、類似性を瞬時に把握
### コード品質
- **重複排除**: 類似コードを自動検出
- **整合性**: DB制約で不整合を防止
- **追跡可能性**: すべての変更を記録
### AI連携
- **構造化データ**: AIが理解しやすい
- **メタデータ**: 型情報、使用頻度など豊富
- **学習効率**: コードパターンを効率的に学習
## 🚀 革新性
### 世界初の要素
1. **完全DB駆動言語**: ファイルシステムからの解放
2. **構造認識エディタ**: Box/メソッド単位の編集
3. **瞬間リファクタリング**: SQLトランザクションで完結
4. **依存関係DB**: コンパイル時情報も含む
### 技術的優位性
- **SQLite**: 軽量、高速、信頼性
- **Everything is Box**: DB表現と相性抜群
- **MIRキャッシュ**: コンパイル高速化
## 📅 実施時期
- **開始条件**: Phase 15セルフホスティング完了後
- **推定期間**: 9ヶ月
- **優先度**: 高(開発効率の革命的向上)
## 🔗 関連フェーズ
- [Phase 15: セルフホスティング](../phase-15/) - 基盤技術
- [Phase 12: 統一実行パス](../phase-12/) - MIRキャッシュ活用
- [Phase 16: プラグインエコシステム](../phase-16/) - DB APIの公開
---
> 「コードはファイルに書くもの」という固定観念を打ち破る。
> 21世紀の開発は、構造化データベースで行うべきだにゃ
## 📚 関連ドキュメント
### Phase 21の進化過程
- [技術的考慮事項](technical-considerations.md) - 詳細な技術検討
- [可逆変換アプローチ](reversible-conversion.md) - Git互換性を保つ方法
- [箱データベース構想v2](README_v2.md) - シンプル化された実装
- [自己解析アプローチ](self-parsing-approach.md) - Nyashの自己パース能力活用
### 学術的評価
- **[AI評価フォルダ](ai-evaluation/)** - Gemini/Codexによる詳細な評価
- [Gemini評価](ai-evaluation/gemini-evaluation.md) - 完全な学術的分析
- [Codex評価部分](ai-evaluation/codex-evaluation-partial.md) - 深い思考過程
- [評価サマリー](ai-evaluation/evaluation-summary.md) - 統合的な分析

View File

@ -0,0 +1,313 @@
# Phase 21: ソースコード⇔データベース完全可逆変換システム
## 📋 概要
データベース駆動開発の最大の課題であるGit互換性を、**完全可逆変換**によって根本的に解決する革新的アプローチ。
ソースコードとデータベースを自在に行き来できることで、両方の利点を最大限に活用する。
## 🎯 核心的なアイデア
```
ソースコード(.nyash ⇔ データベースSQLite
↓ ↓
Git管理 高速リファクタリング
エディタ編集 構造化分析
既存ツール互換 AI最適化
```
**重要な原則:**
- ソースコード → DB → ソースコードで100%元に戻る(情報の欠落なし)
- 開発者は好きな方式ファイルまたはDBを自由に選択可能
- Git運用は完全に従来通りテキストファイルとしてコミット
## 🏗️ 技術設計
### 1. 完全可逆変換の要件
```nyash
box ReversibleConverter {
// 変換の基本原則
verify(sourceCode) {
local db = me.sourceToDb(sourceCode)
local restored = me.dbToSource(db)
return sourceCode == restored // 必ずtrue
}
}
```
### 2. メタデータの完全保存
```sql
-- コード構造
CREATE TABLE code_structure (
id INTEGER PRIMARY KEY,
entity_type TEXT, -- 'box', 'method', 'field'
entity_id INTEGER,
source_order INTEGER,
indentation_level INTEGER,
line_start INTEGER,
line_end INTEGER,
column_start INTEGER,
column_end INTEGER
);
-- スタイル情報
CREATE TABLE style_metadata (
id INTEGER PRIMARY KEY,
entity_id INTEGER,
whitespace_before TEXT,
whitespace_after TEXT,
line_endings TEXT, -- '\n' or '\r\n'
indentation_style TEXT, -- 'space' or 'tab'
indentation_width INTEGER
);
-- コメント保存
CREATE TABLE comments (
id INTEGER PRIMARY KEY,
entity_id INTEGER,
comment_type TEXT, -- 'line', 'block', 'doc'
content TEXT,
position TEXT, -- 'before', 'after', 'inline'
line_number INTEGER,
column_number INTEGER
);
-- 元のソース(差分検証用)
CREATE TABLE original_sources (
file_path TEXT PRIMARY KEY,
content_hash TEXT,
full_content TEXT,
last_synced TIMESTAMP
);
```
### 3. 変換アルゴリズム
#### ソース → DB
```nyash
box SourceToDbConverter {
convert(filePath, sourceCode) {
// 1. AST解析
local ast = Parser.parseWithFullInfo(sourceCode)
// 2. 構造抽出
local boxes = me.extractBoxes(ast)
local methods = me.extractMethods(ast)
local dependencies = me.analyzeDependencies(ast)
// 3. メタデータ抽出
local metadata = {
comments: me.extractComments(sourceCode),
whitespace: me.extractWhitespace(sourceCode),
style: me.detectCodingStyle(sourceCode),
positions: me.mapSourcePositions(ast)
}
// 4. DB保存トランザクション
me.db.transaction {
me.saveStructure(boxes, methods)
me.saveMetadata(metadata)
me.saveDependencies(dependencies)
me.saveOriginal(filePath, sourceCode)
}
}
}
```
#### DB → ソース
```nyash
box DbToSourceConverter {
convert(filePath) {
// 1. 構造読み込み
local structure = me.db.loadStructure(filePath)
local metadata = me.db.loadMetadata(filePath)
// 2. ソース再構築
local builder = new SourceBuilder(metadata.style)
for entity in structure.entities {
// 元の位置情報を使って再配置
builder.addEntity(entity, metadata.positions[entity.id])
// コメントの復元
for comment in metadata.comments[entity.id] {
builder.addComment(comment)
}
// 空白の復元
builder.applyWhitespace(metadata.whitespace[entity.id])
}
return builder.toString()
}
}
```
### 4. スタイルの扱い
```nyash
box StylePreserver {
modes: {
EXACT: "完全保持", // 空白・改行すべて元通り
NORMALIZE: "正規化", // フォーマッタ適用
HYBRID: "ハイブリッド" // コメント保持+コード正規化
}
preserveStyle(source, mode) {
switch mode {
case EXACT:
return me.captureEverything(source)
case NORMALIZE:
return me.formatCode(source)
case HYBRID:
return me.preserveComments(me.formatCode(source))
}
}
}
```
## 🔄 同期メカニズム
### 1. リアルタイム同期
```nyash
box FileSyncDaemon {
watchers: MapBox
birth() {
me.watchers = new MapBox()
}
watch(directory) {
local watcher = new FileWatcher(directory)
watcher.on("change") { event ->
if event.file.endsWith(".nyash") {
me.syncFileToDb(event.file)
}
}
watcher.on("db_change") { event ->
if not event.fromFile {
me.syncDbToFile(event.entity)
}
}
me.watchers.set(directory, watcher)
}
}
```
### 2. Git統合
```bash
# .git/hooks/pre-commit
#!/bin/bash
nyash sync --db-to-files --verify
# .git/hooks/post-checkout
#!/bin/bash
nyash sync --files-to-db --incremental
# .git/hooks/post-merge
#!/bin/bash
nyash sync --files-to-db --full
```
### 3. 差分最適化
```sql
-- 変更追跡
CREATE TABLE sync_status (
entity_id INTEGER PRIMARY KEY,
file_modified TIMESTAMP,
db_modified TIMESTAMP,
sync_status TEXT, -- 'synced', 'file_newer', 'db_newer', 'conflict'
last_sync_hash TEXT
);
-- 差分計算の高速化
CREATE INDEX idx_sync_status ON sync_status(sync_status, file_modified);
```
## 🚀 実装段階
### Phase 1: 基本的な可逆変換1ヶ月
- Box/メソッドレベルの変換
- コメントなし、インデント固定
- 単体テストで100%可逆性検証
### Phase 2: メタデータ保持1ヶ月
- コメントの位置と内容を保存
- インデントスタイルの保持
- 改行コードの維持
### Phase 3: 完全なスタイル保存1ヶ月
- 任意の空白パターン対応
- コーディングスタイルの自動検出
- チーム規約との調整機能
### Phase 4: 高度な同期2ヶ月
- 増分同期アルゴリズム
- コンフリクト解決UI
- パフォーマンス最適化
## 📊 利点の整理
### 開発者にとって
- **選択の自由**: ファイル編集もDB操作も可能
- **既存ツール互換**: VSCode、Vim、Git等すべて使える
- **高速リファクタリング**: 必要な時だけDB機能を活用
### システムにとって
- **Git完全互換**: 通常のテキストファイルとして管理
- **増分コンパイル**: DB側で依存関係を高速解析
- **AI連携強化**: 構造化データで学習効率UP
### チームにとって
- **移行リスクなし**: 段階的導入が可能
- **レビュー互換**: PRは従来通りのテキスト差分
- **柔軟な運用**: プロジェクト毎に最適な方式を選択
## 🎯 成功の指標
1. **完全可逆性**: 1000ファイルで往復変換してもバイト単位で一致
2. **パフォーマンス**: 1000行のファイルを100ms以内で変換
3. **互換性**: 既存のNyashプロジェクトがそのまま動作
4. **開発者満足度**: 90%以上が「便利」と評価
## 🔮 将来の拡張
### 意味的な可逆変換
- コードの意味を保ちながらスタイルを自動最適化
- チーム規約への自動適応
- リファクタリング履歴の保存
### マルチビュー編集
```nyash
// 同じコードを異なる視点で編集
- ファイルビュー: 従来のテキストエディタ
- 構造ビュー: Box/メソッドのツリー表示
- 依存ビュー: グラフィカルな関係表示
- クエリビュー: SQLで直接操作
```
### バージョン管理の革新
- 意味的な差分表示「名前を変更」vs「全行変更」
- 構造認識マージ(メソッド単位での自動解決)
- リファクタリング履歴の永続化
## 📝 実装優先順位
1. **コア変換エンジン**: 可逆性の証明
2. **メタデータ設計**: 完全な情報保存
3. **同期デーモン**: リアルタイム連携
4. **開発ツール**: CLI/IDE統合
5. **最適化**: パフォーマンスチューニング
---
この可逆変換システムにより、データベース駆動開発の利点を最大化しながら、既存の開発フローとの完全な互換性を実現できるにゃ!

View File

@ -0,0 +1,266 @@
# Phase 21: Nyash自己解析アプローチ - AST直接保存
## 📋 概要
Nyashの最大の強み「自分自身をパースできる」を活かした究極にシンプルなアプローチ。
外部パーサー不要、複雑な変換層不要。NyashのASTをそのままデータベースに保存する。
## 🎯 核心的なアイデア
```nyash
// Nyashは自分自身を解析できる
NyashParser.parse(sourceCode) → AST → Database → NyashPrinter.print(AST) → sourceCode
```
**重要な気づき:**
- Nyashにはすでにパーサーがある
- ASTから元のソースを生成する機能もある
- だから、ASTをDBに保存すれば完全可逆
## 🏗️ シンプルな実装
### データベース構造
```sql
-- ASTードをそのまま保存
CREATE TABLE ast_nodes (
id INTEGER PRIMARY KEY,
node_type TEXT, -- "Box", "Method", "Field", "Statement"等
node_data JSON, -- ASTードの完全な情報
parent_id INTEGER,
position INTEGER, -- 親ノード内での位置
source_file TEXT, -- 元のファイルパス
metadata JSON, -- 後から追加する解析情報
FOREIGN KEY (parent_id) REFERENCES ast_nodes(id)
);
-- インデックス
CREATE INDEX idx_node_type ON ast_nodes(node_type);
CREATE INDEX idx_parent ON ast_nodes(parent_id);
CREATE INDEX idx_source ON ast_nodes(source_file);
```
### 基本実装
```nyash
box NyashCodeDB {
parser: NyashParser
printer: NyashPrinter
db: SQLiteBox
birth() {
me.parser = new NyashParser()
me.printer = new NyashPrinter()
me.db = new SQLiteBox("code.db")
}
// ファイルをDBに保存
importFile(filePath) {
local source = FileBox.read(filePath)
local ast = me.parser.parse(source)
// ASTを再帰的にDBに保存
me.saveAST(ast, null, filePath)
}
// ASTードを保存
saveAST(node, parentId, sourceFile) {
local nodeId = me.db.insert("ast_nodes", {
node_type: node.type,
node_data: node.toJSON(),
parent_id: parentId,
position: node.position,
source_file: sourceFile
})
// 子ノードも保存
for (i, child) in node.children.enumerate() {
child.position = i
me.saveAST(child, nodeId, sourceFile)
}
return nodeId
}
// DBからソースコードを復元
exportFile(filePath) {
local rootNodes = me.db.query(
"SELECT * FROM ast_nodes
WHERE source_file = ? AND parent_id IS NULL
ORDER BY position",
filePath
)
local source = ""
for node in rootNodes {
local ast = me.loadAST(node.id)
source += me.printer.print(ast) + "\n"
}
FileBox.write(filePath, source)
}
// ASTを再構築
loadAST(nodeId) {
local node = me.db.get("ast_nodes", nodeId)
local astNode = ASTNode.fromJSON(node.node_data)
// 子ノードも読み込む
local children = me.db.query(
"SELECT * FROM ast_nodes
WHERE parent_id = ?
ORDER BY position",
nodeId
)
for child in children {
astNode.addChild(me.loadAST(child.id))
}
return astNode
}
}
```
## 🚀 高度な機能
### リファクタリング
```nyash
box ASTRefactorer {
db: SQLiteBox
// 名前変更
renameBox(oldName, newName) {
// Box定義を見つける
local boxNodes = me.db.query(
"SELECT * FROM ast_nodes
WHERE node_type = 'Box'
AND json_extract(node_data, '$.name') = ?",
oldName
)
for node in boxNodes {
// AST上で名前を変更
local data = JSON.parse(node.node_data)
data.name = newName
me.db.update("ast_nodes", node.id, {
node_data: JSON.stringify(data)
})
}
// 使用箇所も更新
me.updateReferences(oldName, newName)
}
// メソッド移動
moveMethod(methodName, fromBox, toBox) {
// SQLで親ードを変更するだけ
local fromBoxId = me.findBoxNode(fromBox)
local toBoxId = me.findBoxNode(toBox)
me.db.execute(
"UPDATE ast_nodes
SET parent_id = ?
WHERE parent_id = ?
AND node_type = 'Method'
AND json_extract(node_data, '$.name') = ?",
[toBoxId, fromBoxId, methodName]
)
}
}
```
### メタデータ解析(オンデマンド)
```nyash
box MetadataEngine {
// 必要な時だけ解析
analyzeOnDemand(nodeId) {
local node = db.get("ast_nodes", nodeId)
if not node.metadata or me.isOutdated(node.metadata) {
local metadata = {
dependencies: me.findDependencies(node),
complexity: me.calculateComplexity(node),
lastAnalyzed: now()
}
db.update("ast_nodes", nodeId, {
metadata: JSON.stringify(metadata)
})
}
return JSON.parse(node.metadata)
}
// 依存関係を動的に検出
findDependencies(node) {
local deps = []
// "new XXXBox" パターンを検索
local matches = me.searchPattern(node, "NewBox")
for match in matches {
deps.push(match.boxType)
}
// "from XXX" パターンを検索
local inherits = me.searchPattern(node, "From")
for inherit in inherits {
deps.push(inherit.parentBox)
}
return deps
}
}
```
## 📊 利点
### 1. 実装の簡単さ
- パーサーはすでにあるNyash自身
- プリンターもすでにある
- 複雑な変換層不要
### 2. 100%の正確性
- Nyash公式パーサーを使うから完璧
- ASTは言語の完全な表現
- 情報の欠落なし
### 3. 柔軟性
- メタデータは後から追加
- 部分的な解析が可能
- 増分更新が簡単
### 4. 高速性
- ASTの一部だけ読み込み可能
- SQLの力でクエリが高速
- キャッシュも自然に実装
## 🎯 実装ステップ
### Phase 1: 基本機能1週間
- AST保存・読み込み
- ファイル単位のインポート・エクスポート
- 基本的なクエリ
### Phase 2: リファクタリング1週間
- 名前変更
- メソッド移動
- 依存関係追跡
### Phase 3: 高度な機能2週間
- メタデータ解析
- インクリメンタル更新
- VSCode統合
## 🌟 まとめ
**「Nyashの能力をフル活用する」**
- 外部ツール不要
- 複雑な実装不要
- Nyashらしいシンプルさ
このアプローチなら、Phase 21は「NyashのASTをDBに入れるだけ」という
極めてシンプルな実装で、強力な機能を実現できる!
---
> 「なぜ複雑にするNyashにはすでに必要なものが全部ある」 - にゃ

View File

@ -0,0 +1,409 @@
# Phase 21: 技術的考慮事項
## 🏗️ アーキテクチャ設計
### レイヤー構造
```
┌─────────────────────────────┐
│ 開発ツール層 │ (VSCode, CLI, Web UI)
├─────────────────────────────┤
│ API層 │ (GraphQL/REST)
├─────────────────────────────┤
│ CodeDB抽象層 │ (統一インターフェース)
├─────────────────────────────┤
│ SQLite実装層 │ (具体的なDB操作)
├─────────────────────────────┤
│ ストレージ層 │ (ローカル/リモート)
└─────────────────────────────┘
```
## 🔐 セキュリティ考慮事項
### アクセス制御
```sql
-- ユーザー権限管理
CREATE TABLE permissions (
user_id INTEGER,
resource_type TEXT,
resource_id INTEGER,
permission TEXT CHECK(permission IN ('read', 'write', 'admin')),
granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
granted_by INTEGER,
PRIMARY KEY (user_id, resource_type, resource_id, permission)
);
-- 監査ログ
CREATE TABLE audit_log (
id INTEGER PRIMARY KEY,
user_id INTEGER,
action TEXT,
resource_type TEXT,
resource_id INTEGER,
old_value TEXT,
new_value TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ip_address TEXT,
session_id TEXT
);
```
### SQLインジェクション対策
```nyash
box SecureCodeDB from CodeDB {
// パラメータ化クエリを強制
query(sql, params) {
// SQLをパースして危険な構文をチェック
local ast = me.parseSql(sql)
if me.hasDangerousPattern(ast) {
throw new SecurityError("Dangerous SQL pattern detected")
}
return from CodeDB.query(sql, params)
}
// ホワイトリスト方式のテーブル名検証
validateTableName(name) {
if not name.matches("^[a-z_]+$") {
throw new SecurityError("Invalid table name")
}
}
}
```
## 🚀 パフォーマンス最適化
### インデックス戦略
```sql
-- 頻繁なクエリ用インデックス
CREATE INDEX idx_boxes_namespace ON boxes(namespace);
CREATE INDEX idx_methods_box_id ON methods(box_id);
CREATE INDEX idx_deps_from ON dependencies(from_type, from_id);
CREATE INDEX idx_deps_to ON dependencies(to_type, to_id);
-- 複合インデックス
CREATE INDEX idx_box_namespace_name ON boxes(namespace, name);
CREATE INDEX idx_method_box_name ON methods(box_id, name);
-- 部分インデックス(アクティブなものだけ)
CREATE INDEX idx_active_boxes ON boxes(name)
WHERE deleted_at IS NULL;
```
### クエリ最適化
```nyash
box QueryOptimizer {
cache: MapBox
// クエリ結果のキャッシング
cachedQuery(sql, params, ttl) {
local key = me.hash(sql + params.toString())
if me.cache.has(key) {
local cached = me.cache.get(key)
if cached.timestamp + ttl > now() {
return cached.result
}
}
local result = me.db.query(sql, params)
me.cache.set(key, {
result: result,
timestamp: now()
})
return result
}
}
```
## 🔄 同期・レプリケーション
### マルチデバイス同期
```nyash
box CodeDBSync {
local: CodeDB
remote: RemoteCodeDB
// 変更を追跡
trackChanges() {
CREATE TRIGGER track_box_changes
AFTER INSERT OR UPDATE OR DELETE ON boxes
BEGIN
INSERT INTO sync_queue (
table_name, operation, entity_id, data
) VALUES (
'boxes',
CASE
WHEN OLD.id IS NULL THEN 'INSERT'
WHEN NEW.id IS NULL THEN 'DELETE'
ELSE 'UPDATE'
END,
COALESCE(NEW.id, OLD.id),
json_object('old', OLD, 'new', NEW)
);
END;
}
// 差分同期
sync() {
local changes = me.local.query("
SELECT * FROM sync_queue
WHERE synced_at IS NULL
ORDER BY created_at
")
for change in changes {
me.remote.applyChange(change)
me.local.markSynced(change.id)
}
}
}
```
## 🎯 互換性戦略
### ファイルシステムとの相互変換
```nyash
box FileDBBridge {
// DB→ファイル エクスポート
exportToFiles(outputDir) {
local boxes = me.db.query("SELECT * FROM boxes")
for box in boxes {
local path = outputDir + "/" +
box.namespace.replace(".", "/") + "/" +
box.name + ".nyash"
local file = new FileBox(path)
file.write(me.generateFileContent(box))
}
}
// ファイル→DB インポート
importFromFiles(sourceDir) {
local files = FileBox.glob(sourceDir + "/**/*.nyash")
me.db.beginTransaction()
try {
for file in files {
local ast = Parser.parse(file.read())
me.importAST(ast, file.path)
}
me.db.commit()
} catch (e) {
me.db.rollback()
throw e
}
}
}
```
## 🔍 高度な分析機能
### コードメトリクス
```sql
-- 循環的複雑度の計算
CREATE VIEW method_complexity AS
SELECT
m.id,
b.name || '.' || m.name as full_name,
(
SELECT COUNT(*)
FROM json_each(m.body)
WHERE value LIKE '%if%'
OR value LIKE '%loop%'
OR value LIKE '%catch%'
) + 1 as cyclomatic_complexity
FROM methods m
JOIN boxes b ON m.box_id = b.id;
-- コード行数統計
CREATE VIEW code_stats AS
SELECT
COUNT(DISTINCT b.id) as total_boxes,
COUNT(DISTINCT m.id) as total_methods,
SUM(LENGTH(m.body) - LENGTH(REPLACE(m.body, char(10), ''))) as total_lines,
AVG(LENGTH(m.body) - LENGTH(REPLACE(m.body, char(10), ''))) as avg_method_lines
FROM boxes b
LEFT JOIN methods m ON b.id = m.box_id;
```
### 依存関係の可視化
```nyash
box DependencyAnalyzer {
// 影響範囲分析
getImpactedEntities(changedEntity) {
return me.db.query("
WITH RECURSIVE impacted AS (
-- 直接依存
SELECT to_type, to_id, 1 as level
FROM dependencies
WHERE from_type = ? AND from_id = ?
UNION
-- 推移的依存
SELECT d.to_type, d.to_id, i.level + 1
FROM dependencies d
JOIN impacted i ON
d.from_type = i.to_type AND
d.from_id = i.to_id
WHERE i.level < 5 -- 最大5階層まで
)
SELECT DISTINCT * FROM impacted
ORDER BY level
", [changedEntity.type, changedEntity.id])
}
}
```
## 🌐 分散開発対応
### ブランチ・マージ戦略
```sql
-- ブランチ管理
CREATE TABLE branches (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
base_commit_id INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INTEGER,
is_active BOOLEAN DEFAULT TRUE
);
-- コミット(変更セット)
CREATE TABLE commits (
id INTEGER PRIMARY KEY,
branch_id INTEGER,
parent_commit_id INTEGER,
message TEXT,
author INTEGER,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
changes JSON, -- 変更の詳細
FOREIGN KEY (branch_id) REFERENCES branches(id)
);
```
### コンフリクト解決
```nyash
box ConflictResolver {
// 3-way マージ
merge(base, mine, theirs) {
if mine == theirs {
return mine // 変更なし or 同じ変更
}
if base == mine {
return theirs // 相手のみ変更
}
if base == theirs {
return mine // 自分のみ変更
}
// 両方変更 - コンフリクト
return me.resolveConflict(base, mine, theirs)
}
resolveConflict(base, mine, theirs) {
// AST レベルでのマージを試みる
local baseAST = Parser.parse(base)
local mineAST = Parser.parse(mine)
local theirsAST = Parser.parse(theirs)
// メソッド単位でマージ可能か確認
if me.canMergeAtMethodLevel(baseAST, mineAST, theirsAST) {
return me.mergeASTs(baseAST, mineAST, theirsAST)
}
// マージ不可 - ユーザーに選択させる
throw new MergeConflict(base, mine, theirs)
}
}
```
## 📊 メトリクス・モニタリング
### パフォーマンス追跡
```sql
-- クエリパフォーマンスログ
CREATE TABLE query_performance (
id INTEGER PRIMARY KEY,
query_hash TEXT,
query_text TEXT,
execution_time_ms INTEGER,
rows_affected INTEGER,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- DB統計情報
CREATE VIEW db_stats AS
SELECT
(SELECT COUNT(*) FROM boxes) as total_boxes,
(SELECT COUNT(*) FROM methods) as total_methods,
(SELECT COUNT(*) FROM dependencies) as total_dependencies,
(SELECT page_count * page_size FROM pragma_page_count(), pragma_page_size()) as db_size_bytes,
(SELECT COUNT(*) FROM compile_cache) as cached_compilations;
```
## 🔮 将来の拡張性
### プラグインアーキテクチャ
```nyash
box CodeDBPlugin {
// フック機能
hooks: MapBox
register(event, handler) {
if not me.hooks.has(event) {
me.hooks.set(event, new ArrayBox())
}
me.hooks.get(event).push(handler)
}
trigger(event, data) {
if me.hooks.has(event) {
for handler in me.hooks.get(event) {
handler(data)
}
}
}
}
// 使用例:自動フォーマッター
box AutoFormatter from CodeDBPlugin {
birth() {
me.register("before_save", me.formatCode)
}
formatCode(data) {
if data.entity_type == "method" {
data.body = Formatter.format(data.body)
}
}
}
```
### AI統合の準備
```sql
-- ベクトル埋め込み保存
CREATE TABLE embeddings (
id INTEGER PRIMARY KEY,
entity_type TEXT,
entity_id INTEGER,
embedding BLOB, -- float配列をBLOBで保存
model_version TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 類似性検索用の仮想テーブル(将来的にベクトル検索エンジンと統合)
CREATE VIRTUAL TABLE vector_search USING vector_index(
embedding FLOAT[768]
);
```
---
これらの技術的考慮事項を踏まえて、段階的に実装を進めることで、
安全で高性能なデータベース駆動開発環境を実現できるにゃ!