Skip to content

Commit 2f57d64

Browse files
committed
feat(echo): integrate echo + product types into the OCaml typechecker
Mirrors the Lean spec (proofs/Tangle.lean) into the OCaml checker so echo types are a feature of the actual typechecker, not only the metatheory. - typecheck.ml: `ty` gains `TProd of ty*ty` and `TEcho of ty*ty`; `pp_ty` is now `let rec` and prints them; `infer_expr` gains the eight typing rules [T-Echo-Close]/[T-Lower]/[T-Residue]/[T-Pair]/[T-Fst]/[T-Snd]/[T-Echo-Add]/ [T-Echo-Eq], matching the HasType rules. - ast.ml: `expr` gains EchoClose/Lower/Residue/Pair/Fst/Snd/EchoAdd/EchoEq. - pretty.ml: pp_expr prints the new forms (kept exhaustive). - eval.ml: eval_expr gets an explicit "not yet implemented" arm for the echo forms (runtime evaluation is a scoped follow-on; the typechecker is the deliverable). Stays exhaustive. Scope: the typechecker. Surface parser syntax + runtime eval are follow-ons. NOTE: no OCaml toolchain or OCaml CI exists in this environment, so this was NOT compiled here — it is a careful by-hand integration (exhaustiveness audited via the Ast-only `Twist` probe: pretty/eval/typecheck are the only exhaustive Ast.expr matchers; compositional's of_ast_expr has a catch-all; repl matches no expr). Verify with `dune build` in compiler/. https://claude.ai/code/session_01PgHpCFzwYB7Qy9L6kmR8CE
1 parent 9b3a32d commit 2f57d64

4 files changed

Lines changed: 132 additions & 1 deletion

File tree

compiler/lib/ast.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ and expr =
8080
| Cup of expr * expr
8181
| Twist of expr
8282

83+
(* ---- Echo types (structured loss) — mirror the Lean spec in
84+
* proofs/Tangle.lean (Ty.echo / Ty.prod and the echo operations).
85+
* Typed by typecheck.ml; surface parser syntax is a follow-on. ---- *)
86+
| EchoClose of expr (* echo-preserving closure (residue-retaining close) *)
87+
| Lower of expr (* project an echo to its result *)
88+
| Residue of expr (* project an echo to its residue (recover witness) *)
89+
| Pair of expr * expr (* product introduction *)
90+
| Fst of expr (* first projection *)
91+
| Snd of expr (* second projection *)
92+
| EchoAdd of expr * expr (* echo-preserving addition (residue = summand pair) *)
93+
| EchoEq of expr * expr (* echo-preserving equality (residue = operand pair) *)
94+
8395
(* ---- Literals ---- *)
8496
| BraidLit of generator list
8597
| Identity

compiler/lib/eval.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,14 @@ let rec eval_expr (env : env) (e : expr) : value =
429429
in
430430
try_arms arms
431431

432+
(* ---- Echo types (structured loss) ----
433+
* These are typed by typecheck.ml (mirroring proofs/Tangle.lean). Runtime
434+
* evaluation needs echo/product value forms and is a deliberate follow-on;
435+
* the typechecker is the scoped deliverable. *)
436+
| EchoClose _ | Lower _ | Residue _ | Pair _ | Fst _ | Snd _ | EchoAdd _ | EchoEq _ ->
437+
eval_error "echo-type evaluation is not yet implemented (typecheck-only); \
438+
see proofs/Tangle.lean for the intended small-step semantics"
439+
432440
(** Evaluate a binary operation on two values. *)
433441
and eval_binop (op : binop) (v1 : value) (v2 : value) : value =
434442
match op with

compiler/lib/pretty.ml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,52 @@ let rec pp_expr ctx = function
171171
pp_expr ctx e;
172172
emit ctx ")"
173173

174+
| EchoClose e ->
175+
emit ctx "echoClose(";
176+
pp_expr ctx e;
177+
emit ctx ")"
178+
179+
| Lower e ->
180+
emit ctx "lower(";
181+
pp_expr ctx e;
182+
emit ctx ")"
183+
184+
| Residue e ->
185+
emit ctx "residue(";
186+
pp_expr ctx e;
187+
emit ctx ")"
188+
189+
| Pair (e1, e2) ->
190+
emit ctx "pair(";
191+
pp_expr ctx e1;
192+
emit ctx ", ";
193+
pp_expr ctx e2;
194+
emit ctx ")"
195+
196+
| Fst e ->
197+
emit ctx "fst(";
198+
pp_expr ctx e;
199+
emit ctx ")"
200+
201+
| Snd e ->
202+
emit ctx "snd(";
203+
pp_expr ctx e;
204+
emit ctx ")"
205+
206+
| EchoAdd (e1, e2) ->
207+
emit ctx "echoAdd(";
208+
pp_expr ctx e1;
209+
emit ctx ", ";
210+
pp_expr ctx e2;
211+
emit ctx ")"
212+
213+
| EchoEq (e1, e2) ->
214+
emit ctx "echoEq(";
215+
pp_expr ctx e1;
216+
emit ctx ", ";
217+
pp_expr ctx e2;
218+
emit ctx ")"
219+
174220
| BraidLit gens ->
175221
emit ctx "braid[";
176222
List.iteri (fun i g ->

compiler/lib/typecheck.ml

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ type ty =
4141
| TNum (** Num — integers and floats *)
4242
| TBool (** Bool — booleans *)
4343
| TStr (** Str — strings *)
44+
| TProd of ty * ty (** ρ × σ — product / residue carrier for lossy ops *)
45+
| TEcho of ty * ty (** Echo[ρ, τ] — structured loss: residue ρ, result τ.
46+
Mirrors Ty.echo in proofs/Tangle.lean. *)
4447

4548
(** Function signature: (param_types) -> return_type. *)
4649
type fun_sig = {
@@ -89,12 +92,14 @@ let pp_boundary (b : boundary) : string =
8992
"[" ^ String.concat ", " (List.map pp_strand_type b) ^ "]"
9093

9194
(** Pretty-print a type. *)
92-
let pp_ty = function
95+
let rec pp_ty = function
9396
| TWord n -> Printf.sprintf "Word[%d]" n
9497
| TTangle (a, b) -> Printf.sprintf "Tangle[%s, %s]" (pp_boundary a) (pp_boundary b)
9598
| TNum -> "Num"
9699
| TBool -> "Bool"
97100
| TStr -> "Str"
101+
| TProd (a, b) -> Printf.sprintf "(%s * %s)" (pp_ty a) (pp_ty b)
102+
| TEcho (r, t) -> Printf.sprintf "Echo[%s, %s]" (pp_ty r) (pp_ty t)
98103

99104
(* ================================================================== *)
100105
(* Environment operations *)
@@ -373,6 +378,66 @@ let rec infer_expr (gamma : env) (sigma : strand_ctx) (e : expr) : ty =
373378
) arm_types;
374379
result_ty
375380

381+
(* ---- Echo types (structured loss) ----
382+
* Mirror the HasType rules in proofs/Tangle.lean:
383+
* [T-Echo-Close] echoClose e : Echo[Word[n], Word[0]] when e : Word[n]
384+
* [T-Lower] lower e : τ when e : Echo[ρ, τ]
385+
* [T-Residue] residue e : ρ when e : Echo[ρ, τ]
386+
* [T-Pair]/[T-Fst]/[T-Snd] product intro + projections
387+
* [T-Echo-Add] echoAdd a b : Echo[Num × Num, Num]
388+
* [T-Echo-Eq] echoEq a b : Echo[ρ × ρ, Bool] for ρ ∈ {Num, Str, Word[n]}
389+
*)
390+
| EchoClose e1 ->
391+
begin match infer_expr gamma sigma e1 with
392+
| TWord n -> TEcho (TWord n, TWord 0)
393+
| t -> type_error "echoClose requires Word[n], got %s" (pp_ty t)
394+
end
395+
396+
| Lower e1 ->
397+
begin match infer_expr gamma sigma e1 with
398+
| TEcho (_, t) -> t
399+
| t -> type_error "lower requires Echo[_, _], got %s" (pp_ty t)
400+
end
401+
402+
| Residue e1 ->
403+
begin match infer_expr gamma sigma e1 with
404+
| TEcho (r, _) -> r
405+
| t -> type_error "residue requires Echo[_, _], got %s" (pp_ty t)
406+
end
407+
408+
| Pair (e1, e2) ->
409+
let t1 = infer_expr gamma sigma e1 in
410+
let t2 = infer_expr gamma sigma e2 in
411+
TProd (t1, t2)
412+
413+
| Fst e1 ->
414+
begin match infer_expr gamma sigma e1 with
415+
| TProd (a, _) -> a
416+
| t -> type_error "fst requires a product, got %s" (pp_ty t)
417+
end
418+
419+
| Snd e1 ->
420+
begin match infer_expr gamma sigma e1 with
421+
| TProd (_, b) -> b
422+
| t -> type_error "snd requires a product, got %s" (pp_ty t)
423+
end
424+
425+
| EchoAdd (e1, e2) ->
426+
begin match infer_expr gamma sigma e1, infer_expr gamma sigma e2 with
427+
| TNum, TNum -> TEcho (TProd (TNum, TNum), TNum)
428+
| t1, t2 -> type_error "echoAdd requires Num, Num, got %s, %s" (pp_ty t1) (pp_ty t2)
429+
end
430+
431+
| EchoEq (e1, e2) ->
432+
begin match infer_expr gamma sigma e1, infer_expr gamma sigma e2 with
433+
| TNum, TNum -> TEcho (TProd (TNum, TNum), TBool)
434+
| TStr, TStr -> TEcho (TProd (TStr, TStr), TBool)
435+
| TWord n, TWord m when n = m -> TEcho (TProd (TWord n, TWord n), TBool)
436+
| t1, t2 ->
437+
type_error "echoEq requires matching Num/Str/Word[n] operands, got %s, %s"
438+
(pp_ty t1) (pp_ty t2)
439+
end
440+
376441
(** Infer the type of a binary operation given operand types.
377442
* Implements rules from sections 3.4, 3.5, 3.6.
378443
*)

0 commit comments

Comments
 (0)