Skip to content

Commit 313ab25

Browse files
committed
Make old apply to the whole subexpression.
1 parent d3e4b99 commit 313ab25

File tree

2 files changed

+26
-20
lines changed

2 files changed

+26
-20
lines changed

src/checker/Pulse.Checker.ImpureSpec.fst

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,15 @@ let symb_eval_stateful_app (g: env) (ctxt: slprop) (t: term) : T.Tac R.term =
9292
let rwr = RU.deep_compress rwr in // TODO: maybe this fails on uvars...
9393
rwr
9494

95-
let rec symb_eval_subterms (g:env) (ctxt: ctxt) (t:R.term) : T.Tac (bool & R.term) =
95+
noeq type ctxt' = {
96+
ctxt: ctxt;
97+
in_old: in_old:bool { in_old ==> Some? ctxt.ctxt_old };
98+
}
99+
100+
let cur_ctxt c =
101+
if c.in_old then Some?.v c.ctxt.ctxt_old else c.ctxt.ctxt_now
102+
103+
let rec symb_eval_subterms (g:env) (ctxt: ctxt') (t:R.term) : T.Tac (bool & R.term) =
96104
match R.inspect_ln t with
97105
| R.Tv_Abs b body ->
98106
debug g (fun _ -> [text "symb eval subterms abs 0"; pp t]);
@@ -145,7 +153,7 @@ let rec symb_eval_subterms (g:env) (ctxt: ctxt) (t:R.term) : T.Tac (bool & R.ter
145153
match is_stateful_application g t with
146154
| Some _ ->
147155
let t = RU.mk_app_flat head args (T.range_of_term t) in
148-
let t' = symb_eval_stateful_app g ctxt.ctxt_now t in
156+
let t' = symb_eval_stateful_app g (cur_ctxt ctxt) t in
149157
true, t'
150158
| None ->
151159
if changed then
@@ -159,28 +167,23 @@ let rec symb_eval_subterms (g:env) (ctxt: ctxt) (t:R.term) : T.Tac (bool & R.ter
159167
| R.Tv_FVar fv, [t, _] ->
160168
if R.inspect_fv fv = old_lid then
161169
// let t = RU.mk_app_flat head args (T.range_of_term t) in
162-
match is_stateful_application g t, ctxt.ctxt_old with
163-
| _, None ->
170+
if not (Some? ctxt.ctxt.ctxt_old) then
164171
T.fail_doc_at [
165172
text "'old' can only be used in postconditions";
166173
] r
167-
| None, _ ->
168-
T.fail_doc_at [
169-
text "'old' needs to be applied to a stateful computation, not:";
170-
pp t;
171-
] r
172-
| Some _, Some ctxt_old ->
173-
let head, args = T.collect_app_ln t in
174-
let g, changed, args = symb_eval_subterms_args g ctxt args in
175-
let t = RU.mk_app_flat head args (T.range_of_term t) in
176-
let t' = symb_eval_stateful_app g ctxt_old t in
177-
true, t'
174+
else (
175+
(if ctxt.in_old then
176+
warn_doc g r [
177+
text "'old' only needs to be specified once";
178+
]);
179+
symb_eval_subterms g { ctxt with in_old = true } t
180+
)
178181
else
179182
fallback ()
180183
| _ ->
181184
fallback ()
182185

183-
and symb_eval_subterms_args (g:env) (ctxt: ctxt) (args:list T.argv)
186+
and symb_eval_subterms_args (g:env) (ctxt: ctxt') (args:list T.argv)
184187
: T.Tac (env & bool & list T.argv)
185188
= T.fold_right
186189
(fun (arg, q) (g, changed, args) ->
@@ -219,7 +222,8 @@ let run_elim (g: env) (ctxt: slprop) : T.Tac (env & list nvar & slprop) =
219222
g', xs, list_as_slprop ctxt
220223

221224
(* Adds add to the ctxt in a way that the prover will prefer it when ambiguous. *)
222-
let push_ctxt ctxt add = { ctxt with ctxt_now = tm_star add ctxt.ctxt_now }
225+
let push_ctxt (ctxt: ctxt') add =
226+
{ ctxt with ctxt = { ctxt.ctxt with ctxt_now = tm_star add ctxt.ctxt.ctxt_now } }
223227

224228
let un_uinst (t: term) : R.term_view =
225229
match R.inspect_ln t with
@@ -282,7 +286,7 @@ let tc_term_phase1_with_type_twice g t ty =
282286
let or_emp (t: option slprop) : slprop =
283287
match t with Some t -> t | None -> tm_emp
284288

285-
let rec purify_spec_core (g: env) (ctxt: ctxt) (ts: list slprop) : T.Tac (option slprop) =
289+
let rec purify_spec_core (g: env) (ctxt: ctxt') (ts: list slprop) : T.Tac (option slprop) =
286290
match ts with
287291
| [] -> None
288292
| t::ts ->
@@ -336,7 +340,7 @@ let rec purify_spec_core (g: env) (ctxt: ctxt) (ts: list slprop) : T.Tac (option
336340
let t = T.norm_term_env (elab_env g) steps t in
337341
extrude g ctxt [t] ts
338342

339-
and extrude (g: env) (ctxt: ctxt) (todo: list slprop) (ts: list slprop) : T.Tac (option slprop) =
343+
and extrude (g: env) (ctxt: ctxt') (todo: list slprop) (ts: list slprop) : T.Tac (option slprop) =
340344
match todo with
341345
| [] -> purify_spec_core g ctxt ts
342346
| t::todo ->
@@ -386,12 +390,14 @@ let run_elim_ctxt (g: env) (ctxt: ctxt) =
386390

387391
let purify_term (g: env) (ctxt: ctxt) (t: term) : T.Tac term =
388392
let g', xs, ctxt = run_elim_ctxt g ctxt in
393+
let ctxt = { ctxt; in_old = false } in
389394
let _, t = symb_eval_subterms g ctxt t in
390395
t
391396

392397
let purify_spec (g: env) (ctxt: ctxt) (t0: slprop) : T.Tac slprop =
393398
let t = t0 in
394399
let g', xs, ctxt = run_elim_ctxt g ctxt in
400+
let ctxt = { ctxt; in_old = false } in
395401
let t = purify_spec_core g' ctxt [t] |> or_emp in
396402
// TODO: check that xs is not free in t
397403
// If we call phase1 TC only once, then the universe instantiation in

test/ImpureSpec.fst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn test10 (x: bool)
102102
fn test11 (x:ref (ref int))
103103
preserves nested_live x
104104
returns w:_
105-
ensures pure (w == old(!(old(!x))))
105+
ensures pure (w == old(! !x))
106106
{
107107
!(!x);
108108
}

0 commit comments

Comments
 (0)