@@ -68,7 +68,7 @@ module Position = struct
6868 *)
6969
7070 (* Branch selection *)
71- type codepos_brsel = [`Cond of bool | `Match of EcSymbols .symbol ]
71+ type codepos_brsel = [`Cond of bool | `Match of EcSymbols .symbol | `MatchByPos of int ]
7272 type nm_codepos_brsel = [`Cond of bool | `Match of int ]
7373
7474 (* Linear code position inside a block *)
@@ -354,21 +354,23 @@ module Position = struct
354354 try List. findi (fun _ n -> EcSymbols. sym_equal sel n) cnames |> fst
355355 with Not_found -> raise InvalidCPos
356356
357+ let select_match_arm on_error env e (br :codepos_brsel ) =
358+ match br with
359+ | `Match ms -> select_match_arm_idx env e ms
360+ | `MatchByPos ix -> ix
361+ | _ -> on_error ()
362+
357363 (* Get the block pointed to by brsel for a given instruction *)
358364 let normalize_brsel (env : env ) (i : instr ) (br : codepos_brsel ) : (env * stmt) * nm_codepos_brsel =
359365 match i.i_node, br with
360366 | (Sif (_ , t , _ ), `Cond true ) -> (env, t), `Cond true
361367 | (Sif (_ , _ , f ), `Cond false ) -> (env, f), `Cond false
362368 | (Swhile (_ , s ), `Cond true ) -> (env, s), `Cond true
363- | (Smatch (e , ss ), `Match ms ) ->
364- let ix = select_match_arm_idx env e ms in
369+ | (Smatch (e , ss ), _ ) ->
370+ let ix = select_match_arm ( fun _ -> assert false ) env e br in
365371 let (locals, s) = List. at ss ix in
366372 let env = EcEnv.Var. bind_locals locals env in
367- begin try
368- (env, s), `Match ix
369- with Invalid_argument _ ->
370- raise InvalidCPos
371- end
373+ (env, s), `Match ix
372374 | _ -> assert false
373375
374376 let select_branch (env : env ) (i : instr ) (br : codepos_brsel ) : stmt =
@@ -515,6 +517,34 @@ module Position = struct
515517 let iter_blocks ~(start : nm_codegap1 ) ~(block_size : int ) (s : stmt )
516518 (f : int -> nm_codegap1 -> nm_codegap1 -> unit ) : unit =
517519 fold_blocks ~start ~block_size s (fun idx g1 g2 () -> f idx g1 g2) ()
520+
521+ let find_first_matching_instr (test : instr -> bool ) (s : stmt ) =
522+ let exception Found of codepos in
523+
524+ let rec find_pos rpath n (s : instr list ) =
525+ match s with
526+ | [] -> ()
527+ | i :: s ->
528+ if test i then raise (Found (List. rev rpath, cpos1 n));
529+ find_pos_sub rpath n i;
530+ find_pos rpath (n + 1 ) s
531+
532+ and find_pos_sub rpath n i =
533+ match i.i_node with
534+ | Sif (_ , s1 , s2 ) ->
535+ find_pos ((cpos1 n, `Cond true ) :: rpath) 0 s1.s_node;
536+ find_pos ((cpos1 n, `Cond false ) :: rpath) 0 s2.s_node
537+ | Swhile (_ , s ) ->
538+ find_pos ((cpos1 n, `Cond true ) :: rpath) 0 s.s_node
539+ | Smatch (_ , bs ) ->
540+ List. iteri (fun i (_ , s ) ->
541+ find_pos ((cpos1 n, `MatchByPos i) :: rpath) 0 s.s_node
542+ ) bs
543+ | _ -> ()
544+ in
545+
546+ try find_pos [] 0 s.s_node; None
547+ with Found r -> Some r
518548end
519549
520550(* -------------------------------------------------------------------- *)
@@ -572,8 +602,8 @@ module Zipper = struct
572602 | Sif (e , ifs1 , ifs2 ), `Cond false ->
573603 (ZIfElse (e, ifs1, ((s1, s2), zpr)), ifs2), `Cond false , env
574604
575- | Smatch (e , bs ), `Match cn ->
576- let ix = select_match_arm_idx env e cn in
605+ | Smatch (e , bs ), _ ->
606+ let ix = select_match_arm ( fun () -> raise InvalidCPos ) env e sub in
577607 let prebr, (locals, body), postbr = List. pivot_at ix bs in
578608 let env = EcEnv.Var. bind_locals locals env in
579609 (ZMatch (e, ((s1, s2), zpr), { locals; prebr; postbr; }), body), `Match ix, env
0 commit comments