naming: panic을 crash로 — 그리고 이름을 고르는 원칙을 철학에 넣는다
철학 6번을 추가했다: 이름은 관례가 아니라 뜻에서 고른다 — 낯섦은 한 번 치르고 끝나지만 부정확함은 읽는 사람마다 매번 치른다. 판정 방법도 같이 적었다. 그 단어로 평범한 문장을 써 보고, 단어가 문장을 도우면 맞는 이름이고 싸우면 틀린 이름이다. "크래시는 복구하는 것이 아니라 조사하는 것이다" — 돕는다 "패닉은 복구할 수 없다" — 다른 언어에서는 할 수 있어 싸운다 panic의 자연어 뜻은 "갑작스러운 공포"다. 반응하는 쪽의 감정이지 결함에 대한 말이 아니다. 그리고 Go/Rust에서는 붙잡을 수 있어 이름이 거짓말을 한다. crash는 "계획 없이 갑자기 완전히 망가져 끝남"이고 복구의 함의가 없다 — 크래시는 복구하는 게 아니라 조사하는 것이다. 어휘의 출신도 이유가 됐다. panic+recover는 Go 전통이고 거기엔 감독이 없다. crash+supervision은 얼랭 전통이며, 우리가 만드는 것이 그쪽이다. 한국어 용어도 세 층으로 정리했다: 실패(Result) / 결함(crash) / 감독. 세 층이 세 가지 다른 기제로 규율된다 — 타입, 없음(발산), capability. "상황이 나쁨"은 결함이 아니라 실패다. 이 선을 안 그으면 crash가 게으름의 배출구가 된다. "오류"는 컴파일러 진단에만 쓴다. 얼랭 질문에 대한 답도 기록했다: 감독은 가져오고 비구조적 spawn은 안 가져온다. sc.spawn과 sup.spawn(sc, f)로 갈리며 문법 변경이 없다 — 실패를 삼키려면 Supervisor를 받았어야 하고 그것이 시그니처에 보인다. 개명은 문법을 먼저 고치고 대조 장치로 확인했다. 문장 500개, 파일 26개 모두 갈림 0건. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
This commit is contained in:
+3
-3
@@ -75,7 +75,7 @@ type expr =
|
||||
| E_try of { inner : expr; pos : pos }
|
||||
| E_unary of { op : unop; operand : expr; pos : pos }
|
||||
(* 복구 불가능한 실패. 타입은 Never — 돌아오지 않으므로 어떤 자리에도 놓인다 *)
|
||||
| E_panic of { msg : expr; pos : pos }
|
||||
| E_crash of { msg : expr; pos : pos }
|
||||
| E_binary of { op : binop; lhs : expr; rhs : expr; pos : pos }
|
||||
|
||||
and closure = {
|
||||
@@ -249,8 +249,8 @@ let binop_name = function
|
||||
|
||||
let rec buf_expr b = function
|
||||
| E_lit (l, _) -> buf_lit b l
|
||||
| E_panic { msg; _ } ->
|
||||
Buffer.add_string b "(panic ";
|
||||
| E_crash { msg; _ } ->
|
||||
Buffer.add_string b "(crash ";
|
||||
buf_expr b msg;
|
||||
Buffer.add_char b ')'
|
||||
| E_ident (n, _) -> Buffer.add_string b n
|
||||
|
||||
+1
-1
@@ -320,7 +320,7 @@ let rec eval st (env : env) (e : Ir.t) : value =
|
||||
| [ f ] -> apply st pos f []
|
||||
| _ -> fail pos "spawn은 함수 하나를 받습니다")
|
||||
| other -> fail pos (Printf.sprintf "%s에는 필드가 없습니다" (show other)))
|
||||
| Ir.I_panic (msg, pos) -> (
|
||||
| Ir.I_crash (msg, pos) -> (
|
||||
match eval st env msg with VStr s -> fail pos s | v -> fail pos (show v))
|
||||
| Ir.I_unary (op, e, pos) -> (
|
||||
match (op, eval st env e) with
|
||||
|
||||
@@ -45,7 +45,7 @@ type t =
|
||||
| I_seq of stmt list * t (* 블록: 문 나열 + 꼬리 값 *)
|
||||
| I_call of { callee : t; args : t list; pos : pos }
|
||||
| I_field of { obj : t; name : string; pos : pos }
|
||||
| I_panic of t * pos
|
||||
| I_crash of t * pos
|
||||
| I_unary of Ast.unop * t * pos
|
||||
| I_binary of Ast.binop * t * t * pos
|
||||
|
||||
@@ -186,7 +186,7 @@ let rec lower_pat c (p : Ast.pattern) : pat =
|
||||
|
||||
let rec lower c (e : Ast.expr) : t =
|
||||
match e with
|
||||
| Ast.E_panic { msg; pos } -> I_panic (lower c msg, pos)
|
||||
| Ast.E_crash { msg; pos } -> I_crash (lower c msg, pos)
|
||||
| Ast.E_lit (l, _) -> I_lit l
|
||||
| Ast.E_ident (n, pos) -> I_ref (classify c n, pos)
|
||||
| Ast.E_list (xs, _) -> I_list (List.map (lower c) xs)
|
||||
|
||||
+2
-2
@@ -187,8 +187,8 @@ type ctx = Borrow | Move of string (* 어디로 옮겨가는지 — 진단에
|
||||
let rec walk st (ctx : ctx) (e : expr) : vinfo =
|
||||
match e with
|
||||
| E_lit _ -> v_copy
|
||||
(* panic은 돌아오지 않지만 메시지 식은 계산된다. 메시지는 빌려 쓴다 *)
|
||||
| E_panic { msg; _ } ->
|
||||
(* crash는 돌아오지 않지만 메시지 식은 계산된다. 메시지는 빌려 쓴다 *)
|
||||
| E_crash { msg; _ } ->
|
||||
ignore (walk st Borrow msg);
|
||||
v_copy
|
||||
| E_ident (n, pos) -> (
|
||||
|
||||
+2
-2
@@ -398,12 +398,12 @@ and parse_primary st =
|
||||
| Token.Kw_fn -> parse_closure st
|
||||
| Token.Kw_if -> parse_if st
|
||||
| Token.Kw_match -> parse_match st
|
||||
| Token.Kw_panic ->
|
||||
| Token.Kw_crash ->
|
||||
adv st;
|
||||
expect st Token.LParen "(";
|
||||
let msg = with_struct_ok st (fun () -> parse_expr st) in
|
||||
expect_close st Token.RParen ")";
|
||||
E_panic { msg; pos = p }
|
||||
E_crash { msg; pos = p }
|
||||
| Token.Kw_scope ->
|
||||
adv st;
|
||||
let name = ident st "새 scope 이름" in
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ let rec resolve_pattern st seen = function
|
||||
|
||||
let rec resolve_expr st = function
|
||||
| E_lit _ -> ()
|
||||
| E_panic { msg; _ } -> resolve_expr st msg
|
||||
| E_crash { msg; _ } -> resolve_expr st msg
|
||||
| E_ident (n, pos) ->
|
||||
if lookup_local st n = None then
|
||||
if Hashtbl.mem st.items n then ()
|
||||
|
||||
+5
-5
@@ -28,7 +28,7 @@ type kind =
|
||||
| Kw_else
|
||||
| Kw_match
|
||||
| Kw_scope
|
||||
| Kw_panic
|
||||
| Kw_crash
|
||||
| Kw_test
|
||||
| Kw_true
|
||||
| Kw_false
|
||||
@@ -89,7 +89,7 @@ let keyword = function
|
||||
| "else" -> Some Kw_else
|
||||
| "match" -> Some Kw_match
|
||||
| "scope" -> Some Kw_scope
|
||||
| "panic" -> Some Kw_panic
|
||||
| "crash" -> Some Kw_crash
|
||||
| "test" -> Some Kw_test
|
||||
| "true" -> Some Kw_true
|
||||
| "false" -> Some Kw_false
|
||||
@@ -119,7 +119,7 @@ let show_kind = function
|
||||
| Kw_else -> "else"
|
||||
| Kw_match -> "match"
|
||||
| Kw_scope -> "scope"
|
||||
| Kw_panic -> "panic"
|
||||
| Kw_crash -> "crash"
|
||||
| Kw_test -> "test"
|
||||
| Kw_true -> "true"
|
||||
| Kw_false -> "false"
|
||||
@@ -184,8 +184,8 @@ let next_kind = function
|
||||
| Kw_if -> Some Kw_else
|
||||
| Kw_else -> Some Kw_match
|
||||
| Kw_match -> Some Kw_scope
|
||||
| Kw_scope -> Some Kw_panic
|
||||
| Kw_panic -> Some Kw_test
|
||||
| Kw_scope -> Some Kw_crash
|
||||
| Kw_crash -> Some Kw_test
|
||||
| Kw_test -> Some Kw_true
|
||||
| Kw_true -> Some Kw_false
|
||||
| Kw_false -> Some LParen
|
||||
|
||||
+3
-3
@@ -164,11 +164,11 @@ let builtin_ctor = function
|
||||
|
||||
let rec infer env (e : expr) : T.t =
|
||||
match e with
|
||||
(* panic은 돌아오지 않는다. 타입은 Never이고 어떤 자리에도 놓인다 *)
|
||||
| E_panic { msg; pos } ->
|
||||
(* crash는 돌아오지 않는다. 타입은 Never이고 어떤 자리에도 놓인다 *)
|
||||
| E_crash { msg; pos } ->
|
||||
let t = infer env msg in
|
||||
if not (T.unify t T.TString) then
|
||||
mismatch env pos T.TString t "panic의 메시지";
|
||||
mismatch env pos T.TString t "crash의 메시지";
|
||||
T.TNever
|
||||
| E_lit (L_int _, _) -> T.TInt
|
||||
| E_lit (L_str _, _) -> T.TString
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
|
||||
type t =
|
||||
| TUnknown
|
||||
(* 값을 내지 않는 타입. panic의 타입이고 어떤 자리에도 놓일 수 있다.
|
||||
(* 값을 내지 않는 타입. crash의 타입이고 어떤 자리에도 놓일 수 있다.
|
||||
TUnknown과 다르다 — TUnknown은 "모른다"이고 TNever는 "돌아오지
|
||||
않는다"이다. 둘 다 무엇과도 맞지만 생기는 이유가 다르다. *)
|
||||
| TNever
|
||||
@@ -141,7 +141,7 @@ let unify_eff a b =
|
||||
let rec unify a b =
|
||||
match (resolve a, resolve b) with
|
||||
| TUnknown, _ | _, TUnknown -> true
|
||||
(* Never는 어떤 타입 자리에도 놓인다. panic이 match 팔에 설 수 있는 이유다 *)
|
||||
(* Never는 어떤 타입 자리에도 놓인다. crash가 match 팔에 설 수 있는 이유다 *)
|
||||
| TNever, _ | _, TNever -> true
|
||||
| TMeta r, TMeta r' when r == r' -> true
|
||||
| TMeta r, t | t, TMeta r ->
|
||||
|
||||
Reference in New Issue
Block a user