@@ -249,6 +249,8 @@ module LowRewrite = struct
249249 | LRW_IdRewriting
250250 | LRW_RPatternNoMatch
251251 | LRW_RPatternNoRuleMatch
252+ | LRW_RPatternNotLinear
253+ | LRW_RPatternNoVariable
252254
253255 exception RewriteError of error
254256
@@ -326,48 +328,120 @@ module LowRewrite = struct
326328
327329 let find_rewrite_patterns = find_rewrite_patterns ~inpred: false
328330
329- type rwinfos = rwside * EcFol . form option * EcMatching .occ option
331+ type rwinfos = rwside * ( form * ( EcIdent .t * ty ) option ) option * EcMatching .occ option
330332
331- let t_rewrite_r ?(mode = `Full ) ?target ((s , prw , o ) : rwinfos ) pt tc =
333+ let t_rewrite_r
334+ ?(mode : [`Full | `Light] = `Full )
335+ ?(target : EcIdent.t option )
336+ ((s , prw , o ) : rwinfos )
337+ (pt : pt_ev )
338+ (tc : tcenv1 )
339+ =
332340 let hyps, tgfp = FApi. tc1_flat ?target tc in
333341
334342 let modes =
335343 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
344+ | `Full -> [{ k_keyed = true ; k_conv = false ; k_delta = true };
345+ { k_keyed = true ; k_conv = true ; k_delta = true };]
346+ | `Light -> [{ k_keyed = true ; k_conv = false ; k_delta = true }] in
339347
340348 let for1 (pt , mode , (f1 , f2 )) =
341349 let fp, tp = match s with `LtoR -> f1, f2 | `RtoL -> f2, f1 in
342- let subf, occmode =
350+ let subf, occmode, cpos =
343351 match prw with
344352 | None -> begin
345353 try
346- PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
354+ let subf, occmode =
355+ PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
356+ in
357+ (subf, occmode, None )
347358 with
348359 | PT. FindOccFailure `MatchFailure ->
349360 raise (RewriteError LRW_NothingToRewrite )
350361 | PT. FindOccFailure `IncompleteMatch ->
351362 raise (RewriteError LRW_CannotInfer )
352363 end
353364
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
365+ | Some (prw , subl ) -> begin
366+ let subcpos =
367+ match subl with
368+ | None -> None
361369
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 ->
370+ | Some (x , xty ) ->
371+ let fx = f_local x xty in
372+ let subcpos =
373+ FPosition. select_form
374+ ~xconv: `Eq ~keyed: true hyps None fx prw
375+ in
376+
377+ if FPosition. is_empty subcpos then
378+ raise (RewriteError LRW_RPatternNoVariable );
379+
380+ if FPosition. occurences subcpos <> 1 then
381+ raise (RewriteError LRW_RPatternNotLinear );
382+
383+ let subcpos =
384+ match o with
385+ | None -> subcpos
386+ | Some o ->
387+ if not (FPosition. is_occurences_valid (snd o) subcpos) then
388+ raise (RewriteError LRW_InvalidOccurence );
389+ FPosition. filter o subcpos
390+ in
391+
392+ Some subcpos
393+ in
394+
395+ let ctxt_modes =
396+ match subl with
397+ | None -> modes
398+ | Some _ -> [{ k_keyed = true ; k_conv = false ; k_delta = false }]
399+ in
400+
401+ let prw, prwmode =
402+ try
403+ PT. pf_find_occurence_lazy
404+ pt.PT. ptev_env ~full: false ~modes: ctxt_modes ~ptn: prw tgfp
405+ with PT. FindOccFailure `MatchFailure ->
406+ raise (RewriteError LRW_RPatternNoMatch ) in
407+
408+ let find_in_rpattern ~modes fp prw =
409+ try
410+ PT. pf_find_occurence_lazy
411+ pt.PT. ptev_env ~rooted: true ~modes ~ptn: fp prw
412+ with
413+ | PT. FindOccFailure `MatchFailure ->
367414 raise (RewriteError LRW_RPatternNoRuleMatch )
368- | PT. FindOccFailure `IncompleteMatch ->
369- raise (RewriteError LRW_CannotInfer )
370- end in
415+ | PT. FindOccFailure `IncompleteMatch ->
416+ raise (RewriteError LRW_CannotInfer )
417+ in
418+
419+ match subcpos with
420+ | None ->
421+ let subf, occmode =
422+ find_in_rpattern ~modes: ctxt_modes fp prw
423+ in
424+ (subf, occmode, None )
425+
426+ | Some subcpos ->
427+ let subf = FPosition. first_selected_subform subcpos prw in
428+
429+ ignore (find_in_rpattern ~modes: ctxt_modes fp subf);
430+
431+ let cpos =
432+ let prwpos =
433+ FPosition. select_form
434+ ~xconv: `AlphaEq ~keyed: prwmode.k_keyed hyps
435+ (Some (`Inclusive , EcMaps.Sint. singleton 1 ))
436+ prw tgfp
437+ in
438+ let root = FPosition. path_of_singleton_occurence prwpos in
439+ FPosition. reroot root subcpos
440+ in
441+
442+ (subf, { k_keyed = true ; k_conv = false ; k_delta = false }, Some cpos)
443+ end
444+ in
371445
372446 if not occmode.k_keyed then begin
373447 let tp = PT. concretize_form pt.PT. ptev_env tp in
@@ -377,10 +451,15 @@ module LowRewrite = struct
377451
378452 let pt = fst (PT. concretize pt) in
379453 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 ))
454+ match cpos with
455+ | Some cpos -> cpos
456+ | None ->
457+ try
458+ FPosition. select_form
459+ ~xconv: `AlphaEq ~keyed: occmode.k_keyed
460+ hyps o subf tgfp
461+ with InvalidOccurence ->
462+ raise (RewriteError LRW_InvalidOccurence )
384463 in
385464
386465 EcLowGoal. t_rewrite
@@ -569,7 +648,14 @@ let process_apply_top tc =
569648 | _ -> tc_error !! tc " no top assumption"
570649
571650(* -------------------------------------------------------------------- *)
572- let process_rewrite1_core ?mode ?(close = true ) ?target (s , p , o ) pt tc =
651+ let process_rewrite1_core
652+ ?(mode : [`Full | `Light] option )
653+ ?(close : bool = true )
654+ ?(target : EcIdent.t option )
655+ ((s , p , o ) : rwside * (form * (EcIdent. t * ty ) option ) option * rwocc )
656+ (pt : pt_ev )
657+ (tc : tcenv1 )
658+ =
573659 let o = norm_rwocc o in
574660
575661 try
@@ -596,9 +682,13 @@ let process_rewrite1_core ?mode ?(close = true) ?target (s, p, o) pt tc =
596682 tc_error !! tc " r-pattern does not match the goal"
597683 | LowRewrite. LRW_RPatternNoRuleMatch ->
598684 tc_error !! tc " r-pattern does not match the rewriting rule"
685+ | LowRewrite. LRW_RPatternNotLinear ->
686+ tc_error !! tc " context variable must appear exactly once in the r-pattern"
687+ | LowRewrite. LRW_RPatternNoVariable ->
688+ tc_error !! tc " context variable does not appear in the r-pattern"
599689
600690(* -------------------------------------------------------------------- *)
601- let process_delta ~und_delta ?target (s , o , p ) tc =
691+ let process_delta ~und_delta ?target (( s :rwside ) , o , p ) tc =
602692 let env, hyps, concl = FApi. tc1_eflat tc in
603693 let o = norm_rwocc o in
604694
@@ -768,38 +858,50 @@ let process_rewrite1_r ttenv ?target ri tc =
768858 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
769859 t_simplify_lg ?target ~delta: `IfApplied (ttenv, logic) tc
770860
771- | RWDelta (( s , r , o , px ) , p ) -> begin
772- if Option. is_some px then
861+ | RWDelta (rwopt , p ) -> begin
862+ if Option. is_some rwopt.match_ then
773863 tc_error !! tc " cannot use pattern selection in delta-rewrite rules" ;
774864
775- let do1 tc = process_delta ~und_delta ?target (s, o, p) tc in
865+ let do1 tc =
866+ process_delta ~und_delta ?target (rwopt.side, rwopt.occurrence, p) tc in
776867
777- match r with
868+ match rwopt.repeat with
778869 | None -> do1 tc
779870 | Some (b , n ) -> t_do b n do1 tc
780871 end
781872
782- | RWRw ((( s : rwside ), r , o , p ) , pts ) -> begin
873+ | RWRw (rwopt , pts ) -> begin
783874 let do1 (mode : [`Full | `Light] ) ((subs : rwside ), pt ) tc =
784875 let hyps = FApi. tc1_hyps tc in
785876 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
786877 let hyps = FApi. tc1_hyps ?target tc in
787878
788879 let ptenv, prw =
789- match p with
880+ match rwopt.match_ with
790881 | None ->
791882 PT. ptenv_of_penv hyps !! tc, None
792883
793- | Some p ->
884+ | Some (RWM_Plain p ) ->
794885 let (ps, ue), p = TTC. tc1_process_pattern tc p in
795886 let ev = MEV. of_idents (Mid. keys ps) `Form in
796- (PT. ptenv !! tc hyps (ue, ev), Some p) in
887+ (PT. ptenv !! tc hyps (ue, ev), Some (p, None ))
888+
889+ | Some (RWM_Context (x , p )) ->
890+ let ps = ref Mid. empty in
891+ let ue = EcProofTyping. unienv_of_hyps hyps in
892+ let x = EcIdent. create (unloc x) in
893+ let xty = EcUnify.UniEnv. fresh ue in
894+ let hyps = FApi. tc1_hyps tc in
895+ let hyps = LDecl. add_local x (LD_var (xty, None )) hyps in
896+ let p = EcTyping. trans_pattern (LDecl. toenv hyps) ps ue p in
897+ let ev = MEV. of_idents (x :: Mid. keys ! ps) `Form in
898+ (PT. ptenv !! tc hyps (ue, ev), Some (p, Some (x, xty))) in
797899
798900 let theside =
799- match s , subs with
800- | `LtoR , _ -> (subs :> rwside )
801- | _ , `LtoR -> (s :> rwside )
802- | `RtoL , `RtoL -> (`LtoR :> rwside ) in
901+ match rwopt.side , subs with
902+ | `LtoR , _ -> (subs :> rwside )
903+ | _ , `LtoR -> (rwopt.side :> rwside )
904+ | `RtoL , `RtoL -> (`LtoR :> rwside ) in
803905
804906 let is_baserw p =
805907 EcEnv.BaseRw. is_base p.pl_desc (FApi. tc1_env tc) in
@@ -814,7 +916,7 @@ let process_rewrite1_r ttenv ?target ri tc =
814916
815917 let do1 lemma tc =
816918 let pt = PT. pt_of_uglobal_r (PT. copy ptenv) lemma in
817- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
919+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
818920 in t_ors (List. map do1 ls) tc
819921
820922 | { fp_head = FPNamed (p, None ); fp_args = [] ; }
@@ -832,11 +934,11 @@ let process_rewrite1_r ttenv ?target ri tc =
832934
833935 let do1 (lemma , _ ) tc =
834936 let pt = PT. pt_of_uglobal_r (PT. copy ptenv0) lemma in
835- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc in
937+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc in
836938 t_ors (List. map do1 ls) tc
837939
838940 | _ ->
839- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
941+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
840942 end
841943
842944 | { fp_head = FPCut (Some f); fp_args = [] ; }
@@ -856,16 +958,16 @@ let process_rewrite1_r ttenv ?target ri tc =
856958 let pt = PTApply { pt_head = PTCut (f, None ); pt_args = [] ; } in
857959 let pt = { ptev_env = ptenv; ptev_pt = pt; ptev_ax = f; } in
858960
859- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
961+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
860962
861963 | _ ->
862964 let pt = PT. process_full_pterm ~implicits ptenv pt in
863- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
965+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
864966 in
865967
866968 let doall mode tc = t_ors (List. map (do1 mode) pts) tc in
867969
868- match r with
970+ match rwopt.repeat with
869971 | None ->
870972 doall `Full tc
871973 | Some (`Maybe, None) ->
0 commit comments