@@ -18,6 +18,7 @@ open EcLowGoal
1818
1919module Sid = EcIdent. Sid
2020module Mid = EcIdent. Mid
21+ module Mint = EcMaps. Mint
2122module Sp = EcPath. Sp
2223
2324module ER = EcReduction
@@ -249,6 +250,8 @@ module LowRewrite = struct
249250 | LRW_IdRewriting
250251 | LRW_RPatternNoMatch
251252 | LRW_RPatternNoRuleMatch
253+ | LRW_RPatternNotLinear
254+ | LRW_RPatternNoVariable
252255
253256 exception RewriteError of error
254257
@@ -326,48 +329,171 @@ module LowRewrite = struct
326329
327330 let find_rewrite_patterns = find_rewrite_patterns ~inpred: false
328331
329- type rwinfos = rwside * EcFol . form option * EcMatching .occ option
332+ type rwinfos = rwside * ( form * ( EcIdent .t * ty ) option ) option * EcMatching .occ option
330333
331- let t_rewrite_r ?(mode = `Full ) ?target ((s , prw , o ) : rwinfos ) pt tc =
334+ let first_occurrence (p : EcMatching.ptnpos ) =
335+ EcMatching.FPosition. filter (`Inclusive , EcMaps.Sint. singleton 1 ) p
336+
337+ let ptnpos_as_map (p : EcMatching.ptnpos ) =
338+ (p :> [`Select of int | `Sub of EcMatching.ptnpos] Mint.t )
339+
340+ let path_of_occurrence (p : EcMatching.ptnpos ) =
341+ let rec aux acc (p : EcMatching.ptnpos ) =
342+ let p = ptnpos_as_map p in
343+ assert (Mint. cardinal p = 1 );
344+
345+ let i, p = Mint. choose p in
346+
347+ match p with
348+ | `Select _ -> List. rev (i :: acc)
349+ | `Sub p -> aux (i :: acc) p
350+ in
351+
352+ let p = first_occurrence p in
353+ let p = ptnpos_as_map p in
354+
355+ assert (Mint. cardinal p = 1 );
356+
357+ let i, p = Mint. choose p in
358+ assert (i = 0 );
359+
360+ match p with
361+ | `Select _ -> []
362+ | `Sub p -> aux [] p
363+
364+ let first_selected_subform (p : EcMatching.ptnpos ) (f : form ) =
365+ let selected = ref None in
366+
367+ let _ =
368+ EcMatching.FPosition. map p
369+ (fun fp ->
370+ if Option. is_none ! selected then selected := Some fp;
371+ fp)
372+ f
373+ in
374+
375+ oget ! selected
376+
377+ let t_rewrite_r
378+ ?(mode : [`Full | `Light] = `Full )
379+ ?(target : EcIdent.t option )
380+ ((s , prw , o ) : rwinfos )
381+ (pt : pt_ev )
382+ (tc : tcenv1 )
383+ =
332384 let hyps, tgfp = FApi. tc1_flat ?target tc in
333385
334386 let modes =
335387 match mode with
336- | `Full -> [{ k_keyed = true ; k_conv = false };
337- { k_keyed = true ; k_conv = true };]
338- | `Light -> [{ k_keyed = true ; k_conv = false }] in
388+ | `Full -> [{ k_keyed = true ; k_conv = false ; k_delta = true };
389+ { k_keyed = true ; k_conv = true ; k_delta = true };]
390+ | `Light -> [{ k_keyed = true ; k_conv = false ; k_delta = true }] in
339391
340392 let for1 (pt , mode , (f1 , f2 )) =
341393 let fp, tp = match s with `LtoR -> f1, f2 | `RtoL -> f2, f1 in
342- let subf, occmode =
394+ let subf, occmode, cpos =
343395 match prw with
344396 | None -> begin
345397 try
346- PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
398+ let subf, occmode =
399+ PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
400+ in
401+ (subf, occmode, None )
347402 with
348403 | PT. FindOccFailure `MatchFailure ->
349404 raise (RewriteError LRW_NothingToRewrite )
350405 | PT. FindOccFailure `IncompleteMatch ->
351406 raise (RewriteError LRW_CannotInfer )
352407 end
353408
354- | Some prw -> begin
355- let prw, _ =
356- try
357- PT. pf_find_occurence_lazy
358- pt.PT. ptev_env ~full: false ~modes ~ptn: prw tgfp
359- with PT. FindOccFailure `MatchFailure ->
360- raise (RewriteError LRW_RPatternNoMatch ) in
409+ | Some (prw , subl ) -> begin
410+ let subcpos =
411+ match subl with
412+ | None -> None
361413
362- try
363- PT. pf_find_occurence_lazy
364- pt.PT. ptev_env ~rooted: true ~modes ~ptn: fp prw
365- with
366- | PT. FindOccFailure `MatchFailure ->
367- raise (RewriteError LRW_RPatternNoRuleMatch )
368- | PT. FindOccFailure `IncompleteMatch ->
369- raise (RewriteError LRW_CannotInfer )
370- end in
414+ | Some (x , xty ) ->
415+ let fx = f_local x xty in
416+ let subcpos =
417+ FPosition. select_form
418+ ~xconv: `Eq ~keyed: true hyps None fx prw
419+ in
420+
421+ if FPosition. is_empty subcpos then
422+ raise (RewriteError LRW_RPatternNoVariable );
423+
424+ if FPosition. occurences subcpos <> 1 then
425+ raise (RewriteError LRW_RPatternNotLinear );
426+
427+ let subcpos =
428+ match o with
429+ | None -> subcpos
430+ | Some o ->
431+ if not (FPosition. is_occurences_valid (snd o) subcpos) then
432+ raise (RewriteError LRW_InvalidOccurence );
433+ FPosition. filter o subcpos
434+ in
435+
436+ Some subcpos
437+ in
438+
439+ let ctxt_modes =
440+ match subl with
441+ | None -> modes
442+ | Some _ -> [{ k_keyed = true ; k_conv = false ; k_delta = false }]
443+ in
444+
445+ let prw, prwmode =
446+ try
447+ PT. pf_find_occurence_lazy
448+ pt.PT. ptev_env ~full: false ~modes: ctxt_modes ~ptn: prw tgfp
449+ with PT. FindOccFailure `MatchFailure ->
450+ raise (RewriteError LRW_RPatternNoMatch ) in
451+
452+ match subcpos with
453+ | None ->
454+ begin
455+ try
456+ let subf, occmode =
457+ PT. pf_find_occurence_lazy
458+ pt.PT. ptev_env ~rooted: true ~modes: ctxt_modes ~ptn: fp prw
459+ in
460+ (subf, occmode, None )
461+ with
462+ | PT. FindOccFailure `MatchFailure ->
463+ raise (RewriteError LRW_RPatternNoRuleMatch )
464+ | PT. FindOccFailure `IncompleteMatch ->
465+ raise (RewriteError LRW_CannotInfer )
466+ end
467+
468+ | Some subcpos ->
469+ let subf = first_selected_subform subcpos prw in
470+
471+ begin
472+ try
473+ ignore
474+ (PT. pf_find_occurence_lazy
475+ pt.PT. ptev_env ~rooted: true ~modes: ctxt_modes ~ptn: fp subf)
476+ with
477+ | PT. FindOccFailure `MatchFailure ->
478+ raise (RewriteError LRW_RPatternNoRuleMatch )
479+ | PT. FindOccFailure `IncompleteMatch ->
480+ raise (RewriteError LRW_CannotInfer )
481+ end ;
482+
483+ let cpos =
484+ let prwpos =
485+ FPosition. select_form
486+ ~xconv: `AlphaEq ~keyed: prwmode.k_keyed hyps
487+ (Some (`Inclusive , EcMaps.Sint. singleton 1 ))
488+ prw tgfp
489+ in
490+ let root = path_of_occurrence prwpos in
491+ FPosition. reroot root subcpos
492+ in
493+
494+ (subf, { k_keyed = true ; k_conv = false ; k_delta = false }, Some cpos)
495+ end
496+ in
371497
372498 if not occmode.k_keyed then begin
373499 let tp = PT. concretize_form pt.PT. ptev_env tp in
@@ -377,10 +503,15 @@ module LowRewrite = struct
377503
378504 let pt = fst (PT. concretize pt) in
379505 let cpos =
380- try FPosition. select_form
381- ~xconv: `AlphaEq ~keyed: occmode.k_keyed
382- hyps o subf tgfp
383- with InvalidOccurence -> raise (RewriteError (LRW_InvalidOccurence ))
506+ match cpos with
507+ | Some cpos -> cpos
508+ | None ->
509+ try
510+ FPosition. select_form
511+ ~xconv: `AlphaEq ~keyed: occmode.k_keyed
512+ hyps o subf tgfp
513+ with InvalidOccurence ->
514+ raise (RewriteError LRW_InvalidOccurence )
384515 in
385516
386517 EcLowGoal. t_rewrite
@@ -569,7 +700,14 @@ let process_apply_top tc =
569700 | _ -> tc_error !! tc " no top assumption"
570701
571702(* -------------------------------------------------------------------- *)
572- let process_rewrite1_core ?mode ?(close = true ) ?target (s , p , o ) pt tc =
703+ let process_rewrite1_core
704+ ?(mode : [`Full | `Light] option )
705+ ?(close : bool = true )
706+ ?(target : EcIdent.t option )
707+ ((s , p , o ) : rwside * (form * (EcIdent. t * ty ) option ) option * rwocc )
708+ (pt : pt_ev )
709+ (tc : tcenv1 )
710+ =
573711 let o = norm_rwocc o in
574712
575713 try
@@ -596,9 +734,13 @@ let process_rewrite1_core ?mode ?(close = true) ?target (s, p, o) pt tc =
596734 tc_error !! tc " r-pattern does not match the goal"
597735 | LowRewrite. LRW_RPatternNoRuleMatch ->
598736 tc_error !! tc " r-pattern does not match the rewriting rule"
737+ | LowRewrite. LRW_RPatternNotLinear ->
738+ tc_error !! tc " context variable must appear exactly once in the r-pattern"
739+ | LowRewrite. LRW_RPatternNoVariable ->
740+ tc_error !! tc " context variable does not appear in the r-pattern"
599741
600742(* -------------------------------------------------------------------- *)
601- let process_delta ~und_delta ?target (s , o , p ) tc =
743+ let process_delta ~und_delta ?target (( s :rwside ) , o , p ) tc =
602744 let env, hyps, concl = FApi. tc1_eflat tc in
603745 let o = norm_rwocc o in
604746
@@ -768,38 +910,50 @@ let process_rewrite1_r ttenv ?target ri tc =
768910 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
769911 t_simplify_lg ?target ~delta: `IfApplied (ttenv, logic) tc
770912
771- | RWDelta (( s , r , o , px ) , p ) -> begin
772- if Option. is_some px then
913+ | RWDelta (rwopt , p ) -> begin
914+ if Option. is_some rwopt.match_ then
773915 tc_error !! tc " cannot use pattern selection in delta-rewrite rules" ;
774916
775- let do1 tc = process_delta ~und_delta ?target (s, o, p) tc in
917+ let do1 tc =
918+ process_delta ~und_delta ?target (rwopt.side, rwopt.occurrence, p) tc in
776919
777- match r with
920+ match rwopt.repeat with
778921 | None -> do1 tc
779922 | Some (b , n ) -> t_do b n do1 tc
780923 end
781924
782- | RWRw ((( s : rwside ), r , o , p ) , pts ) -> begin
925+ | RWRw (rwopt , pts ) -> begin
783926 let do1 (mode : [`Full | `Light] ) ((subs : rwside ), pt ) tc =
784927 let hyps = FApi. tc1_hyps tc in
785928 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
786929 let hyps = FApi. tc1_hyps ?target tc in
787930
788931 let ptenv, prw =
789- match p with
932+ match rwopt.match_ with
790933 | None ->
791934 PT. ptenv_of_penv hyps !! tc, None
792935
793- | Some p ->
936+ | Some (RWM_Plain p ) ->
794937 let (ps, ue), p = TTC. tc1_process_pattern tc p in
795938 let ev = MEV. of_idents (Mid. keys ps) `Form in
796- (PT. ptenv !! tc hyps (ue, ev), Some p) in
939+ (PT. ptenv !! tc hyps (ue, ev), Some (p, None ))
940+
941+ | Some (RWM_Context (x , p )) ->
942+ let ps = ref Mid. empty in
943+ let ue = EcProofTyping. unienv_of_hyps hyps in
944+ let x = EcIdent. create (unloc x) in
945+ let xty = EcUnify.UniEnv. fresh ue in
946+ let hyps = FApi. tc1_hyps tc in
947+ let hyps = LDecl. add_local x (LD_var (xty, None )) hyps in
948+ let p = EcTyping. trans_pattern (LDecl. toenv hyps) ps ue p in
949+ let ev = MEV. of_idents (x :: Mid. keys ! ps) `Form in
950+ (PT. ptenv !! tc hyps (ue, ev), Some (p, Some (x, xty))) in
797951
798952 let theside =
799- match s , subs with
800- | `LtoR , _ -> (subs :> rwside )
801- | _ , `LtoR -> (s :> rwside )
802- | `RtoL , `RtoL -> (`LtoR :> rwside ) in
953+ match rwopt.side , subs with
954+ | `LtoR , _ -> (subs :> rwside )
955+ | _ , `LtoR -> (rwopt.side :> rwside )
956+ | `RtoL , `RtoL -> (`LtoR :> rwside ) in
803957
804958 let is_baserw p =
805959 EcEnv.BaseRw. is_base p.pl_desc (FApi. tc1_env tc) in
@@ -814,7 +968,7 @@ let process_rewrite1_r ttenv ?target ri tc =
814968
815969 let do1 lemma tc =
816970 let pt = PT. pt_of_uglobal_r (PT. copy ptenv) lemma in
817- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
971+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
818972 in t_ors (List. map do1 ls) tc
819973
820974 | { fp_head = FPNamed (p, None ); fp_args = [] ; }
@@ -832,11 +986,11 @@ let process_rewrite1_r ttenv ?target ri tc =
832986
833987 let do1 (lemma , _ ) tc =
834988 let pt = PT. pt_of_uglobal_r (PT. copy ptenv0) lemma in
835- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc in
989+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc in
836990 t_ors (List. map do1 ls) tc
837991
838992 | _ ->
839- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
993+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
840994 end
841995
842996 | { fp_head = FPCut (Some f); fp_args = [] ; }
@@ -856,16 +1010,16 @@ let process_rewrite1_r ttenv ?target ri tc =
8561010 let pt = PTApply { pt_head = PTCut (f, None ); pt_args = [] ; } in
8571011 let pt = { ptev_env = ptenv; ptev_pt = pt; ptev_ax = f; } in
8581012
859- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
1013+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
8601014
8611015 | _ ->
8621016 let pt = PT. process_full_pterm ~implicits ptenv pt in
863- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
1017+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
8641018 in
8651019
8661020 let doall mode tc = t_ors (List. map (do1 mode) pts) tc in
8671021
868- match r with
1022+ match rwopt.repeat with
8691023 | None ->
8701024 doall `Full tc
8711025 | Some (`Maybe, None) ->
0 commit comments