🏗️ Refactor: Major LLVM codegen modularization + Phase 15 docs cleanup + Phase 21 DDD concept

## LLVM Codegen Refactoring (by ChatGPT5)
- Split massive boxcall.rs into focused submodules:
  - strings.rs: String method optimizations (concat, length)
  - arrays.rs: Array operations (get, set, push, length)
  - maps.rs: Map operations (get, set, has, size)
  - fields.rs: getField/setField handling
  - invoke.rs: Tagged invoke implementation
  - marshal.rs: Helper functions for marshaling
- Improved code organization and maintainability
- No functional changes, pure refactoring

## Phase 15 Documentation Cleanup
- Restructured phase-15 folder:
  - implementation/: Technical implementation docs
  - planning/: Planning and sequence docs
  - archive/: Redundant/old content
- Removed duplicate content (80k→20k line reduction mentioned 5 times)
- Converted all .txt files to .md for consistency
- Fixed broken links in README.md
- Removed redundant INDEX.md

## Phase 21: Database-Driven Development (New)
- Revolutionary concept: Source code in SQLite instead of files
- Instant refactoring with SQL transactions
- Structured management of boxes, methods, dependencies
- Technical design with security considerations
- Vision: World's first DB-driven programming language

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Selfhosting Dev
2025-09-12 00:35:11 +09:00
parent 3ac4a383e4
commit 4f4c6397a9
22 changed files with 2247 additions and 870 deletions

View File

@ -0,0 +1,469 @@
# Phase 15: セルフホスティング技術詳細
## 1. アーキテクチャ設計
### 1.1 全体構成
```
NyashCompiler (Nyashで実装)
├── Frontend
│ ├── Lexer (トークナイザー)
│ ├── Parser (構文解析)
│ └── AST Builder
├── Middle-end
│ ├── Type Checker
│ ├── Name Resolver
│ ├── MIR Lowerer (→13命令)
│ └── Optimizer
└── Backend複数選択可能
├── CraneliftBox (JITラッパー)
├── X86EmitterBox (直接エミッタ)
├── TemplateStitcherBox (超小型)
└── Runtime Linker
```
### 1.2 CompilerBox設計
```nyash
box CompilerBox {
init {
lexer, // トークン解析器
parser, // 構文解析器
lowerer, // MIR生成器
optimizer, // 最適化器
backend // コード生成器
}
// ソースコードからASTを生成
parse(source) {
local tokens = me.lexer.tokenize(source)
local ast = me.parser.parse(tokens)
return ast
}
// ASTからMIRを生成
lower(ast) {
local mir = me.lowerer.lower(ast)
return me.optimizer.optimize(mir)
}
// MIRから実行可能コードを生成
codegen(mir) {
return me.backend.generate(mir)
}
// 完全なコンパイルパイプライン
compile(source) {
local ast = me.parse(source)
local mir = me.lower(ast)
return me.codegen(mir)
}
}
```
## 2. パーサー実装Nyash版
### 2.1 Lexer実装例
```nyash
box Lexer {
init { keywords, operators }
constructor() {
me.keywords = new MapBox()
me.keywords.set("box", TokenType.BOX)
me.keywords.set("if", TokenType.IF)
me.keywords.set("loop", TokenType.LOOP)
// ... 他のキーワード
me.operators = new MapBox()
me.operators.set("+", TokenType.PLUS)
me.operators.set("-", TokenType.MINUS)
// ... 他の演算子
}
tokenize(source) {
local tokens = new ArrayBox()
local position = 0
loop(position < source.length()) {
local char = source.charAt(position)
if me.isWhitespace(char) {
position = position + 1
continue
}
if me.isDigit(char) {
local token = me.readNumber(source, position)
tokens.push(token)
position = token.end
continue
}
if me.isLetter(char) {
local token = me.readIdentifier(source, position)
tokens.push(token)
position = token.end
continue
}
// ... 他のトークン種別
}
return tokens
}
}
```
### 2.2 Parser実装例
```nyash
box Parser {
init { tokens, current }
parse(tokens) {
me.tokens = tokens
me.current = 0
return me.parseProgram()
}
parseProgram() {
local statements = new ArrayBox()
loop(not me.isAtEnd()) {
local stmt = me.parseStatement()
statements.push(stmt)
}
return new ASTNode("Program", statements)
}
parseStatement() {
if me.match(TokenType.BOX) {
return me.parseBoxDeclaration()
}
if me.match(TokenType.IF) {
return me.parseIfStatement()
}
// ... 他の文種別
return me.parseExpression()
}
}
```
## 3. MIR生成器実装
### 3.1 Lowerer実装例
```nyash
box MIRLowerer {
init {
current_block,
value_counter,
block_counter,
locals
}
lower(ast) {
me.value_counter = 0
me.block_counter = 0
me.locals = new MapBox()
local mir = new MIRModule()
me.lowerNode(ast, mir)
return mir
}
lowerExpression(node, mir) {
if node.type == "BinaryOp" {
local left = me.lowerExpression(node.left, mir)
local right = me.lowerExpression(node.right, mir)
local result = me.newValue()
mir.addInstruction(new BinOp(
node.operator,
left,
right,
result
))
return result
}
if node.type == "Literal" {
local result = me.newValue()
mir.addInstruction(new Const(node.value, result))
return result
}
// ... 他の式種別
}
}
```
## 4. バックエンド実装
### 4.1 CraneliftBox実装
```nyash
box CraneliftBox {
init { jit_module, func_ctx }
constructor() {
// CraneliftをFFI経由で初期化
me.jit_module = ExternCall("cranelift_new_module")
me.func_ctx = ExternCall("cranelift_new_context")
}
compile(mir) {
local compiled_funcs = new MapBox()
// 各関数をコンパイル
for func in mir.functions {
local code = me.compileFunction(func)
compiled_funcs.set(func.name, code)
}
return compiled_funcs
}
compileFunction(mir_func) {
// MIR → Cranelift IR変換
ExternCall("cranelift_begin_function", me.func_ctx)
for inst in mir_func.instructions {
me.emitInstruction(inst)
}
// JITコンパイル
return ExternCall("cranelift_finalize_function", me.func_ctx)
}
}
```
### 4.2 X86EmitterBox実装直接x86生成
```nyash
box X86EmitterBox {
init { code_buffer, label_map }
constructor() {
me.code_buffer = new ArrayBox()
me.label_map = new MapBox()
}
compile(mir) {
// MIR 13命令を直接x86-64に変換
for func in mir.functions {
me.emitFunction(func)
}
return me.code_buffer
}
emitInstruction(inst) {
// MIR命令をx86テンプレートに変換
if inst.type == "Const" {
// mov rax, imm64
me.emit_mov_imm(inst.dst, inst.value)
}
if inst.type == "BinOp" {
if inst.op == "Add" {
// add rax, rbx
me.emit_add(inst.dst, inst.left, inst.right)
}
}
if inst.type == "BoxCall" {
// mov rdi, receiver
// mov rax, [rdi] ; vtable
// call [rax+slot*8] ; method call
me.emit_boxcall(inst.recv, inst.slot)
}
// ... 残り10命令のテンプレート
}
emit_mov_imm(reg, value) {
// REX.W + mov r64, imm64
me.code_buffer.push(0x48) // REX.W
me.code_buffer.push(0xB8 + reg) // mov opcode
// 64ビット即値をリトルエンディアンで
for i in range(0, 8) {
me.code_buffer.push((value >> (i * 8)) & 0xFF)
}
}
}
```
### 4.3 テンプレート・スティッチャ実装(超小型バイナリ)
```nyash
box TemplateStitcherBox {
init { stub_addresses, jump_table }
constructor() {
// 各MIR命令の共通スタブアドレス
me.stub_addresses = new MapBox()
me.stub_addresses.set("Const", 0x1000)
me.stub_addresses.set("UnaryOp", 0x1100)
me.stub_addresses.set("BinOp", 0x1200)
me.stub_addresses.set("Compare", 0x1300)
me.stub_addresses.set("TypeOp", 0x1400)
me.stub_addresses.set("Load", 0x1500)
me.stub_addresses.set("Store", 0x1600)
me.stub_addresses.set("Branch", 0x1700)
me.stub_addresses.set("Jump", 0x1800)
me.stub_addresses.set("Return", 0x1900)
me.stub_addresses.set("Phi", 0x1A00)
me.stub_addresses.set("BoxCall", 0x1B00)
me.stub_addresses.set("ExternCall", 0x1C00)
}
compile(mir) {
me.jump_table = new ArrayBox()
// プログラムはスタブへのジャンプ列として表現
for inst in mir.instructions {
local stub_addr = me.stub_addresses.get(inst.type)
// jmp rel32
me.jump_table.push(0xE9) // jmp opcode
me.jump_table.push_rel32(stub_addr)
// 命令固有のパラメータをデータセクションに配置
me.encodeParameters(inst)
}
return me.jump_table
}
}
```
## 5. ブートストラップ手順
### 5.1 段階的移行
1. **Stage 0**: Rustコンパイラで初期Nyashコンパイラをビルド
2. **Stage 1**: Stage 0コンパイラでNyashコンパイラNyash版をコンパイル
3. **Stage 2**: Stage 1コンパイラで自分自身をコンパイル
4. **検証**: Stage 1とStage 2の出力が同一であることを確認
### 5.2 検証スクリプト
```nyash
box BootstrapVerifier {
verify() {
// Stage 0でStage 1をビルド
local stage0 = new CompilerBox() // Rust版
local stage1_code = stage0.compile(readFile("compiler.nyash"))
// Stage 1でStage 2をビルド
local stage1 = stage1_code.instantiate()
local stage2_code = stage1.compile(readFile("compiler.nyash"))
// バイナリ比較
if stage1_code.equals(stage2_code) {
print("🎉 Bootstrap successful!")
return true
} else {
print("❌ Bootstrap failed - outputs differ")
return false
}
}
}
```
## 6. 性能最適化
### 6.1 ホットパス最適化
```nyash
box OptimizingCompiler from CompilerBox {
init { profiler }
constructor() {
from CompilerBox.constructor()
me.profiler = new ProfilerBox()
}
compile(source) {
// プロファイル収集モード
if me.profiler.isEnabled() {
me.profiler.start()
}
local result = from CompilerBox.compile(source)
// ホット関数をJIT再コンパイル
if me.profiler.hasHotFunctions() {
for func in me.profiler.getHotFunctions() {
me.recompileWithOptimization(func)
}
}
return result
}
}
```
## 7. エラー処理とデバッグ
### 7.1 エラーレポート
```nyash
box CompilerError {
init { message, location, suggestions }
format() {
local output = "Error at " + me.location + ": " + me.message
if me.suggestions.length() > 0 {
output = output + "\nSuggestions:"
for suggestion in me.suggestions {
output = output + "\n - " + suggestion
}
}
return output
}
}
```
## 8. テストフレームワーク
```nyash
box CompilerTest {
testParser() {
local parser = new Parser()
local ast = parser.parse("box Test { }")
assert(ast.type == "Program")
assert(ast.children.length() == 1)
assert(ast.children[0].type == "BoxDeclaration")
}
testMIRGeneration() {
local compiler = new CompilerBox()
local mir = compiler.lower(compiler.parse("1 + 2"))
assert(mir.instructions.length() == 3) // 2 Const + 1 BinOp
}
testEndToEnd() {
local compiler = new CompilerBox()
local code = compiler.compile("print('Hello')")
local output = code.run()
assert(output == "Hello")
}
}
```
このようにして、NyashでNyashコンパイラを実装することで、真のセルフホスティングを実現します。

