📚 Phase 15 - セルフホスティング戦略の明確化とEXE-first実装
## 主な変更点 ### 🎯 戦略の転換と明確化 - 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>
This commit is contained in:
@ -124,17 +124,31 @@ class PyVM:
|
||||
op = inst.get("op")
|
||||
|
||||
if op == "phi":
|
||||
# incoming: [[vid, pred_bid], ...]
|
||||
# incoming: prefer [[vid, pred_bid]], but accept [pred_bid, vid] robustly
|
||||
incoming = inst.get("incoming", [])
|
||||
chosen: Any = None
|
||||
# Prefer predecessor match; otherwise fallback to first
|
||||
for vid, pb in incoming:
|
||||
if prev is not None and int(pb) == int(prev):
|
||||
chosen = regs.get(int(vid))
|
||||
for pair in incoming:
|
||||
if not isinstance(pair, (list, tuple)) or len(pair) < 2:
|
||||
continue
|
||||
a, b = pair[0], pair[1]
|
||||
# Case 1: [vid, pred]
|
||||
if prev is not None and int(b) == int(prev) and int(a) in regs:
|
||||
chosen = regs.get(int(a))
|
||||
break
|
||||
# Case 2: [pred, vid]
|
||||
if prev is not None and int(a) == int(prev) and int(b) in regs:
|
||||
chosen = regs.get(int(b))
|
||||
break
|
||||
if chosen is None and incoming:
|
||||
vid, _ = incoming[0]
|
||||
chosen = regs.get(int(vid))
|
||||
# Fallback to first element that resolves to a known vid
|
||||
for pair in incoming:
|
||||
if not isinstance(pair, (list, tuple)) or len(pair) < 2:
|
||||
continue
|
||||
a, b = pair[0], pair[1]
|
||||
if int(a) in regs:
|
||||
chosen = regs.get(int(a)); break
|
||||
if int(b) in regs:
|
||||
chosen = regs.get(int(b)); break
|
||||
self._set(regs, inst.get("dst"), chosen)
|
||||
i += 1
|
||||
continue
|
||||
@ -229,6 +243,30 @@ class PyVM:
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if op == "unop":
|
||||
kind = inst.get("kind")
|
||||
src = self._read(regs, inst.get("src"))
|
||||
out: Any
|
||||
if kind == "neg":
|
||||
if isinstance(src, (int, float)):
|
||||
out = -src
|
||||
elif src is None:
|
||||
out = 0
|
||||
else:
|
||||
try:
|
||||
out = -int(src)
|
||||
except Exception:
|
||||
out = 0
|
||||
elif kind == "not":
|
||||
out = 0 if self._truthy(src) else 1
|
||||
elif kind == "bitnot":
|
||||
out = ~int(src) if src is not None else -1
|
||||
else:
|
||||
out = None
|
||||
self._set(regs, inst.get("dst"), out)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if op == "newbox":
|
||||
btype = inst.get("type")
|
||||
if btype == "ConsoleBox":
|
||||
@ -236,6 +274,10 @@ class PyVM:
|
||||
elif btype == "StringBox":
|
||||
# empty string instance
|
||||
val = ""
|
||||
elif btype == "ArrayBox":
|
||||
val = {"__box__": "ArrayBox", "__arr": []}
|
||||
elif btype == "MapBox":
|
||||
val = {"__box__": "MapBox", "__map": {}}
|
||||
else:
|
||||
# Unknown box -> opaque
|
||||
val = {"__box__": btype}
|
||||
@ -302,6 +344,58 @@ class PyVM:
|
||||
out = os.path.join(base, rel)
|
||||
else:
|
||||
out = None
|
||||
# ArrayBox minimal methods
|
||||
elif isinstance(recv, dict) and recv.get("__box__") == "ArrayBox":
|
||||
arr = recv.get("__arr", [])
|
||||
if method in ("len", "size"):
|
||||
out = len(arr)
|
||||
elif method == "get":
|
||||
idx = int(args[0]) if args else 0
|
||||
out = arr[idx] if 0 <= idx < len(arr) else None
|
||||
elif method == "set":
|
||||
idx = int(args[0]) if len(args) > 0 else 0
|
||||
val = args[1] if len(args) > 1 else None
|
||||
if 0 <= idx < len(arr):
|
||||
arr[idx] = val
|
||||
elif idx == len(arr):
|
||||
arr.append(val)
|
||||
else:
|
||||
# extend with None up to idx, then set
|
||||
while len(arr) < idx:
|
||||
arr.append(None)
|
||||
arr.append(val)
|
||||
out = 0
|
||||
elif method == "push":
|
||||
val = args[0] if args else None
|
||||
arr.append(val)
|
||||
out = len(arr)
|
||||
elif method == "toString":
|
||||
out = "[" + ",".join(str(x) for x in arr) + "]"
|
||||
else:
|
||||
out = None
|
||||
recv["__arr"] = arr
|
||||
# MapBox minimal methods
|
||||
elif isinstance(recv, dict) and recv.get("__box__") == "MapBox":
|
||||
m = recv.get("__map", {})
|
||||
if method == "size":
|
||||
out = len(m)
|
||||
elif method == "has":
|
||||
key = str(args[0]) if args else ""
|
||||
out = 1 if key in m else 0
|
||||
elif method == "get":
|
||||
key = str(args[0]) if args else ""
|
||||
out = m.get(key)
|
||||
elif method == "set":
|
||||
key = str(args[0]) if len(args) > 0 else ""
|
||||
val = args[1] if len(args) > 1 else None
|
||||
m[key] = val
|
||||
out = 0
|
||||
elif method == "toString":
|
||||
items = ",".join(f"{k}:{m[k]}" for k in m)
|
||||
out = "{" + items + "}"
|
||||
else:
|
||||
out = None
|
||||
recv["__map"] = m
|
||||
elif method == "esc_json":
|
||||
# Escape backslash and double-quote in the given string argument
|
||||
s = args[0] if args else ""
|
||||
|
||||
Reference in New Issue
Block a user