Phase 25.1b: Step2完了(FuncBodyBasicLowerBox導入)
Step2実装内容: - FuncBodyBasicLowerBox導入(defs専用下請けモジュール) - _try_lower_local_if_return実装(Local+単純if) - _inline_local_ints実装(軽い正規化) - minimal lowers統合(Return/BinOp/IfCompare/MethodArray系) Fail-Fast体制確立: - MirBuilderBox: defs_onlyでも必ずタグ出力 - [builder/selfhost-first:unsupported:defs_only] - [builder/selfhost-first:unsupported:no_match] Phase構造整備: - Phase 25.1b README新設(Step0-3計画) - Phase 25.2b README新設(次期計画) - UsingResolverBox追加(using system対応準備) スモークテスト: - stage1_launcher_program_to_mir_canary_vm.sh追加 Next: Step3 LoopForm対応 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -29,13 +29,13 @@ static box HakoCli {
|
||||
@cmd = "" + cmd_raw
|
||||
|
||||
if cmd == "run" {
|
||||
return self.cmd_run(args)
|
||||
return me.cmd_run(args)
|
||||
} else if cmd == "build" {
|
||||
return self.cmd_build(args)
|
||||
return me.cmd_build(args)
|
||||
} else if cmd == "emit" {
|
||||
return self.cmd_emit(args)
|
||||
return me.cmd_emit(args)
|
||||
} else if cmd == "check" {
|
||||
return self.cmd_check(args)
|
||||
return me.cmd_check(args)
|
||||
}
|
||||
|
||||
print("[hakorune] unknown command: " + cmd)
|
||||
@ -63,7 +63,7 @@ static box HakoCli {
|
||||
@sub_raw = args.get(1)
|
||||
@sub = "" + sub_raw
|
||||
if sub == "exe" {
|
||||
return self.cmd_build_exe(args)
|
||||
return me.cmd_build_exe(args)
|
||||
}
|
||||
|
||||
print("[hakorune] build: unknown subcommand: " + sub)
|
||||
@ -86,7 +86,7 @@ static box HakoCli {
|
||||
@source_path = null
|
||||
|
||||
@i = 2
|
||||
while i < argc {
|
||||
loop(i < argc) {
|
||||
@arg_raw = args.get(i)
|
||||
@arg = "" + arg_raw
|
||||
if arg == "-o" || arg == "--out" {
|
||||
@ -116,66 +116,53 @@ static box HakoCli {
|
||||
return 91
|
||||
}
|
||||
|
||||
// Read Hako source
|
||||
@fb = new FileBox()
|
||||
@ok = fb.open(source_path, "r")
|
||||
if ok != 1 {
|
||||
print("[hakorune] build exe: failed to open source " + source_path)
|
||||
return 91
|
||||
}
|
||||
@src = fb.read()
|
||||
fb.close()
|
||||
if src == null || src == "" {
|
||||
print("[hakorune] build exe: source is empty")
|
||||
return 91
|
||||
}
|
||||
local tag = "[hakorune] build exe"
|
||||
local src = me._read_file(tag, source_path)
|
||||
if src == null { return 91 }
|
||||
|
||||
// .hako → Program(JSON v0)
|
||||
@prog = BuildBox.emit_program_json_v0(src, null)
|
||||
local prog = BuildBox.emit_program_json_v0(src, null)
|
||||
if prog == null {
|
||||
print("[hakorune] build exe: BuildBox returned null")
|
||||
return 91
|
||||
}
|
||||
@ps = "" + prog
|
||||
local ps = "" + prog
|
||||
if ps.indexOf("\"version\":0") < 0 || ps.indexOf("\"kind\":\"Program\"") < 0 {
|
||||
print("[hakorune] build exe: unexpected Program(JSON) output (missing version/kind)")
|
||||
return 91
|
||||
}
|
||||
|
||||
// Program(JSON v0) → MIR(JSON)
|
||||
@mir = MirBuilderBox.emit_from_program_json_v0(ps, null)
|
||||
local mir = MirBuilderBox.emit_from_program_json_v0(ps, null)
|
||||
if mir == null {
|
||||
print("[hakorune] build exe: MirBuilderBox returned null")
|
||||
return 91
|
||||
}
|
||||
@ms = "" + mir
|
||||
local ms = "" + mir
|
||||
|
||||
// MIR(JSON) → object via env.codegen.emit_object
|
||||
@emit_args = new ArrayBox()
|
||||
local emit_args = new ArrayBox()
|
||||
emit_args.push(ms)
|
||||
@obj = hostbridge.extern_invoke("env.codegen", "emit_object", emit_args)
|
||||
local obj = hostbridge.extern_invoke("env.codegen", "emit_object", emit_args)
|
||||
if obj == null || ("" + obj) == "" {
|
||||
print("[hakorune] build exe: env.codegen.emit_object failed")
|
||||
return 91
|
||||
}
|
||||
@obj_path = "" + obj
|
||||
local obj_path = "" + obj
|
||||
|
||||
// object → EXE via env.codegen.link_object
|
||||
@link_args = new ArrayBox()
|
||||
local link_args = new ArrayBox()
|
||||
link_args.push(obj_path)
|
||||
if out_path != null && out_path != "" {
|
||||
link_args.push(out_path)
|
||||
}
|
||||
@exe = hostbridge.extern_invoke("env.codegen", "link_object", link_args)
|
||||
local exe = hostbridge.extern_invoke("env.codegen", "link_object", link_args)
|
||||
if exe == null || ("" + exe) == "" {
|
||||
print("[hakorune] build exe: env.codegen.link_object failed")
|
||||
return 91
|
||||
}
|
||||
@exe_path = "" + exe
|
||||
local exe_path = "" + exe
|
||||
|
||||
if quiet != 1 {
|
||||
print("[hakorune] build exe: " + exe_path)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -192,9 +179,9 @@ static box HakoCli {
|
||||
@sub_raw = args.get(1)
|
||||
@sub = "" + sub_raw
|
||||
if sub == "mir-json" {
|
||||
return self.cmd_emit_mir_json(args)
|
||||
return me.cmd_emit_mir_json(args)
|
||||
} else if sub == "program-json" {
|
||||
return self.cmd_emit_program_json(args)
|
||||
return me.cmd_emit_program_json(args)
|
||||
}
|
||||
|
||||
print("[hakorune] emit: unknown subcommand: " + sub)
|
||||
@ -212,20 +199,20 @@ static box HakoCli {
|
||||
return 92
|
||||
}
|
||||
|
||||
@path = null
|
||||
@out_path = null
|
||||
@quiet = 0
|
||||
local path = null
|
||||
local out_path = null
|
||||
local quiet = 0
|
||||
|
||||
@i = 2
|
||||
while i < argc {
|
||||
@arg_raw = args.get(i)
|
||||
@arg = "" + arg_raw
|
||||
local i = 2
|
||||
loop(i < argc) {
|
||||
local arg_raw = args.get(i)
|
||||
local arg = "" + arg_raw
|
||||
if arg == "-o" || arg == "--out" {
|
||||
if i + 1 >= argc {
|
||||
print("[hakorune] emit program-json: -o/--out requires a path")
|
||||
return 92
|
||||
}
|
||||
@op_raw = args.get(i + 1)
|
||||
local op_raw = args.get(i + 1)
|
||||
out_path = "" + op_raw
|
||||
i = i + 2
|
||||
} else if arg == "--quiet" {
|
||||
@ -247,46 +234,26 @@ static box HakoCli {
|
||||
return 92
|
||||
}
|
||||
|
||||
// Read Hako source from file
|
||||
@fb = new FileBox()
|
||||
@ok = fb.open(path, "r")
|
||||
if ok != 1 {
|
||||
print("[hakorune] emit program-json: failed to open " + path)
|
||||
return 92
|
||||
}
|
||||
@src = fb.read()
|
||||
fb.close()
|
||||
if src == null || src == "" {
|
||||
print("[hakorune] emit program-json: source is empty")
|
||||
return 92
|
||||
}
|
||||
local tag = "[hakorune] emit program-json"
|
||||
local src = me._read_file(tag, path)
|
||||
if src == null { return 92 }
|
||||
|
||||
// Compile to Program(JSON v0) via BuildBox
|
||||
@prog = BuildBox.emit_program_json_v0(src, null)
|
||||
local prog = BuildBox.emit_program_json_v0(src, null)
|
||||
if prog == null {
|
||||
print("[hakorune] emit program-json: BuildBox returned null")
|
||||
return 92
|
||||
}
|
||||
|
||||
// Minimal validation: require Program(version 0)
|
||||
@ps = "" + prog
|
||||
local ps = "" + prog
|
||||
if ps.indexOf("\"version\":0") < 0 || ps.indexOf("\"kind\":\"Program\"") < 0 {
|
||||
print("[hakorune] emit program-json: unexpected output (missing version/kind)")
|
||||
return 92
|
||||
}
|
||||
|
||||
if out_path != null && out_path != "" {
|
||||
@out_fb = new FileBox()
|
||||
@ok2 = out_fb.open(out_path, "w")
|
||||
if ok2 != 1 {
|
||||
print("[hakorune] emit program-json: failed to open output " + out_path)
|
||||
if me._write_file(tag, out_path, ps, quiet) != 1 {
|
||||
return 92
|
||||
}
|
||||
out_fb.write(ps)
|
||||
out_fb.close()
|
||||
if quiet != 1 {
|
||||
print("[hakorune] emit program-json: written " + out_path)
|
||||
}
|
||||
} else {
|
||||
print(ps)
|
||||
}
|
||||
@ -298,23 +265,23 @@ static box HakoCli {
|
||||
// - Program(JSON v0) から MIR(JSON) を生成する経路に加えて、
|
||||
// .hako ソースから直接 Program(JSON v0)→MIR(JSON) まで進める経路もサポートする。
|
||||
method cmd_emit_mir_json(args){
|
||||
@argc = 0
|
||||
local argc = 0
|
||||
if args { argc = args.size() }
|
||||
|
||||
@prog_path = null
|
||||
@source_path = null
|
||||
@out_path = null
|
||||
@quiet = 0
|
||||
@i = 2
|
||||
while i < argc {
|
||||
@arg_raw = args.get(i)
|
||||
@arg = "" + arg_raw
|
||||
local prog_path = null
|
||||
local source_path = null
|
||||
local out_path = null
|
||||
local quiet = 0
|
||||
local i = 2
|
||||
loop(i < argc) {
|
||||
local arg_raw = args.get(i)
|
||||
local arg = "" + arg_raw
|
||||
if arg == "--from-program-json" {
|
||||
if i + 1 >= argc {
|
||||
print("[hakorune] emit mir-json: --from-program-json requires a path")
|
||||
return 92
|
||||
}
|
||||
@p_raw = args.get(i + 1)
|
||||
local p_raw = args.get(i + 1)
|
||||
prog_path = "" + p_raw
|
||||
i = i + 2
|
||||
} else if arg == "-o" || arg == "--out" {
|
||||
@ -322,14 +289,13 @@ static box HakoCli {
|
||||
print("[hakorune] emit mir-json: -o/--out requires a path")
|
||||
return 92
|
||||
}
|
||||
@op_raw = args.get(i + 1)
|
||||
local op_raw = args.get(i + 1)
|
||||
out_path = "" + op_raw
|
||||
i = i + 2
|
||||
} else if arg == "--quiet" {
|
||||
quiet = 1
|
||||
i = i + 1
|
||||
} else {
|
||||
// Interpret as <source.hako> when not already set
|
||||
if source_path == null {
|
||||
source_path = arg
|
||||
i = i + 1
|
||||
@ -340,54 +306,32 @@ static box HakoCli {
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent ambiguous usage
|
||||
if prog_path != null && prog_path != "" && source_path != null && source_path != "" {
|
||||
print("[hakorune] emit mir-json: specify either --from-program-json or <source.hako>, not both")
|
||||
return 92
|
||||
}
|
||||
|
||||
@prog_json = null
|
||||
if (prog_path == null || prog_path == "") && (source_path == null || source_path == "") {
|
||||
print("[hakorune] emit mir-json: require --from-program-json <file> or <source.hako>")
|
||||
return 92
|
||||
}
|
||||
|
||||
local tag = "[hakorune] emit mir-json"
|
||||
local prog_json = null
|
||||
|
||||
if prog_path != null && prog_path != "" {
|
||||
// Read Program(JSON v0) from file
|
||||
@fb = new FileBox()
|
||||
@ok = fb.open(prog_path, "r")
|
||||
if ok != 1 {
|
||||
print("[hakorune] emit mir-json: failed to open " + prog_path)
|
||||
return 92
|
||||
}
|
||||
@p = fb.read()
|
||||
fb.close()
|
||||
if p == null || p == "" {
|
||||
print("[hakorune] emit mir-json: program JSON is empty")
|
||||
return 92
|
||||
}
|
||||
prog_json = p
|
||||
local prog_text = me._read_file(tag, prog_path)
|
||||
if prog_text == null { return 92 }
|
||||
prog_json = prog_text
|
||||
} else {
|
||||
// Expect .hako source path
|
||||
if source_path == null || source_path == "" {
|
||||
print("[hakorune] emit mir-json: require --from-program-json <file> or <source.hako>")
|
||||
return 92
|
||||
}
|
||||
@fb2 = new FileBox()
|
||||
@ok2 = fb2.open(source_path, "r")
|
||||
if ok2 != 1 {
|
||||
print("[hakorune] emit mir-json: failed to open source " + source_path)
|
||||
return 92
|
||||
}
|
||||
@src = fb2.read()
|
||||
fb2.close()
|
||||
if src == null || src == "" {
|
||||
print("[hakorune] emit mir-json: source is empty")
|
||||
return 92
|
||||
}
|
||||
// Compile to Program(JSON v0) via BuildBox
|
||||
@prog = BuildBox.emit_program_json_v0(src, null)
|
||||
local src = me._read_file(tag, source_path)
|
||||
if src == null { return 92 }
|
||||
local prog = BuildBox.emit_program_json_v0(src, null)
|
||||
if prog == null {
|
||||
print("[hakorune] emit mir-json: BuildBox returned null")
|
||||
return 92
|
||||
}
|
||||
@ps = "" + prog
|
||||
local ps = "" + prog
|
||||
if ps.indexOf("\"version\":0") < 0 || ps.indexOf("\"kind\":\"Program\"") < 0 {
|
||||
print("[hakorune] emit mir-json: unexpected Program(JSON) output (missing version/kind)")
|
||||
return 92
|
||||
@ -395,27 +339,17 @@ static box HakoCli {
|
||||
prog_json = ps
|
||||
}
|
||||
|
||||
// Convert Program(JSON v0) → MIR(JSON) via MirBuilderBox
|
||||
@mir = MirBuilderBox.emit_from_program_json_v0(prog_json, null)
|
||||
local mir = MirBuilderBox.emit_from_program_json_v0(prog_json, null)
|
||||
if mir == null {
|
||||
print("[hakorune] emit mir-json: MirBuilderBox returned null")
|
||||
return 92
|
||||
}
|
||||
|
||||
// Success: emit MIR(JSON) to stdout or file
|
||||
@ms = "" + mir
|
||||
local ms = "" + mir
|
||||
if out_path != null && out_path != "" {
|
||||
@out_fb = new FileBox()
|
||||
@ok3 = out_fb.open(out_path, "w")
|
||||
if ok3 != 1 {
|
||||
print("[hakorune] emit mir-json: failed to open output " + out_path)
|
||||
if me._write_file(tag, out_path, ms, quiet) != 1 {
|
||||
return 92
|
||||
}
|
||||
out_fb.write(ms)
|
||||
out_fb.close()
|
||||
if quiet != 1 {
|
||||
print("[hakorune] emit mir-json: written " + out_path)
|
||||
}
|
||||
} else {
|
||||
print(ms)
|
||||
}
|
||||
@ -423,18 +357,56 @@ static box HakoCli {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
// hakorune check <entry.hako>
|
||||
// - Reserved for future static checks (syntax/using/subset).
|
||||
method cmd_check(args){
|
||||
print("[hakorune] check: not implemented yet")
|
||||
return 93
|
||||
}
|
||||
|
||||
// Helpers for file I/O (Phase 25.1a: consolidate Stage‑B friendly patterns)
|
||||
method _read_file(tag, path){
|
||||
if path == null || path == "" {
|
||||
print(tag + ": source path is required")
|
||||
return null
|
||||
}
|
||||
local fb = new FileBox()
|
||||
local ok = fb.open(path, "r")
|
||||
if ok != 1 {
|
||||
print(tag + ": failed to open " + path)
|
||||
return null
|
||||
}
|
||||
local content = fb.read()
|
||||
fb.close()
|
||||
if content == null || content == "" {
|
||||
print(tag + ": source is empty")
|
||||
return null
|
||||
}
|
||||
return "" + content
|
||||
}
|
||||
|
||||
method _write_file(tag, path, content, quiet){
|
||||
if path == null || path == "" { return 1 }
|
||||
local fb = new FileBox()
|
||||
local ok = fb.open(path, "w")
|
||||
if ok != 1 {
|
||||
print(tag + ": failed to open output " + path)
|
||||
return 0
|
||||
}
|
||||
fb.write(content)
|
||||
fb.close()
|
||||
if quiet != 1 {
|
||||
print(tag + ": written " + path)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
static box Main {
|
||||
// Main entrypoint for Stage1 hakorune CLI.
|
||||
// args: raw argv array (excluding executable name).
|
||||
main(args){
|
||||
method main(args){
|
||||
@cli = new HakoCli()
|
||||
return cli.run(args)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user