Skip to content

Commit 4f214ac

Browse files
committed
Fix logical variable shadowing program variables
Currently, when resolving an identifier, EasyCrypt tries to resolve it as a logical variable first, and then as a program variable (in the active memory), even when a memory specifier is given. This commit adds a new memory specifier that changes the resolution order: when using it, we first try to resolve the identifier as a program variable (in the given memory), and then as a logical variable if no program variable matching that name is found. The syntax if `form{!memory}`. The pretty-printer has been updated accordingly.
1 parent 9128669 commit 4f214ac

File tree

4 files changed

+102
-54
lines changed

4 files changed

+102
-54
lines changed

src/ecParser.mly

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,9 @@ pside_:
881881
pside:
882882
| x=brace(pside_) { x }
883883

884+
pside_force:
885+
| brace(b=boption(NOT) m=loc(pside_) { (b, m) }) { $1 }
886+
884887
(* -------------------------------------------------------------------- *)
885888
(* Patterns *)
886889

@@ -1211,7 +1214,7 @@ sform_u(P):
12111214
{ let e1 = List.reduce1 (fun _ -> lmap (fun x -> PFtuple x) e1) (unloc e1) in
12121215
pfset (EcLocation.make $startpos $endpos) ti se e1 e2 }
12131216

1214-
| x=sform_r(P) s=loc(pside)
1217+
| x=sform_r(P) s=pside_force
12151218
{ PFside (x, s) }
12161219

12171220
| op=loc(numop) ti=tvars_app?

src/ecParsetree.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ and pformula_r =
181181
| PFident of pqsymbol * ptyannot option
182182
| PFref of psymbol * pffilter list
183183
| PFmem of psymbol
184-
| PFside of pformula * symbol located
184+
| PFside of pformula * (bool * symbol located)
185185
| PFapp of pformula * pformula list
186186
| PFif of pformula * pformula * pformula
187187
| PFmatch of pformula * (ppattern * pformula) list

src/ecPrinting.ml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ module PPEnv = struct
322322
match EcEnv.Var.lookup_local_opt name ppe.ppe_env with
323323
| Some (id, _) when EcIdent.id_equal id x -> name
324324
| _ -> EcIdent.name x
325+
325326
let tyvar (ppe : t) x =
326327
match Mid.find_opt x ppe.ppe_locals with
327328
| None -> EcIdent.tostring x
@@ -1665,12 +1666,23 @@ and pp_form_core_r (ppe : PPEnv.t) outer fmt f =
16651666
pp_local ppe fmt id
16661667

16671668
| Fpvar (x, i) -> begin
1668-
match EcEnv.Memory.get_active ppe.PPEnv.ppe_env with
1669-
| Some i' when EcMemory.mem_equal i i' ->
1670-
Format.fprintf fmt "%a" (pp_pv ppe) x
1671-
| _ ->
1672-
let ppe = PPEnv.enter_by_memid ppe i in
1673-
Format.fprintf fmt "%a{%a}" (pp_pv ppe) x (pp_mem ppe) i
1669+
let default (force : bool) =
1670+
let ppe = PPEnv.enter_by_memid ppe i in
1671+
Format.fprintf fmt "%a{%s%a}"
1672+
(pp_pv ppe) x (if force then "!" else "") (pp_mem ppe) i in
1673+
1674+
let force =
1675+
match x with
1676+
| PVloc x -> Ssym.mem x ppe.ppe_inuse
1677+
| PVglob _ -> false in
1678+
1679+
if force then default true else
1680+
1681+
match EcEnv.Memory.get_active ppe.PPEnv.ppe_env with
1682+
| Some i' when EcMemory.mem_equal i i' ->
1683+
Format.fprintf fmt "%a" (pp_pv ppe) x
1684+
| _ ->
1685+
default false
16741686
end
16751687

16761688
| Fglob (mp, i) -> begin

src/ecTyping.ml

Lines changed: 79 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ end
338338
let gen_select_op
339339
~(actonly : bool)
340340
~(mode : OpSelect.mode)
341+
~(forcepv : bool)
341342
(opsc : path option)
342343
(tvi : EcUnify.tvi)
343344
(env : EcEnv.env)
@@ -348,15 +349,15 @@ let gen_select_op
348349
: OpSelect.gopsel list
349350
=
350351

