mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 03:05:31 -05:00
feat(term): add replace
This commit is contained in:
parent
1b0d47a01d
commit
0c658e3ee4
2 changed files with 42 additions and 21 deletions
|
|
@ -478,13 +478,14 @@ module Make_ = struct
|
||||||
let app store f a = make_ store (E_app (f, a))
|
let app store f a = make_ store (E_app (f, a))
|
||||||
let app_l store f l = List.fold_left (app store) f l
|
let app_l store f l = List.fold_left (app store) f l
|
||||||
|
|
||||||
|
type cache = t T_int_tbl.t
|
||||||
|
|
||||||
|
let create_cache : int -> cache = T_int_tbl.create
|
||||||
|
|
||||||
(* general substitution, compatible with DB indices. We use this
|
(* general substitution, compatible with DB indices. We use this
|
||||||
also to abstract on a free variable, because it subsumes it and
|
also to abstract on a free variable, because it subsumes it and
|
||||||
it's better to minimize the number of DB indices manipulations *)
|
it's better to minimize the number of DB indices manipulations *)
|
||||||
let subst_ ~make ~recursive e0 (subst : subst) : t =
|
let replace_ ?(cache = create_cache 8) ~make ~recursive e0 ~f : t =
|
||||||
(* cache for types and some terms *)
|
|
||||||
let cache_ = T_int_tbl.create 16 in
|
|
||||||
|
|
||||||
let rec loop k e =
|
let rec loop k e =
|
||||||
if is_type e then
|
if is_type e then
|
||||||
e
|
e
|
||||||
|
|
@ -492,27 +493,15 @@ module Make_ = struct
|
||||||
(* no free variables, cannot change *)
|
(* no free variables, cannot change *)
|
||||||
e
|
e
|
||||||
else (
|
else (
|
||||||
try T_int_tbl.find cache_ (e, k)
|
try T_int_tbl.find cache (e, k)
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
let r = loop_uncached_ k e in
|
let r = loop_uncached_ k e in
|
||||||
T_int_tbl.add cache_ (e, k) r;
|
T_int_tbl.add cache (e, k) r;
|
||||||
r
|
r
|
||||||
)
|
)
|
||||||
and loop_uncached_ k (e : t) : t =
|
and loop_uncached_ k (e : t) : t =
|
||||||
match view e with
|
match f ~recurse:(loop k) e with
|
||||||
| E_var v ->
|
| None ->
|
||||||
(* first, subst in type *)
|
|
||||||
let v = { v with v_ty = loop k v.v_ty } in
|
|
||||||
(match Var_.Map.find v subst.m with
|
|
||||||
| u ->
|
|
||||||
let u = db_shift_ ~make u k in
|
|
||||||
if recursive then
|
|
||||||
loop 0 u
|
|
||||||
else
|
|
||||||
u
|
|
||||||
| exception Not_found -> make (E_var v))
|
|
||||||
| E_const _ -> e
|
|
||||||
| _ ->
|
|
||||||
map_shallow_ e ~make ~f:(fun inb u ->
|
map_shallow_ e ~make ~f:(fun inb u ->
|
||||||
loop
|
loop
|
||||||
(if inb then
|
(if inb then
|
||||||
|
|
@ -520,12 +509,26 @@ module Make_ = struct
|
||||||
else
|
else
|
||||||
k)
|
k)
|
||||||
u)
|
u)
|
||||||
|
| Some u ->
|
||||||
|
let u = db_shift_ ~make u k in
|
||||||
|
if recursive then
|
||||||
|
loop 0 u
|
||||||
|
else
|
||||||
|
u
|
||||||
in
|
in
|
||||||
|
loop 0 e0
|
||||||
|
|
||||||
|
let subst_ ~make ~recursive e0 (subst : subst) : t =
|
||||||
if Var_.Map.is_empty subst.m then
|
if Var_.Map.is_empty subst.m then
|
||||||
e0
|
e0
|
||||||
else
|
else
|
||||||
loop 0 e0
|
replace_ ~make ~recursive e0 ~f:(fun ~recurse e ->
|
||||||
|
match view e with
|
||||||
|
| E_var v ->
|
||||||
|
(* first, subst in type *)
|
||||||
|
let v = { v with v_ty = recurse v.v_ty } in
|
||||||
|
Var_.Map.find_opt v subst.m
|
||||||
|
| _ -> None)
|
||||||
|
|
||||||
module DB = struct
|
module DB = struct
|
||||||
let subst_db0 store e ~by : t = db_0_replace_ ~make:(make_ store) e ~by
|
let subst_db0 store e ~by : t = db_0_replace_ ~make:(make_ store) e ~by
|
||||||
|
|
@ -603,6 +606,13 @@ let map_shallow store ~f e : t = map_shallow_ ~make:(make_ store) ~f e
|
||||||
|
|
||||||
(* re-export some internal things *)
|
(* re-export some internal things *)
|
||||||
module Internal_ = struct
|
module Internal_ = struct
|
||||||
|
type nonrec cache = cache
|
||||||
|
|
||||||
|
let create_cache = create_cache
|
||||||
|
|
||||||
|
let replace_ ?cache store ~recursive t ~f =
|
||||||
|
replace_ ?cache ~make:(make_ store) ~recursive t ~f
|
||||||
|
|
||||||
let subst_ store ~recursive t subst =
|
let subst_ store ~recursive t subst =
|
||||||
subst_ ~make:(make_ store) ~recursive t subst
|
subst_ ~make:(make_ store) ~recursive t subst
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,18 @@ end
|
||||||
(**/**)
|
(**/**)
|
||||||
|
|
||||||
module Internal_ : sig
|
module Internal_ : sig
|
||||||
|
type cache
|
||||||
|
|
||||||
|
val create_cache : int -> cache
|
||||||
val subst_ : store -> recursive:bool -> t -> subst -> t
|
val subst_ : store -> recursive:bool -> t -> subst -> t
|
||||||
|
|
||||||
|
val replace_ :
|
||||||
|
?cache:cache ->
|
||||||
|
store ->
|
||||||
|
recursive:bool ->
|
||||||
|
t ->
|
||||||
|
f:(recurse:(t -> t) -> t -> t option) ->
|
||||||
|
t
|
||||||
end
|
end
|
||||||
|
|
||||||
(**/**)
|
(**/**)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue