@@ -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,133 @@ 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 selected_subform (p : EcMatching.ptnpos ) (f : form ) =
334+ let selected = ref None in
335+
336+ let _ =
337+ EcMatching.FPosition. map p
338+ (fun fp ->
339+ if Option. is_none ! selected then selected := Some fp;
340+ fp)
341+ f
342+ in
343+
344+ oget ! selected
345+
346+ let t_rewrite_r
347+ ?(mode : [`Full | `Light] = `Full )
348+ ?(target : EcIdent.t option )
349+ ((s , prw , o ) : rwinfos )
350+ (pt : pt_ev )
351+ (tc : tcenv1 )
352+ =
332353 let hyps, tgfp = FApi. tc1_flat ?target tc in
333354
334355 let modes =
335356 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
357+ | `Full -> [{ k_keyed = true ; k_conv = false ; k_delta = true };
358+ { k_keyed = true ; k_conv = true ; k_delta = true };]
359+ | `Light -> [{ k_keyed = true ; k_conv = false ; k_delta = true }] in
339360
340361 let for1 (pt , mode , (f1 , f2 )) =
341362 let fp, tp = match s with `LtoR -> f1, f2 | `RtoL -> f2, f1 in
342- let subf, occmode =
363+ let subf, occmode, cpos =
343364 match prw with
344365 | None -> begin
345366 try
346- PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
367+ let subf, occmode =
368+ PT. pf_find_occurence_lazy pt.PT. ptev_env ~modes ~ptn: fp tgfp
369+ in
370+ (subf, occmode, None )
347371 with
348372 | PT. FindOccFailure `MatchFailure ->
349373 raise (RewriteError LRW_NothingToRewrite )
350374 | PT. FindOccFailure `IncompleteMatch ->
351375 raise (RewriteError LRW_CannotInfer )
352376 end
353377
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
378+ | Some (prw , subl ) -> begin
379+ let subcpos =
380+ match subl with
381+ | None -> None
361382
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 ->
383+ | Some (x , xty ) ->
384+ let fx = f_local x xty in
385+ let subcpos =
386+ FPosition. select_form
387+ ~xconv: `Eq ~keyed: true hyps None fx prw
388+ in
389+
390+ if FPosition. is_empty subcpos then
391+ raise (RewriteError LRW_RPatternNoVariable );
392+
393+ if FPosition. occurences subcpos <> 1 then
394+ raise (RewriteError LRW_RPatternNotLinear );
395+
396+ let subcpos =
397+ match o with
398+ | None -> subcpos
399+ | Some o ->
400+ if not (FPosition. is_occurences_valid (snd o) subcpos) then
401+ raise (RewriteError LRW_InvalidOccurence );
402+ FPosition. filter o subcpos
403+ in
404+
405+ Some subcpos
406+ in
407+
408+ let ctxt_modes =
409+ match subl with
410+ | None -> modes
411+ | Some _ -> [{ k_keyed = true ; k_conv = false ; k_delta = false }]
412+ in
413+
414+ let prw, prwmode =
415+ try
416+ PT. pf_find_occurence_lazy
417+ pt.PT. ptev_env ~full: false ~modes: ctxt_modes ~ptn: prw tgfp
418+ with PT. FindOccFailure `MatchFailure ->
419+ raise (RewriteError LRW_RPatternNoMatch ) in
420+
421+ let find_in_rpattern ~modes fp prw =
422+ try
423+ PT. pf_find_occurence_lazy
424+ pt.PT. ptev_env ~rooted: true ~modes ~ptn: fp prw
425+ with
426+ | PT. FindOccFailure `MatchFailure ->
367427 raise (RewriteError LRW_RPatternNoRuleMatch )
368- | PT. FindOccFailure `IncompleteMatch ->
369- raise (RewriteError LRW_CannotInfer )
370- end in
428+ | PT. FindOccFailure `IncompleteMatch ->
429+ raise (RewriteError LRW_CannotInfer )
430+ in
431+
432+ match subcpos with
433+ | None ->
434+ let subf, occmode =
435+ find_in_rpattern ~modes: ctxt_modes fp prw
436+ in
437+ (subf, occmode, None )
438+
439+ | Some subcpos ->
440+ let subf = selected_subform subcpos prw in
441+
442+ ignore (find_in_rpattern ~modes: ctxt_modes fp subf);
443+
444+ let cpos =
445+ let prwpos =
446+ FPosition. select_form
447+ ~xconv: `AlphaEq ~keyed: prwmode.k_keyed hyps
448+ (Some (`Inclusive , EcMaps.Sint. singleton 1 ))
449+ prw tgfp
450+ in
451+ let root = FPosition. path_of_singleton_occurence prwpos in
452+ FPosition. reroot root subcpos
453+ in
454+
455+ (subf, { k_keyed = true ; k_conv = false ; k_delta = false }, Some cpos)
456+ end
457+ in
371458
372459 if not occmode.k_keyed then begin
373460 let tp = PT. concretize_form pt.PT. ptev_env tp in
@@ -377,10 +464,15 @@ module LowRewrite = struct
377464
378465 let pt = fst (PT. concretize pt) in
379466 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 ))
467+ match cpos with
468+ | Some cpos -> cpos
469+ | None ->
470+ try
471+ FPosition. select_form
472+ ~xconv: `AlphaEq ~keyed: occmode.k_keyed
473+ hyps o subf tgfp
474+ with InvalidOccurence ->
475+ raise (RewriteError LRW_InvalidOccurence )
384476 in
385477
386478 EcLowGoal. t_rewrite
@@ -569,7 +661,14 @@ let process_apply_top tc =
569661 | _ -> tc_error !! tc " no top assumption"
570662
571663(* -------------------------------------------------------------------- *)
572- let process_rewrite1_core ?mode ?(close = true ) ?target (s , p , o ) pt tc =
664+ let process_rewrite1_core
665+ ?(mode : [`Full | `Light] option )
666+ ?(close : bool = true )
667+ ?(target : EcIdent.t option )
668+ ((s , p , o ) : rwside * (form * (EcIdent. t * ty ) option ) option * rwocc )
669+ (pt : pt_ev )
670+ (tc : tcenv1 )
671+ =
573672 let o = norm_rwocc o in
574673
575674 try
@@ -596,9 +695,13 @@ let process_rewrite1_core ?mode ?(close = true) ?target (s, p, o) pt tc =
596695 tc_error !! tc " r-pattern does not match the goal"
597696 | LowRewrite. LRW_RPatternNoRuleMatch ->
598697 tc_error !! tc " r-pattern does not match the rewriting rule"
698+ | LowRewrite. LRW_RPatternNotLinear ->
699+ tc_error !! tc " context variable must appear exactly once in the r-pattern"
700+ | LowRewrite. LRW_RPatternNoVariable ->
701+ tc_error !! tc " context variable does not appear in the r-pattern"
599702
600703(* -------------------------------------------------------------------- *)
601- let process_delta ~und_delta ?target (s , o , p ) tc =
704+ let process_delta ~und_delta ?target (( s :rwside ) , o , p ) tc =
602705 let env, hyps, concl = FApi. tc1_eflat tc in
603706 let o = norm_rwocc o in
604707
@@ -768,38 +871,50 @@ let process_rewrite1_r ttenv ?target ri tc =
768871 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
769872 t_simplify_lg ?target ~delta: `IfApplied (ttenv, logic) tc
770873
771- | RWDelta (( s , r , o , px ) , p ) -> begin
772- if Option. is_some px then
874+ | RWDelta (rwopt , p ) -> begin
875+ if Option. is_some rwopt.match_ then
773876 tc_error !! tc " cannot use pattern selection in delta-rewrite rules" ;
774877
775- let do1 tc = process_delta ~und_delta ?target (s, o, p) tc in
878+ let do1 tc =
879+ process_delta ~und_delta ?target (rwopt.side, rwopt.occurrence, p) tc in
776880
777- match r with
881+ match rwopt.repeat with
778882 | None -> do1 tc
779883 | Some (b , n ) -> t_do b n do1 tc
780884 end
781885
782- | RWRw ((( s : rwside ), r , o , p ) , pts ) -> begin
886+ | RWRw (rwopt , pts ) -> begin
783887 let do1 (mode : [`Full | `Light] ) ((subs : rwside ), pt ) tc =
784888 let hyps = FApi. tc1_hyps tc in
785889 let target = target |> omap (fst -| ((LDecl. hyp_by_name^~ hyps) -| unloc)) in
786890 let hyps = FApi. tc1_hyps ?target tc in
787891
788892 let ptenv, prw =
789- match p with
893+ match rwopt.match_ with
790894 | None ->
791895 PT. ptenv_of_penv hyps !! tc, None
792896
793- | Some p ->
897+ | Some (RWM_Plain p ) ->
794898 let (ps, ue), p = TTC. tc1_process_pattern tc p in
795899 let ev = MEV. of_idents (Mid. keys ps) `Form in
796- (PT. ptenv !! tc hyps (ue, ev), Some p) in
900+ (PT. ptenv !! tc hyps (ue, ev), Some (p, None ))
901+
902+ | Some (RWM_Context (x , p )) ->
903+ let ps = ref Mid. empty in
904+ let ue = EcProofTyping. unienv_of_hyps hyps in
905+ let x = EcIdent. create (unloc x) in
906+ let xty = EcUnify.UniEnv. fresh ue in
907+ let hyps = FApi. tc1_hyps tc in
908+ let hyps = LDecl. add_local x (LD_var (xty, None )) hyps in
909+ let p = EcTyping. trans_pattern (LDecl. toenv hyps) ps ue p in
910+ let ev = MEV. of_idents (x :: Mid. keys ! ps) `Form in
911+ (PT. ptenv !! tc hyps (ue, ev), Some (p, Some (x, xty))) in
797912
798913 let theside =
799- match s , subs with
800- | `LtoR , _ -> (subs :> rwside )
801- | _ , `LtoR -> (s :> rwside )
802- | `RtoL , `RtoL -> (`LtoR :> rwside ) in
914+ match rwopt.side , subs with
915+ | `LtoR , _ -> (subs :> rwside )
916+ | _ , `LtoR -> (rwopt.side :> rwside )
917+ | `RtoL , `RtoL -> (`LtoR :> rwside ) in
803918
804919 let is_baserw p =
805920 EcEnv.BaseRw. is_base p.pl_desc (FApi. tc1_env tc) in
@@ -814,7 +929,7 @@ let process_rewrite1_r ttenv ?target ri tc =
814929
815930 let do1 lemma tc =
816931 let pt = PT. pt_of_uglobal_r (PT. copy ptenv) lemma in
817- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
932+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
818933 in t_ors (List. map do1 ls) tc
819934
820935 | { fp_head = FPNamed (p, None ); fp_args = [] ; }
@@ -832,11 +947,11 @@ let process_rewrite1_r ttenv ?target ri tc =
832947
833948 let do1 (lemma , _ ) tc =
834949 let pt = PT. pt_of_uglobal_r (PT. copy ptenv0) lemma in
835- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc in
950+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc in
836951 t_ors (List. map do1 ls) tc
837952
838953 | _ ->
839- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
954+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
840955 end
841956
842957 | { fp_head = FPCut (Some f); fp_args = [] ; }
@@ -856,16 +971,16 @@ let process_rewrite1_r ttenv ?target ri tc =
856971 let pt = PTApply { pt_head = PTCut (f, None ); pt_args = [] ; } in
857972 let pt = { ptev_env = ptenv; ptev_pt = pt; ptev_ax = f; } in
858973
859- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
974+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
860975
861976 | _ ->
862977 let pt = PT. process_full_pterm ~implicits ptenv pt in
863- process_rewrite1_core ~mode ?target (theside, prw, o ) pt tc
978+ process_rewrite1_core ~mode ?target (theside, prw, rwopt.occurrence ) pt tc
864979 in
865980
866981 let doall mode tc = t_ors (List. map (do1 mode) pts) tc in
867982
868- match r with
983+ match rwopt.repeat with
869984 | None ->
870985 doall `Full tc
871986 | Some (`Maybe, None) ->
0 commit comments