mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-11 13:38:43 -05:00
72 lines
2.1 KiB
OCaml
72 lines
2.1 KiB
OCaml
open Sidekick_core_logic
|
|
module Tr = Sidekick_trace
|
|
module T = Term
|
|
|
|
type term_ref = Tr.entry_id
|
|
type state = { sink: Tr.Sink.t; emitted: Tr.Entry_id.t T.Weak_map.t }
|
|
|
|
let emit_term_ (self : state) (t : Term.t) =
|
|
let module V = Ser_value in
|
|
let rec loop t =
|
|
match T.Weak_map.find_opt self.emitted t with
|
|
| Some id -> id
|
|
| None ->
|
|
let loop' t = V.int (loop t :> int) in
|
|
let tag, v =
|
|
match T.view t with
|
|
| T.E_var v -> "TV", V.(list [ string (Var.name v); loop' v.v_ty ])
|
|
| T.E_bound_var v -> "Tv", V.(list [ int (Bvar.idx v); loop' v.bv_ty ])
|
|
| T.E_app (f, a) -> "T@", V.(list [ loop' f; loop' a ])
|
|
| T.E_type i -> "Ty", V.int i
|
|
| T.E_const ({ Const.c_ty; _ } as const) ->
|
|
let tag, view = Const.ser ~ser_t:loop' const in
|
|
( "Tc",
|
|
let fields =
|
|
(if V.is_null view then
|
|
[]
|
|
else
|
|
[ "v", view ])
|
|
@ [ "ty", loop' c_ty; "tag", V.string tag ]
|
|
in
|
|
V.dict_of_list fields )
|
|
| T.E_app_fold { f; args; acc0 } ->
|
|
( "Tf@",
|
|
V.(
|
|
dict_of_list
|
|
[
|
|
"f", loop' f;
|
|
"l", list (List.map loop' args);
|
|
"a0", loop' acc0;
|
|
]) )
|
|
| T.E_lam (name, ty, bod) ->
|
|
"Tl", V.(list [ string name; loop' ty; loop' bod ])
|
|
| T.E_pi (name, ty, bod) ->
|
|
"Tp", V.(list [ string name; loop' ty; loop' bod ])
|
|
in
|
|
|
|
let id = Tr.Sink.emit self.sink ~tag v in
|
|
T.Weak_map.add self.emitted t id;
|
|
id
|
|
in
|
|
loop t
|
|
|
|
class type t =
|
|
object
|
|
method emit_term : Term.t -> term_ref
|
|
end
|
|
|
|
class dummy : t =
|
|
object
|
|
method emit_term _ = Tr.Entry_id.dummy
|
|
end
|
|
|
|
(* tracer *)
|
|
class concrete ~sink : t =
|
|
object
|
|
val state = { sink; emitted = T.Weak_map.create 16 }
|
|
method emit_term (t : Term.t) : term_ref = emit_term_ state t
|
|
end
|
|
|
|
let create ~sink () : t = new concrete ~sink
|
|
let emit (self : #t) (t : T.t) : term_ref = self#emit_term t
|
|
let emit' self t : unit = ignore (emit self t : term_ref)
|