Files
hakorune/docs/private/papers/paper-f-self-parsing-db/self-parsing-approach.md

266 lines
7.1 KiB
Markdown
Raw Normal View History

# 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にはすでに必要なものが全部ある」 - にゃ