@@ -57,6 +57,12 @@ type level_info = (* Stores information for computing the
5757
5858let exprlevel : level_info pfuncs =
5959 Property. make " Expr.Levels.exprlevel"
60+ type elcache =
61+ | ELCache_full of hyp Deque .dq * expr_ * level_info
62+ | ELCache_empty
63+ let exprlevel_cache : elcache ref pfuncs =
64+ Property. make " Expr.Levels.exprlevel_cache"
65+
6066let assert_is_level (level : int ) =
6167 assert ((level > = 0 ) && (level < = 3 ))
6268 (* The value 4 signifies that the notion of level is undefined for
@@ -124,6 +130,23 @@ let kind_to_level (kind: kind): int =
124130 | Temporal -> 3
125131 | Unknown -> assert false
126132
133+ let has_cached_level cx e =
134+ match Property. get e exprlevel_cache with
135+ | exception Not_found -> false
136+ | {contents = ELCache_full (cx2, ecore, l)}
137+ when ecore == e.core && Deque. equal (== ) cx2 cx -> true
138+ | _ -> false
139+
140+ let get_cached_level e =
141+ match Property. get e exprlevel_cache with
142+ | {contents = ELCache_full (_ , _ , l )} -> l
143+ | _ -> assert false
144+ | exception Not_found -> assert false
145+
146+ let set_cached_level e cx l =
147+ match Property. get e exprlevel_cache with
148+ | r -> r := ELCache_full (cx, e.core, l)
149+ | exception Not_found -> ()
127150
128151(*
129152The level property is stored in the syntax tree nodes.
@@ -142,8 +165,15 @@ class virtual ['s] level_computation = object (self : 'self)
142165 method expr ((_, cx) as scx) e =
143166 if (has_level e) then
144167 e
168+ else if has_cached_level cx e then
169+ assign e exprlevel (get_cached_level e)
145170 else
146171 begin
172+ let assign e tag l =
173+ assert (tag == exprlevel);
174+ set_cached_level e cx l;
175+ assign e tag l
176+ in
147177 let max_args_level scx args = (
148178 let es_ = List. map (self#expr scx) args in
149179 let es_levels = List. map get_level es_ in
@@ -402,7 +432,7 @@ class virtual ['s] level_computation = object (self : 'self)
402432 assign e exprlevel level_info
403433 | Bang (e , sels ) -> assert false (* subexpression references are
404434 expanded before expanding `ENABLED` and `\cdot`. *)
405- | Lambda (vs , e ) ->
435+ | Lambda (vs , e2 ) ->
406436 (* Note: 2nd-order operators (signified via `shp` below) are
407437 handled by the declarations in `e_scx` below and the call to
408438 the method `self#hyp` in the pattern case `Apply (op, es)` below.
@@ -415,7 +445,7 @@ class virtual ['s] level_computation = object (self : 'self)
415445 @@ v)
416446 vs) in
417447 (* expression `e` *)
418- let e_ = self#expr e_scx e in
448+ let e_ = self#expr e_scx e2 in
419449 let e_level = get_level e_ in
420450 (*
421451 if e_level > 2 then
@@ -962,7 +992,7 @@ class virtual ['s] level_computation = object (self : 'self)
962992 *)
963993
964994 method hyp scx h =
965- let level_info = begin match h.core with
995+ let level_info h = begin match h.core with
966996 (* declared variable *)
967997 | Flex _ -> make_level_info 1
968998 (* declared operator of any arity *)
@@ -1003,18 +1033,14 @@ class virtual ['s] level_computation = object (self : 'self)
10031033 assert false (* not implemented *)
10041034 (* defined operator of any arity *)
10051035 | Defn (df , _ , _ , _ ) ->
1006- let df_ = self#defn scx df in
1007- get_level_info df_
1036+ get_level_info df
10081037 | Fact (e , _ , _ ) ->
1009- let e_ = self#expr scx e in
1010- begin
1011- if (has_level e_) then
1012- get_level_info e_
1038+ if (has_level e) then
1039+ get_level_info e
10131040 else
10141041 (* For example, the notion of expression level is
10151042 undefined for theorems. *)
10161043 make_undefined_level_info
1017- end
10181044 end in
10191045 (* Hidden definitions need to be visited to
10201046 have level information available for computing the
@@ -1041,11 +1067,12 @@ class virtual ['s] level_computation = object (self : 'self)
10411067 let h = Fact (self#expr scx e, vis, tm) @@ h in
10421068 (adj scx h, h)
10431069 in
1044- let e_ = assign e_ exprlevel level_info in
1070+ let e_ = assign e_ exprlevel ( level_info e_) in
10451071 (scx_, e_)
10461072
10471073end
10481074
1075+ let newcache e = Property. assign e exprlevel_cache (ref ELCache_empty )
10491076
10501077let compute_level cx expr =
10511078 let visitor = object
0 commit comments