## 主な変更点 ### 🎯 戦略の転換と明確化 - PyVMを開発ツールとして位置づけ(本番経路ではない) - EXE-first戦略を明確に優先(build_compiler_exe.sh実装済み) - Phase順序の整理: 15.2(LLVM)→15.3(コンパイラ)→15.4(VM) ### 🚀 セルフホスティング基盤の実装 - apps/selfhost-compiler/にNyashコンパイラMVP実装 - compiler.nyash: メインエントリー(位置引数対応) - boxes/: parser_box, emitter_box, debug_box分離 - tools/build_compiler_exe.sh: ネイティブEXEビルド+dist配布 - Python MVPパーサーStage-2完成(local/if/loop/call/method/new) ### 📝 ドキュメント整備 - Phase 15 README/ROADMAP更新(Self-Hosting優先明記) - docs/guides/exe-first-wsl.md: WSLクイックスタート追加 - docs/private/papers/: 論文G~L、爆速事件簿41事例収録 ### 🔧 技術的改善 - JSON v0 Bridge: If/Loop PHI生成実装(ChatGPT協力) - PyVM/llvmliteパリティ検証スイート追加 - using/namespace機能(gated実装、Phase 15では非解決) ## 次のステップ 1. パーサー無限ループ修正(未実装関数の実装) 2. EXEビルドとセルフホスティング実証 3. c0→c1→c1'ブートストラップループ確立 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
109 lines
3.0 KiB
Plaintext
109 lines
3.0 KiB
Plaintext
// Selfhost Compiler MVP (Phase 15.3)
|
||
// Reads tmp/ny_parser_input.ny and prints a minimal JSON v0 program.
|
||
// Components are split under boxes/ and included here.
|
||
|
||
include "apps/selfhost-compiler/boxes/debug_box.nyash"
|
||
include "apps/selfhost-compiler/boxes/parser_box.nyash"
|
||
include "apps/selfhost-compiler/boxes/emitter_box.nyash"
|
||
|
||
static box Main {
|
||
// ---- IO helper ----
|
||
read_all(path) {
|
||
local fb = new FileBox()
|
||
fb.open(path, "r")
|
||
local s = fb.read()
|
||
fb.close()
|
||
if s == null { return "return 1+2*3" }
|
||
return s
|
||
}
|
||
|
||
// ---- JSON helpers ----
|
||
esc_json(s) {
|
||
local out = ""
|
||
local i = 0
|
||
local n = s.length()
|
||
loop(i < n) {
|
||
local ch = s.substring(i, i+1)
|
||
if ch == "\\" { out = out + "\\\\" } else {
|
||
if ch == "\"" { out = out + "\\\"" } else { out = out + ch }
|
||
}
|
||
i = i + 1
|
||
}
|
||
return out
|
||
}
|
||
|
||
// Parser delegation
|
||
parse_program(src) {
|
||
local parser = new ParserBox()
|
||
// Collect using metadata (no-op acceptance in Stage‑15)
|
||
parser.extract_usings(src)
|
||
me._usings = parser.get_usings_json()
|
||
return parser.parse_program2(src)
|
||
}
|
||
|
||
main(args) {
|
||
// Debug setup
|
||
me.dbg = new DebugBox()
|
||
me.dbg.set_enabled(0)
|
||
|
||
// Source selection (EXE-first friendly)
|
||
// - default: safe constant
|
||
// - positional arg: treat as input file path
|
||
// - --read-tmp: use tmp/ny_parser_input.ny (requires FileBox plugin)
|
||
local src = "return 1+2*3"
|
||
local read_tmp = 0
|
||
local input_path = null
|
||
if args != null {
|
||
local alen = args.length()
|
||
local i = 0
|
||
loop(i < alen) {
|
||
local a = args.get(i)
|
||
if a == "--read-tmp" { read_tmp = 1 } else {
|
||
if a == "--min-json" { /* handled later */ } else {
|
||
// First non-flag arg as input path
|
||
if input_path == null { input_path = a }
|
||
}
|
||
}
|
||
i = i + 1
|
||
}
|
||
}
|
||
if input_path != null {
|
||
// Prefer explicit file when provided (requires FileBox plugin)
|
||
local s1 = me.read_all(input_path)
|
||
if s1 != null { src = s1 }
|
||
} else {
|
||
if read_tmp == 1 {
|
||
// Optional: read tmp/ny_parser_input.ny (requires FileBox plugin; do not use in CI)
|
||
local s2 = me.read_all("tmp/ny_parser_input.ny")
|
||
if s2 != null { src = s2 }
|
||
}
|
||
}
|
||
|
||
// Gate: minimal JSON when requested via script arg
|
||
local min_mode = 0
|
||
if args != null {
|
||
local alen = args.length()
|
||
local i = 0
|
||
loop(i < alen) {
|
||
if args.get(i) == "--min-json" { min_mode = 1 }
|
||
i = i + 1
|
||
}
|
||
}
|
||
local json = null
|
||
if min_mode == 1 {
|
||
json = "{\"version\":0,\"kind\":\"Program\",\"body\":[{\"type\":\"Return\",\"expr\":{\"type\":\"Int\",\"value\":0}}]}"
|
||
} else {
|
||
json = me.parse_program(src)
|
||
}
|
||
|
||
// Emit via EmitterBox (attach meta.usings when available)
|
||
local emitter = new EmitterBox()
|
||
json = emitter.emit_program(json, me._usings)
|
||
|
||
// Output
|
||
local console = new ConsoleBox()
|
||
console.println(json)
|
||
return 0
|
||
}
|
||
}
|