View File

@ -0,0 +1,139 @@
# Phase 15 自己ホスティング準備メモ - 箱積み上げ戦略
Date: 2025-09-03
Author: Claude + にゃ
## 基本理念:箱を下にして積み重ねる
- フォールバック不要、Rust依存なしEXEライブラリのみ
- 一度置いた箱は動かさない
- 下の箱が安定なら、上も安定
- 複雑さは敵、シンプルさは友
## 基礎Box群の階層構造
### 第1層最下層これがないと何も始まらない
- **MemoryBox**: メモリ管理
- **StringBox**: 文字列処理
- **ArrayBox**: 配列操作
- **MapBox**: 連想配列
- **ErrorBox**: エラー処理
### 第2層言語処理の基礎
- **TokenBox**: 字句解析
- **ASTBox**: 構文木
- **SymbolBox**: シンボルテーブル
- **ScopeBox**: スコープ管理
### 第3層コンパイラコア
- **ParserBox**: パーサー
- **MIRBox**: 中間表現13命令
- **OptimizerBox**: 最適化
- **GeneratorBox**: コード生成
### 第4層実行系
- **InterpreterBox**: インタープリター
- **VMBox**: 仮想マシン
- **JITBox**: JITコンパイラCranelift
- **LinkerBox**: リンカーlld
## 準備期間の研究項目
### 1. 依存関係マップ作成
- 何が何に依存?
- 最小限の依存で最大の効果
- 循環依存の排除
### 2. インターフェース設計
- 全Boxの共通プロトコル
- 入力/出力の標準化
- エラー処理の統一
### 3. ビルド順序の科学
- Day 1: 基礎Box群
- Day 2: 言語処理層
- Day 3: コンパイラ層
- 完成まで一直線
### 4. 最小ブートストラップセット
- 自分自身をコンパイルできる最小構成
- 必須機能の特定
- 段階的な機能追加
## 箱の品質保証原則
1. **単体で完結** - 他に依存しすぎない
2. **明確な責務** - 1つの箱は1つの仕事
3. **テスト可能** - 単独で動作確認
4. **不変インターフェース** - 一度決めたら変更なし
## 実装戦略
1. Rust実装の機能分解Box単位
2. 各Boxの仕様書作成
3. テストケースの移植計画
4. Box間プロトコル設計
5. 最小実装から始める
6. 増分的に機能追加
## 成功の鍵
- 準備こそすべて
- 急いで実装より、じっくり設計
- 箱を積み重ねれば必ず頂上に到達
- フォールバックなし、後戻りなし、前進あるのみ
## 革新的アイデア
### 1. BoxDNA設計書
- 各Boxの入力/出力/依存を明文化
- 遺伝子のように継承・組み合わせ
### 2. 増分コンパイル対応
- 変更部分だけ再コンパイル
- 開発効率の向上
### 3. 可視化ツール
- 進捗の見える化
- 依存関係の図示
## 数値目標
- **80,000行 → 20,000行**75%削減)
- **MIR13命令**で全機能実現
- **ビルド時間**1分以内
- **テストカバレッジ**90%以上
## コンテキスト圧縮対策
### 1. ANCP活用Phase 12.7
- 90%圧縮でAIコンテキスト節約
- [ANCP仕様書](../../../phase-12.7/ancp-specs/ANCP-Token-Specification-v1.md)
### 2. モジュール分割開発
- 各Boxを独立して開発
- 統合は最後に実施
### 3. AI協調開発
- Claude実装担当
- ChatGPT5リファクタリング
- Geminiレビュー
- Codexデバッグ支援
## 関連ドキュメント
- [自己ホスティングlld戦略](./lld-strategy.md)
- [Phase 15 README](../README.md)
- [Phase 12.7 ANCP](../../../phase-12.7/)
- [MIR13命令セット](../../../../../reference/mir/INSTRUCTION_SET.md)
## 次のアクション
1. このメモをベースに詳細設計
2. Box依存関係グラフの作成
3. 最小実装セットの確定
4. 各Boxの仕様書ドラフト
---
「箱を積み上げて、世界一美しいコンパイラを作るにゃ!」

