interp: 실패해도 그때까지의 출력을 보여준다
0으로 나누는 프로그램을 돌려보니 실패 전에 출력한 것이 통째로 사라졌다. Interp.run이 출력을 버퍼에 모았다가 성공했을 때만 돌려주고 실패하면 버렸다. print는 실제로 일어난 effect다. 일어난 일을 안 보여주면 "어디까지 갔나"를 알 수 없고, 그게 실패했을 때 가장 먼저 보고 싶은 것이다. Interp.run과 Session.run이 이제 (출력, 실패 여부)를 함께 돌려준다. result가 아니라 짝인 이유는 둘이 배타가 아니기 때문이다 — 실패했어도 출력은 있다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
This commit is contained in:
+9
-6
@@ -484,14 +484,17 @@ and eval_binary st env op a b pos =
|
||||
|
||||
(* main이 선언한 capability만 런타임이 넘긴다. 선언하지 않은 권한은
|
||||
프로그램 안에 존재하지 않는다. *)
|
||||
(* 실패해도 그때까지 나온 출력을 함께 돌려준다.
|
||||
print는 실제로 일어난 effect다. 일어난 일을 안 보여주면 "어디까지 갔나"를
|
||||
알 수 없고, 그게 실패했을 때 가장 먼저 보고 싶은 것이다. *)
|
||||
let run ?(args = []) (prog : Ir.program) (entry : string)
|
||||
(main_params : (string * string) list) : (string, Token.pos * string) result
|
||||
(main_params : (string * string) list) : string * (Token.pos * string) option
|
||||
=
|
||||
Buffer.clear out;
|
||||
argv := args;
|
||||
let st = { prog } in
|
||||
match Hashtbl.find_opt prog.Ir.fns (entry ^ "#main") with
|
||||
| None -> Error (Token.{ line = 0; col = 0 }, "main 함수가 없습니다")
|
||||
| None -> ("", Some (Token.{ line = 0; col = 0 }, "main 함수가 없습니다"))
|
||||
| Some fn -> (
|
||||
let args =
|
||||
List.map
|
||||
@@ -503,12 +506,12 @@ let run ?(args = []) (prog : Ir.program) (entry : string)
|
||||
main_params
|
||||
in
|
||||
match List.find_opt Result.is_error args with
|
||||
| Some (Error m) -> Error (Token.{ line = 0; col = 0 }, m)
|
||||
| Some (Error m) -> ("", Some (Token.{ line = 0; col = 0 }, m))
|
||||
| _ -> (
|
||||
let args = List.map Result.get_ok args in
|
||||
try
|
||||
ignore (apply st Token.{ line = 0; col = 0 } (VFn fn) args);
|
||||
Ok (Buffer.contents out)
|
||||
(Buffer.contents out, None)
|
||||
with
|
||||
| Fail (pos, msg) -> Error (pos, msg)
|
||||
| Return_exc _ -> Ok (Buffer.contents out)))
|
||||
| Fail (pos, msg) -> (Buffer.contents out, Some (pos, msg))
|
||||
| Return_exc _ -> (Buffer.contents out, None)))
|
||||
|
||||
+6
-5
@@ -258,14 +258,15 @@ let main_params (m : Ast.modul) =
|
||||
| _ -> [])
|
||||
m.items
|
||||
|
||||
let run ?(args = []) st path : (string, error) result =
|
||||
(* 출력과 실패를 함께 돌려준다. 실패해도 그때까지 나온 것은 보여줘야 한다 *)
|
||||
let run ?(args = []) st path : string * error option =
|
||||
load st path;
|
||||
let errs = errors st in
|
||||
if errs <> [] then Error (List.hd errs)
|
||||
if errs <> [] then ("", Some (List.hd errs))
|
||||
else
|
||||
match find st path with
|
||||
| None ->
|
||||
Error { file = path; line = 0; col = 0; message = "모듈을 찾을 수 없습니다" }
|
||||
("", Some { file = path; line = 0; col = 0; message = "모듈을 찾을 수 없습니다" })
|
||||
| Some e -> (
|
||||
(* IR은 그래프 전체를 받는다. 별칭이 실행 의미에 남지 않도록. *)
|
||||
let mods =
|
||||
@@ -276,5 +277,5 @@ let run ?(args = []) st path : (string, error) result =
|
||||
in
|
||||
let prog = Ir.of_program mods in
|
||||
match Interp.run ~args prog path (main_params e.ast) with
|
||||
| Ok out -> Ok out
|
||||
| Error (pos, msg) -> Error (err_of path pos msg))
|
||||
| out, None -> (out, None)
|
||||
| out, Some (pos, msg) -> (out, Some (err_of path pos msg)))
|
||||
|
||||
Reference in New Issue
Block a user