351-
let fpv me (pv, ty, ue) =
352+
let fpv me (pv, ty, ue) : OpSelect.gopsel =
352353
(`Pv (me, pv), ty, ue, (pv :> opmatch))
353354

354-
and fop (op, ty, ue, bd) =
355+
and fop (op, ty, ue, bd) : OpSelect.gopsel=
355356
match bd with
356357
| None -> (`Op op, ty, ue, (`Op op :> opmatch))
357358
| Some bd -> (`Nt bd, ty, ue, (`Op op :> opmatch))
358359

359-
and flc (lc, ty, ue) =
360+
and flc (lc, ty, ue) : OpSelect.gopsel =
360361
(`Lc lc, ty, ue, (`Lc lc :> opmatch)) in
361362

362363
let ue_filter =
@@ -378,39 +379,52 @@ let gen_select_op
378379

379380
in
380381

381-
match (if tvi = None then select_local env name else None) with
382-
| Some (id, ty) ->
383-
[ flc (id, ty, ue) ]
382+
let locals () : OpSelect.gopsel list =
383+
if Option.is_none tvi then
384+
select_local env name
385+
|> Option.map
386+
(fun (id, ty) -> flc (id, ty, ue))
387+
|> Option.to_list
388+
else [] in
389+
390+
let ops () : OpSelect.gopsel list =
391+
let ops = EcUnify.select_op ~filter:ue_filter tvi env name ue psig in
392+
let ops = opsc |> ofold (fun opsc -> List.mbfilter (by_scope opsc)) ops in
393+
let ops = match List.mbfilter by_current ops with [] -> ops | ops -> ops in
394+
let ops = match List.mbfilter by_tc ops with [] -> ops | ops -> ops in
395+
(List.map fop ops)
396+
397+
and pvs () : OpSelect.gopsel list =
398+
let me, pvs =
399+
match EcEnv.Memory.get_active env, actonly with
400+
| None, true -> (None, [])
401+
| me , _ -> ( me, select_pv env me name ue tvi psig)
402+
in List.map (fpv me) pvs
403+
in
384404

385-
| None ->
386-
let ops () =
387-
let ops = EcUnify.select_op ~filter:ue_filter tvi env name ue psig in
388-
let ops = opsc |> ofold (fun opsc -> List.mbfilter (by_scope opsc)) ops in
389-
let ops = match List.mbfilter by_current ops with [] -> ops | ops -> ops in
390-
let ops = match List.mbfilter by_tc ops with [] -> ops | ops -> ops in
391-
(List.map fop ops)
392-
393-
and pvs () =
394-
let me, pvs =
395-
match EcEnv.Memory.get_active env, actonly with
396-
| None, true -> (None, [])
397-
| me , _ -> ( me, select_pv env me name ue tvi psig)
398-
in List.map (fpv me) pvs
399-
in
405+
let select (filters : (unit -> OpSelect.gopsel list) list) : OpSelect.gopsel list =
406+
List.find_map_opt
407+
(fun f -> match f () with [] -> None | x -> Some x)
408+
filters
409+
|> odfl [] in
400410

401-
match mode with
402-
| `Expr `InOp -> ops ()
403-
| `Form -> (match pvs () with [] -> ops () | pvs -> pvs)
404-
| `Expr `InProc -> (match pvs () with [] -> ops () | pvs -> pvs)
411+
match mode with
412+
| `Expr `InOp -> select [locals; ops]
413+
| `Form
414+
| `Expr `InProc ->
415+
if forcepv then
416+
select [pvs; locals; ops]
417+
else
418+
select [locals; pvs; ops]
405419

406420
(* -------------------------------------------------------------------- *)
407421
let select_exp_op env mode opsc name ue tvi psig =
408-
gen_select_op ~actonly:false ~mode:(`Expr mode)
422+
gen_select_op ~actonly:false ~forcepv:false ~mode:(`Expr mode)
409423
opsc tvi env name ue psig
410424

411425
(* -------------------------------------------------------------------- *)
412-
let select_form_op env opsc name ue tvi psig =
413-
gen_select_op ~actonly:true ~mode:`Form
426+
let select_form_op env ~forcepv opsc name ue tvi psig =
427+
gen_select_op ~actonly:true ~mode:`Form ~forcepv
414428
opsc tvi env name ue psig
415429

416430
(* -------------------------------------------------------------------- *)
@@ -1745,23 +1759,36 @@ module PFS : sig
17451759

17461760
val set_memused : pfstate -> unit
17471761
val get_memused : pfstate -> bool
1748-
val new_memused : ('a -> 'b) -> pfstate -> 'a -> bool * 'b
1762+
val isforced : pfstate -> bool
1763+
val new_memused : ('a -> 'b) -> force:bool -> pfstate -> 'a -> bool * 'b
17491764
end = struct
1750-
type pfstate = { mutable pfa_memused : bool; }
1765+
type pfstate1 = {
1766+
pfa_memused : bool;
1767+
pfa_forced : bool;
1768+
}
17511769

1752-
let create () = { pfa_memused = true; }
1770+
type pfstate = pfstate1 ref
17531771

1754-
let set_memused state =
1755-
state.pfa_memused <- true
1772+
let create1 ~(force : bool) : pfstate1 =
1773+
{ pfa_memused = false; pfa_forced = force; }
17561774

1757-
let get_memused state =
1758-
state.pfa_memused
1775+
let create () : pfstate =
1776+
ref (create1 ~force:false)
17591777

1760-
let new_memused f state x =
1761-
let old = state.pfa_memused in
1762-
let aout = (state.pfa_memused <- false; f x) in
1763-
let new_ = state.pfa_memused in
1764-
state.pfa_memused <- old; (new_, aout)
1778+
let set_memused (state : pfstate) =
1779+
state := { !state with pfa_memused = true }
1780+
1781+
let get_memused (state : pfstate) =
1782+
(!state).pfa_memused
1783+
1784+
let isforced (state : pfstate) =
1785+
(!state).pfa_forced
1786+
1787+
let new_memused (f : 'a -> 'b) ~(force : bool) (state : pfstate) (x : 'a) =
1788+
let old = !state in
1789+
let aout = (state := create1 ~force; f x) in
1790+
let new_ = get_memused state in
1791+
state := old; (new_, aout)
17651792
end
17661793

17671794
(* -------------------------------------------------------------------- *)
@@ -3026,7 +3053,10 @@ and trans_form_or_pattern env ?mv ?ps ue pf tt =
30263053

30273054
| PFident ({ pl_desc = name; pl_loc = loc }, tvi) ->
30283055
let tvi = tvi |> omap (transtvi env ue) in
3029-
let ops = select_form_op env opsc name ue tvi [] in
3056+
let ops =
3057+
select_form_op
3058+
~forcepv:(PFS.isforced state)
3059+
env opsc name ue tvi [] in
30303060
begin match ops with
30313061
| [] ->
30323062
tyerror loc env (UnknownVarOrOp (name, []))
@@ -3045,7 +3075,7 @@ and trans_form_or_pattern env ?mv ?ps ue pf tt =
30453075
tyerror loc env (MultipleOpMatch (name, [], matches))
30463076
end
30473077

3048-
| PFside (f, side) -> begin
3078+
| PFside (f, (force, side)) -> begin
30493079
let (sloc, side) = (side.pl_loc, unloc side) in
30503080
let me =
30513081
match EcEnv.Memory.lookup side env with
@@ -3056,7 +3086,7 @@ and trans_form_or_pattern env ?mv ?ps ue pf tt =
30563086
let used, aout =
30573087
PFS.new_memused
30583088
(transf (EcEnv.Memory.set_active me env))
3059-
state f
3089+
~force state f
30603090
in
30613091
if not used then begin
30623092
let ppe = EcPrinting.PPEnv.ofenv env in
@@ -3139,11 +3169,11 @@ and trans_form_or_pattern env ?mv ?ps ue pf tt =
31393169
let _, f1 =
31403170
PFS.new_memused
31413171
(transf (EcEnv.Memory.set_active me1 env))
3142-
state f in
3172+
~force:false state f in
31433173
let _, f2 =
31443174
PFS.new_memused
31453175
(transf (EcEnv.Memory.set_active me2 env))
3146-
state f in
3176+
~force:false state f in
31473177
unify_or_fail env ue f.pl_loc ~expct:f1.f_ty f2.f_ty;
31483178
f_eq f1 f2
31493179

@@ -3156,7 +3186,10 @@ and trans_form_or_pattern env ?mv ?ps ue pf tt =
31563186
let tvi = tvi |> omap (transtvi env ue) in
31573187
let es = List.map (transf env) pes in
31583188
let esig = List.map EcFol.f_ty es in
3159-
let ops = select_form_op env opsc name ue tvi esig in
3189+
let ops =
3190+
select_form_op ~forcepv:(PFS.isforced state)
3191+
env opsc name ue tvi esig in
3192+
31603193
begin match ops with
31613194
| [] ->
31623195
let uidmap = UE.assubst ue in

0 commit comments

Comments
 (0)