View File

@ -0,0 +1,196 @@
# Phase 15 自己ホスティング実装戦略 - MIR→Cranelift→lld
Author: ChatGPT5 + Claude協議
Date: 2025-09-03
Version: 1.0
## 📋 概要
Nyash完全自己ホスティングを実現するための具体的実装戦略。
**「MIR→Craneliftで.o/.objを作る→lldでEXEを組む」**をNyashツールチェーンに内蔵する。
## 🎯 最終形(自己ホスト時の一発ボタン)
```bash
nyash build main.ny \
--backend=cranelift \
--target=x86_64-pc-windows-msvc # or x86_64-unknown-linux-gnu
```
内部処理フロー:
1. **frontend**: AST→MIR13
2. **codegen**: MIR→Cranelift→`.obj/.o`
3. **link**: `lld-link`(Win) / `ld.lld`(Linux)でEXE生成
4. 依存ランタイム`nyashrt`を自動リンク(静的/動的選択)
## 🏗️ 実装の芯(最小で美しいやつ)
### 1. コード生成ライブラリC ABIファサード
```c
// 最小限の美しいインターフェース
ny_mir_to_obj(mir_bin, target_triple) -> obj_bytes
ny_mir_jit_entry(mir_bin) -> exit_code // 開発用
ny_free_buf(buffer) // メモリ解放
// エラーハンドリング
// 例外は戻り値NyErrunwind禁止
```
実装のポイント:
- 返却メモリは`ny_free_buf`で解放
- 例外は戻り値NyErrで統一unwind禁止
- C ABIで安定した境界を作る
### 2. リンカー・ラッパ(プラットフォーム別)
#### Windows
- 既定: `lld-link`
- 主要フラグ:
```bash
lld-link <objs...> nyashrt.lib /SUBSYSTEM:CONSOLE \
/OUT:a.exe /ENTRY:nyash_entry \
/LIBPATH:<sdk/lib> /MACHINE:X64
```
- MSVC互換が要る配布向けに`/fallback:link.exe`オプションも用意可
#### Linux
- 既定: `ld.lld`(開発で`mold`併用可)
```bash
ld.lld -o a.out main.o -L. -lnyashrt -lc -lm -pthread \
--gc-sections --icf=all
```
#### macOS将来
- 日常は`ld64.lld`、配布はXcodeの`ld64` + コード署名要Entitlements
### 3. 同梱/検出戦略
**優先順**: 埋め込み`lld` → システム`lld` → 代替mold/link.exe/ld64
```bash
nyash toolchain doctor # 検出&パス設定
--linker=lld|mold|link.exe|ld64 # 明示上書き
```
### 4. ランタイム同梱
- `nyashrt`を**static.a/.lib**と**shared.so/.dll**両用意
- 既定は**static**(配布が楽)、`--shared-rt`で動的リンクに切替
- Windowsは**PDB生成**、Linuxは`-g`/`-Wl,--build-id`でデバッグ容易に
## 🔧 エラー整合(ビルド失敗をわかりやすく)
| エラー種別 | 戻り値 | 説明・対処 |
|----------|-------|-----------|
| `ny_mir_to_obj`失敗 | `NYCG_ERR_*` | ターゲット不一致/CLIF生成失敗など |
| リンク失敗 | リンカ標準出力 | ファイル名/未解決シンボルを整形表示 |
診断オプション:
```bash
--emit=clif,asm,obj,link-cmd # 診断をファイル出力(再現しやすい)
```
## 💾 キャッシュ&クロスコンパイル
### オブジェクトキャッシュ
`hash(MIR, target, codegen_ver)``.obj/.o`を再利用
### クロスコンパイル
```bash
--target=<triple> # .obj/.oとリンク器/SDKを切替
```
- Win用: `x86_64-pc-windows-msvc``lld-link` + MSVCライブラリ
- Linux: `x86_64-unknown-linux-gnu``ld.lld` + glibc
**Zig toolchain**を併用するとクロス用のCRT/SDKが楽内部はlld
## 🎨 使いやすいCLI例
```bash
nyash build main.ny --backend=cranelift --release
nyash build main.ny --emit=obj,asm,clif # 解析用
nyash run main.ny --backend=cranelift # JITで即実行
nyash toolchain doctor # lld/SDK検出
```
## ⚡ 地味に効く最適化スイッチ
### リンカ最適化
- `ld.lld`: `--gc-sections --icf=all`(不要コード除去&同一関数折りたたみ)
### Cranelift最適化
- `opt_level=speed`
- TypedArrayの**bounds-check併合**をLowerで実装
### 実行時最適化
- 起動時CPUIDで**関数ポインタ切替**AVX2/512の専用小関数
## ✅ 最初の"動くまで"チェックリスト
- [ ] `ny_mir_to_obj`C ABI`.o/.obj`を返せる
- [ ] `nyash link <obj> --target=<triple>``lld`でEXEを作れる
- [ ] Windows/Linuxそれぞれ"Hello, Box!"実行成功
- [ ] `--emit=clif,asm`でダンプが落ちる
- [ ] 失敗時のエラーメッセージが**ファイル名+未解決シンボル**まで出る
- [ ] `nyash toolchain doctor`でlld/SDK検出
## 📐 実装設計詳細
### LinkerBox設計
```nyash
box LinkerBox {
init { platform, linker_path, libraries, flags }
link(objects, output_path) {
local cmd = me.build_link_command(objects, output_path)
local result = me.execute_linker(cmd)
if result.exit_code != 0 {
me.format_link_error(result.stderr)
}
return result
}
detect_linker() {
// 優先順: 内蔵lld → システムlld → 代替
if me.has_embedded_lld() {
return me.extract_embedded_lld()
}
return me.find_system_linker()
}
}
```
### CraneliftBox統合
```nyash
box CraneliftBox {
init { target_triple, opt_level }
compile(mir) {
// MIR13 → Cranelift IR → Object
local module = me.create_module()
for inst in mir.instructions {
me.lower_instruction(module, inst)
}
return module.compile()
}
}
```
## 🌟 まとめ
- **Yes**: CraneliftでEXEにするには**内部でlldを叩く機能を埋め込む**のが正攻法
- 仕組みは**MIR→Cranelift .o/.obj → lld**
- C ABIファサード経由でcodegenを呼び、リンカは**内蔵ドライバ**で統一
- これで**自己ホスト→即EXE生成**の"気持ちいい体験"が完成!
## 🔗 関連ドキュメント
- [Phase 15メインドキュメント](README.md)
- [C ABI境界設計](../phase-12/c-abi-spec.md)
- [MIR 13命令セット](../../reference/mir/INSTRUCTION_SET.md)
- [Cranelift統合](../phase-10/)