2025-09-15 01:21:37 +09:00
|
|
|
|
// Selfhost Compiler MVP (Phase 15.3)
|
|
|
|
|
|
// Reads tmp/ny_parser_input.ny and prints a minimal JSON v0 program.
|
2025-09-15 18:44:49 +09:00
|
|
|
|
// Components are split under boxes/ and included here.
|
|
|
|
|
|
|
2025-09-18 13:35:38 +09:00
|
|
|
|
// Prefer using for module declaration (Runner strips and registers)
|
|
|
|
|
|
using "apps/selfhost-compiler/boxes/debug_box.nyash" as DebugBoxMod
|
|
|
|
|
|
using "apps/selfhost-compiler/boxes/parser_box.nyash" as ParserBoxMod
|
|
|
|
|
|
using "apps/selfhost-compiler/boxes/emitter_box.nyash" as EmitterBoxMod
|
|
|
|
|
|
using "apps/selfhost-compiler/boxes/mir_emitter_box.nyash" as MirEmitterBoxMod
|
|
|
|
|
|
|
2025-09-28 20:38:09 +09:00
|
|
|
|
// (removed) Transitional duplicate using lines to avoid resolver duplicate-import error
|
2025-09-15 01:21:37 +09:00
|
|
|
|
|
|
|
|
|
|
static box Main {
|
|
|
|
|
|
// ---- IO helper ----
|
|
|
|
|
|
read_all(path) {
|
|
|
|
|
|
local fb = new FileBox()
|
|
|
|
|
|
fb.open(path, "r")
|
|
|
|
|
|
local s = fb.read()
|
|
|
|
|
|
fb.close()
|
2025-09-15 18:44:49 +09:00
|
|
|
|
if s == null { return "return 1+2*3" }
|
2025-09-15 01:21:37 +09:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 18:44:49 +09:00
|
|
|
|
// Parser delegation
|
2025-09-16 18:33:59 +09:00
|
|
|
|
parse_program(src, stage3_flag) {
|
2025-09-28 20:40:06 +09:00
|
|
|
|
local parser = new ParserBox()
|
2025-09-16 18:33:59 +09:00
|
|
|
|
if stage3_flag == 1 { parser.stage3_enable(1) }
|
2025-09-15 18:44:49 +09:00
|
|
|
|
// Collect using metadata (no-op acceptance in Stage‑15)
|
|
|
|
|
|
parser.extract_usings(src)
|
|
|
|
|
|
me._usings = parser.get_usings_json()
|
|
|
|
|
|
return parser.parse_program2(src)
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 18:44:49 +09:00
|
|
|
|
main(args) {
|
|
|
|
|
|
// Debug setup
|
2025-09-28 20:40:06 +09:00
|
|
|
|
me.dbg = new DebugBox()
|
2025-09-15 18:44:49 +09:00
|
|
|
|
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
|
2025-09-16 18:33:59 +09:00
|
|
|
|
local stage3_mode = 0
|
2025-09-15 18:44:49 +09:00
|
|
|
|
if args != null {
|
|
|
|
|
|
local alen = args.length()
|
|
|
|
|
|
local i = 0
|
|
|
|
|
|
loop(i < alen) {
|
|
|
|
|
|
local a = args.get(i)
|
2025-09-16 18:33:59 +09:00
|
|
|
|
if a == "--read-tmp" {
|
|
|
|
|
|
read_tmp = 1
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if a == "--min-json" {
|
|
|
|
|
|
/* handled later */
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if a == "--stage3" {
|
|
|
|
|
|
stage3_mode = 1
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if input_path == null { input_path = a }
|
|
|
|
|
|
}
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-15 18:44:49 +09:00
|
|
|
|
i = i + 1
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-15 18:44:49 +09:00
|
|
|
|
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 }
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 18:44:49 +09:00
|
|
|
|
// Gate: minimal JSON when requested via script arg
|
|
|
|
|
|
local min_mode = 0
|
2025-09-18 06:35:49 +09:00
|
|
|
|
local emit_mir = 0
|
2025-09-15 18:44:49 +09:00
|
|
|
|
if args != null {
|
|
|
|
|
|
local alen = args.length()
|
|
|
|
|
|
local i = 0
|
|
|
|
|
|
loop(i < alen) {
|
2025-09-16 18:33:59 +09:00
|
|
|
|
local arg = args.get(i)
|
|
|
|
|
|
if arg == "--min-json" { min_mode = 1 }
|
2025-09-18 06:35:49 +09:00
|
|
|
|
if arg == "--emit-mir" { emit_mir = 1 }
|
2025-09-15 18:44:49 +09:00
|
|
|
|
i = i + 1
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-15 18:44:49 +09:00
|
|
|
|
local json = null
|
2025-09-18 06:35:49 +09:00
|
|
|
|
local ast_json = null
|
2025-09-15 18:44:49 +09:00
|
|
|
|
if min_mode == 1 {
|
2025-09-18 06:35:49 +09:00
|
|
|
|
ast_json = "{\"version\":0,\"kind\":\"Program\",\"body\":[{\"type\":\"Return\",\"expr\":{\"type\":\"Int\",\"value\":0}}]}"
|
2025-09-15 18:44:49 +09:00
|
|
|
|
} else {
|
2025-09-18 06:35:49 +09:00
|
|
|
|
ast_json = me.parse_program(src, stage3_mode)
|
2025-09-15 01:21:37 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-18 06:35:49 +09:00
|
|
|
|
if emit_mir == 1 {
|
|
|
|
|
|
// Lower minimal AST to MIR JSON (Return(Int) only for MVP)
|
2025-09-28 20:40:06 +09:00
|
|
|
|
local mir = new MirEmitterBox()
|
2025-09-18 06:35:49 +09:00
|
|
|
|
json = mir.emit_mir_min(ast_json)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Emit Stage‑1 JSON with metadata
|
2025-09-28 20:40:06 +09:00
|
|
|
|
local emitter = new EmitterBox()
|
2025-09-18 06:35:49 +09:00
|
|
|
|
json = emitter.emit_program(ast_json, me._usings)
|
|
|
|
|
|
}
|
2025-09-15 01:21:37 +09:00
|
|
|
|
|
2025-09-18 06:35:49 +09:00
|
|
|
|
// Output JSON
|
2025-09-15 01:21:37 +09:00
|
|
|
|
local console = new ConsoleBox()
|
|
|
|
|
|
console.println(json)
|
|
|
|
|
|
return 0
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|