https://github.com/EasyCrypt/easycrypt
Raw File
Tip revision: 8bceccd0cf22999f88e5e30e1269c6153b519729 authored by Cécile BARITEL-RUET on 13 December 2017, 16:30:02 UTC
.
Tip revision: 8bceccd
ecFMatching.ml
open EcUtils
open EcFol
open EcTypes
open EcPath
open EcIdent
open EcEnv
(* open EcGenRegexp *)
(* open EcMatching *)

(* ---------------------------------------------------------------------- *)
exception NoMatches
exception CannotUnify
exception NoNext


module Name = struct
  include EcIdent
  let compare = id_compare
end


(* -------------------------------------------------------------------------- *)

module FPattern = struct

  type name = Name.t

  (* invariant of pattern : if the form is not Pobject, then there is
     at least one of the first set of patterns *)
  type pattern =
    | Panything
    | Pnamed     of pattern * name
    | Psub       of pattern
    | Por        of pattern list

    | Ptype      of pattern * ty

    | Pobject    of tobject

    | Pif        of pattern * pattern * pattern
    | Papp       of pattern * pattern list
    | Ptuple     of pattern list
    | Pproj      of pattern * int
    | Pmatch     of pattern * pattern list
    | Pquant     of quantif * bindings * pattern
    (* | Plet    of lpattern * pattern * pattern *)
    | Ppvar      of pattern * pattern
    | Pglob      of pattern * pattern
    (* | FhoareF of hoareF (\* $hr / $hr *\) *)
    (* | FhoareS of hoareS *)
    (* | FbdHoareF of bdHoareF (\* $hr / $hr *\) *)
    (* | FbdHoareS of bdHoareS *)
    (* | FequivF of equivF (\* $left,$right / $left,$right *\) *)
    (* | FequivS of equivS *)
    (* | FeagerF of eagerF *)
    | Ppr             of pattern * pattern * pattern * pattern

    | Pprog_var       of prog_var

    | Pxpath          of xpath
    (* mpath patterns *)
    (*                   mpath_top, mpath  list *)
    | Pmpath          of pattern * pattern list

   and tobject =
    | Oform      of form
    | Omem       of EcMemory.memory
    (* | Ompath     of mpath *)
    (* | Oxpath     of xpath *)
    | Ompath_top of mpath_top

  type tmatch = tobject * binding Mid.t

  type map = tmatch Mid.t

  type to_match = tmatch * pattern

  type pat_continuation =
    | ZTop
    | Znamed     of tmatch * name * pat_continuation
    (* Zor (cont, e_list, ne) :
       - cont   : the continuation if the matching is correct
       - e_list : if not, the sorted list of next engines to try matching with
       - ne     : if no match at all, then take the nengine to go up
     *)
    | Zor        of pat_continuation * engine list * nengine
    (* Zand (before, after, cont) :
       - before : list of couples (form, pattern) that has already been checked
       - after  : list of couples (form, pattern) to check in the following
       - cont   : continuation if all the matches succeed
     *)
    | Zand       of to_match list * to_match list * pat_continuation

    | Zbinds     of pat_continuation * binding Mid.t

  and engine = {
      e_head         : tmatch;
      e_continuation : pat_continuation;
      e_pattern      : pattern;
      e_map          : map;
      e_hyps         : EcEnv.LDecl.hyps;
    }

  and nengine = {
      ne_continuation : pat_continuation;
      ne_map          : map;
      ne_binds        : binding Mid.t;
      ne_hyps         : EcEnv.LDecl.hyps;
    }

  (* val mkengine    : base -> engine *)
  let mkengine (f : form) (p : pattern) (h : LDecl.hyps) : engine = {
      e_head         = Oform f, Mid.empty ;
      e_continuation = ZTop ;
      e_map          = Mid.empty ;
      e_pattern      = p ;
      e_hyps         = h ;
    }

  type ismatch =
    | Match
    | NoMatch

  let object_equal (o1 : tobject) (o2 : tobject) (h : LDecl.hyps) : bool =
    match o1,o2 with
    | Oform f1, Oform f2 -> EcReduction.is_conv h f1 f2
    | Omem m1, Omem m2 -> EcMemory.mem_equal m1 m2
    | Ompath_top (`Local id1), Ompath_top (`Local id2) -> id_equal id1 id2
    | Ompath_top (`Concrete (p1,None)), Ompath_top (`Concrete (p2,None)) ->
       p_equal p1 p2
    | Ompath_top (`Concrete (p1,Some op1)), Ompath_top (`Concrete (p2,Some op2)) ->
       p_equal p1 p2 && p_equal op1 op2
    | ((Omem _|Ompath_top _|Oform _),
       (Omem _|Ompath_top _|Oform _))
      -> false

  let rec merge_binds bs1 bs2 map = match bs1,bs2 with
    | [], _ | _,[] -> Some (map,bs1,bs2)
    | (_,ty1)::_, (_,ty2)::_ when not(gty_equal ty1 ty2) -> None
    | (id1,_)::_, (_,_)::_ when Mid.mem id1 map -> None
    | (id1,_)::bs1, (id2,ty2)::bs2 ->
       merge_binds bs1 bs2 (Mid.add id1 (id2,ty2) map)

  (* add_match can raise the exception : CannotUnify *)
  (* val add_match : matches -> name -> t_matches -> matches *)
  let add_match (map : map) (name : name) (o : tmatch) h =
    if Mid.set_disjoint (snd o) map
    then
      let (o1,o2) = o in
      let o = o1,match o1 with
                 | Oform      f  -> Mid.set_inter o2 (f_fv f)
                 | Omem       m  -> Mid.set_inter o2 (Sid.singleton m)
                 | Ompath_top mp -> Mid.set_inter o2 (m_fv Mid.empty (mpath mp [])) in
      let map = match Mid.find_opt name map with
        | None   -> Mid.add name o map
        | Some x -> if object_equal (fst x) (fst o) h then map
                    else raise CannotUnify
      in map
    else raise CannotUnify

  let e_next (e : engine) : nengine =
    { ne_continuation = e.e_continuation;
      ne_map = e.e_map;
      ne_binds = snd e.e_head;
      ne_hyps = e.e_hyps;
    }

  let n_engine (tm : tmatch) (e_pattern : pattern) (n : nengine) =
    { e_head = (fst tm, n.ne_binds);
      e_pattern;
      e_continuation = n.ne_continuation;
      e_map = n.ne_map;
      e_hyps = n.ne_hyps;
    }

  let sub_engine e p f =
    { e with e_head = f; e_pattern = Psub p }


  let rec substitution n1 p1 p2 = match p2 with
    | Panything -> Panything
    | Pnamed (_,n2) when id_equal n1 n2 -> p1
    | Pnamed (p2,n2) -> Pnamed (substitution n1 p1 p2, n2)
    | Psub p -> Psub (substitution n1 p1 p)
    | Por pl -> Por (List.map (substitution n1 p1) pl)
    | Ptype (p,ty) -> Ptype (substitution n1 p1 p, ty)
    | Pif (p2,p3,p4) -> Pif (substitution n1 p1 p2,
                             substitution n1 p1 p3,
                             substitution n1 p1 p4)
    | Papp (p2,pl) -> Papp (substitution n1 p1 p2,
                            List.map (substitution n1 p1) pl)
    | Ptuple pl -> Ptuple (List.map (substitution n1 p1) pl)
    | Pproj (p2,i) -> Pproj (substitution n1 p1 p2,i)
    | Pmatch (p2,pl) -> Pmatch (substitution n1 p1 p2,
                                List.map (substitution n1 p1) pl)
    | Pquant (q,bs,p2) -> Pquant (q,bs,substitution n1 p1 p2)
    | Ppvar (p2,p3) -> Ppvar (substitution n1 p1 p2,substitution n1 p1 p3)
    | Pglob (p2,p3) -> Pglob (substitution n1 p1 p2,substitution n1 p1 p3)
    | Ppr (p2,p3,p4,p5) -> Ppr (substitution n1 p1 p2,
                                substitution n1 p1 p3,
                                substitution n1 p1 p4,
                                substitution n1 p1 p5)
    | Pprog_var pv ->
       let xp = pv.pv_name in
       let name = xp.x_sub in
       if (EcPath.tostring name) = (EcIdent.tostring n1) then p1 else p2
    | Pxpath xp ->
       let name = xp.x_sub in
       if (EcPath.tostring name) = (EcIdent.tostring n1) then p1 else p2
    | Pmpath (p2,pl) -> Pmpath (substitution n1 p1 p2,
                                List.map (substitution n1 p1) pl)
    | Pobject (Omem mem) ->
       if id_equal n1 mem then p1 else p2
    | Pobject (Ompath_top _) -> p2
    | Pobject (Oform f) ->
       if not(Mid.mem n1 f.f_fv) then p2
       else match f.f_node with
            |  Flocal id ->
                if id_equal id n1 then Ptype (p1,f.f_ty) else p2
            | Fquant (quant,bs,f') ->
               if Mid.mem n1 f'.f_fv then Pquant (quant,bs,substitution n1 p1 (Pobject (Oform f')))
               else p2
            | Fif (f1,f2,f3) ->
               Pif (substitution n1 p1 (Pobject (Oform f1)),
                    substitution n1 p1 (Pobject (Oform f2)),
                    substitution n1 p1 (Pobject (Oform f3)))
            | Fmatch _ | Flet _-> Pobject (Oform f) (* FIXME *)
            | Fint _ -> Pobject (Oform f)
            | Fpvar (pvar,mem) ->
               if id_equal mem n1 then Ppvar (Pprog_var pvar,p1)
               else p2
            | Fglob (mpath,mem) ->
               if id_equal mem n1 then Pglob (substitution_mpath n1 p1 mpath, p1)
               else p2
            | Fop _ -> Pobject (Oform f) (* FIXME *)
            | Fapp (f1,fargs) ->
               Papp (substitution n1 p1 (Pobject (Oform f1)),
                     List.map (fun f -> substitution n1 p1 (Pobject (Oform f))) fargs)
            | Ftuple t ->
               Ptuple (List.map (fun f -> substitution n1 p1 (Pobject (Oform f))) t)
            | Fproj (f1,i) -> Pproj (substitution n1 p1 (Pobject (Oform f1)),i)
            | _ -> (* FIXME *) p2

    and substitution_mpath n1 p1 mpath =
      Pmpath (Pobject (Ompath_top mpath.m_top),
              List.map (substitution_mpath n1 p1) mpath.m_args)

  (* ---------------------------------------------------------------------- *)
  let rec process (e : engine) : nengine =
    match e.e_pattern, e.e_head with
    | Panything, _ -> next Match e

    | Pnamed (p,name), _ ->
       process { e with
                 e_pattern = p;
                 e_continuation = Znamed(e.e_head,name,e.e_continuation);
               }

    | Psub p, _ ->
       let le = sub_engines e p in
       process { e with
                 e_pattern = p;
                 e_continuation = Zor (e.e_continuation,le,e_next e);
               }

    | Ptype (p,ty), (Oform f, _) ->
       if ty_equal ty f.f_ty then
         process { e with e_pattern = p }
       else next NoMatch e

    | Por [], _ -> next NoMatch e
    | Por (p::pl), _ ->
       let f p = { e with
                   e_pattern = p;
                 } in
       process { e with
                 e_pattern = p;
                 e_continuation = Zor (e.e_continuation,List.map f pl,e_next e);
               }

    | Pquant (q1,bs1,p), (Oform f,binds) ->
       begin match f.f_node with
       | Fquant (q2,bs2,f2) ->
          (* FIXME : lambda case to be considered in higher order *)
          if not(q1 = q2) then next NoMatch e
          else begin
              match merge_binds bs1 bs2 binds with
              | None -> next NoMatch e
              | Some (new_binds,[],args) ->
                 let p =
                   Mid.fold_left
                     (fun acc n1 (n2,ty) ->
                       match ty with
                       | GTty ty -> substitution n1 (Pobject (Oform (f_local n2 ty))) acc
                       | _ -> acc)
                     p new_binds in
                 process { e with
                           e_pattern = p;
                           e_head = (Oform (f_quant q2 args f2), new_binds);
                           e_continuation = Zbinds (e.e_continuation, binds);
                         }
              | Some (_new_binds,_args,[]) -> (* FIXME for higher order *)
              (*    let p = *)
              (*      Mid.fold_left *)
              (*        (fun acc n1 (n2,ty) -> *)
              (*          match ty with *)
              (*          | GTty ty -> substitution n1 (Pobject (Oform (f_local n2 ty))) acc *)
              (*          | _ -> acc) *)
              (*        p new_binds in *)
              (*    let p = Pquant (q1,args,p) in *)
              (*    process_higer_order { e with *)
              (*                          e_pattern = p; *)
              (*                          e_head = Oform f2, new_binds; *)
              (*                          e_continuation = Zbinds (e.e_continuation, binds); *)
              (*                        } *)
                 next NoMatch e
              | _ -> assert false
            end
       | _ -> next NoMatch e
       end

    | Pif (pcond,p1,p2), (Oform f,binds) ->
       begin match f_node f with
       | Fif (cond,b1,b2) ->
          let zand = [((Oform b1,binds),p1);((Oform b2,binds),p2)] in
          process { e with
                    e_head = Oform cond, binds;
                    e_pattern = pcond;
                    e_continuation = Zand ([],zand,e.e_continuation);
                  }
       | _ -> next NoMatch e
       end

    | Papp (pop,pargs), (Oform f, binds) ->
       (* FIXME : higher order *)
       begin match f_node f with
       | Fapp (fop,fargs) ->
          let pl,fl = List.length pargs, List.length fargs in
          if fl < pl
          then next NoMatch e (* process_higer_order e *)
          else
            let fargs1,fargs2 = List.split_at (fl - pl) fargs in
            let fop' = f_app fop fargs1 (EcTypes.toarrow (List.map f_ty fargs2) (f_ty fop)) in
            let to_match_args = List.combine (List.map (fun x -> Oform x, binds)fargs2) pargs in
            let l = ((Oform fop', binds), pop)::to_match_args in
            let p,h,l = match List.rev l with
              | [] -> assert false
              | (o,p)::l -> p,o,l in
            process { e with
                      e_pattern = p;
                      e_head = h;
                      e_continuation = Zand ([],l,e.e_continuation);
                    }
       | _ -> next NoMatch e (* process_higer_order e *)
       end

    | Ptuple [], (Oform f,_) ->
       begin match f_node f with
       | Ftuple [] -> next Match e
       | _ -> next NoMatch e
       end
    | Ptuple (p::ptuple), (Oform f, binds) ->
       begin match f_node f with
       | Ftuple [] -> next NoMatch e
       | Ftuple (f::ftuple) ->
          if (List.length ptuple = List.length ftuple)
          then
            let zand =
              List.combine (List.map (fun x -> Oform x, binds) ftuple) ptuple in
            let l = ((Oform f,binds),p)::zand in
            let pat,o,l = match List.rev l with
              | [] -> assert false
              | (o,p)::l -> p,o,l in
            process
              { e with
                e_pattern = p;
                e_head = Oform f, binds;
                e_continuation =
                  Zor (Zand ([],zand,e.e_continuation),
                       [{ e with
                          e_pattern = pat;
                          e_head = o;
                          e_continuation = Zand ([],l,e.e_continuation) }],
                       e_next e)
              }
          else next NoMatch e
       | _ -> next NoMatch e
       end

    | Pproj (e_pattern,i), (Oform f, binds) ->
       begin match f_node f with
       | Fproj (f,j) when i = j ->
          process { e with
                    e_pattern;
                    e_head = Oform f, binds;
                  }
       | _ -> next NoMatch e
       end

    | Pmatch (p,pl) , (Oform f,binds) ->
       begin match f_node f with
       | Fmatch (f,fl,_) when (List.length fl = List.length pl) ->
          let zand = List.combine (List.map (fun x -> Oform x, binds) fl) pl in
          process {
              e with
              e_pattern = p;
              e_head = Oform f, binds;
              e_continuation = Zand ([],zand,e.e_continuation);
            }
       | _ -> next NoMatch e
       end

    | Pobject o1, (o2,_) when object_equal o1 o2 e.e_hyps -> next Match e
    | Pobject (Oform f1), (Oform f2, _) -> begin
        match f1.f_node with
        | Flocal id1 -> begin
            match Mid.find_opt id1 e.e_map with
            | None -> next NoMatch e
            | Some (Oform f1, _) when EcReduction.is_conv e.e_hyps f1 f2 ->
               next Match e
            | _ -> next NoMatch e
          end
        | _ -> next NoMatch e
      end
    | Pobject _, _ -> next NoMatch e

    | Ppvar (p1,p2), (Oform f,binds) ->
       begin match f.f_node with
       | Fpvar (_,m) ->
          process { e with
                    e_pattern = p2;
                    e_head = Omem m, binds;
                    e_continuation = Zand ([],[(Oform f,binds),p1],e.e_continuation);
                  }
       | _ -> next NoMatch e
       end

    | Pprog_var x1, (Oform f,_) ->
       begin match f.f_node with
       | Fpvar (x2,_) when pv_equal x1 x2 -> next Match e
       | _ -> next NoMatch e
       end

    | Pglob (p1,p2), (Oform f,binds) ->
       begin match f.f_node with
       | Fglob (x,m) ->
          let zand = [(Ompath_top x.m_top,binds), p1] in
          process { e with
                    e_pattern = p2;
                    e_head = Omem m, binds;
                    e_continuation = Zand ([],zand,e.e_continuation);
                  }
       | _ -> next NoMatch e
       end

    | Pmpath (m,[]), (Ompath_top _,_ as omp) ->
       process { e with
                 e_pattern = m;
                 e_head = omp;
               }
    | Pmpath _,(Ompath_top _,_) -> next NoMatch e

    | Ppr (pmem,pfun,pargs,pevent), (Oform f, binds) ->
       begin match f.f_node with
       | Fpr pr ->
          let zand = [((Oform f, binds), pfun);
                      ((Oform pr.pr_args,binds), pargs);
                      ((Oform pr.pr_event, binds), pevent)] in
          process { e with
                    e_pattern = pmem;
                    e_head = Omem pr.pr_mem, binds;
                    e_continuation = Zand ([], zand, e.e_continuation);
                  }
       | _ -> next NoMatch e
       end

    | Pxpath pxp, (Oform f, _) ->
       begin match f.f_node with
       | Fpr pr when x_equal pr.pr_fun pxp -> next Match e
       | _ -> next NoMatch e
       end

    | ((Pmpath _|Pglob _|Pprog_var _|Ppvar _|Pquant _|Ppr _|Pxpath _),
       ((Oform _|Omem _|Ompath_top _),_))
      | (Pproj _|Ptuple _|Papp _|Pif _|Pmatch _|Ptype _),
        ((Omem _|Ompath_top _),_) ->
       next NoMatch e

  and next (m : ismatch) (e : engine) : nengine = next_n m (e_next e)

  and next_n (m : ismatch) (e : nengine) : nengine =
    match m,e.ne_continuation with
    | NoMatch, ZTop -> raise NoMatches

    | Match, ZTop   -> e

    | NoMatch, Znamed (_f, _name, ne_continuation) ->
       next_n NoMatch { e with ne_continuation }

    | Match, Znamed (f, name, ne_continuation) ->
       let m,e =
         try Match, { e with
                      ne_continuation;
                      ne_map = add_match e.ne_map name f e.ne_hyps;
                    }
         with
         | CannotUnify ->
            NoMatch, { e with
                       ne_continuation;
                     } in
       next_n m e

    | NoMatch, Zand (_,_,ne_continuation) ->
       next_n NoMatch { e with ne_continuation }

    | Match, Zand (_before,[],ne_continuation) -> next_n Match { e with ne_continuation }
    | Match, Zand (before,(f,p)::after,z) ->
       process (n_engine f p { e with ne_continuation = Zand ((f,p)::before,after,z)})

    | Match, Zor (ne_continuation, _, _) -> next_n Match { e with ne_continuation }

    | NoMatch, Zor (_, [], ne) ->
       next_n NoMatch ne

    | NoMatch, Zor (_, e'::engines, ne) ->
       process { e' with e_continuation = Zor (e'.e_continuation, engines, ne); }

    | Match, Zbinds (ne_continuation, ne_binds) ->
       next_n Match { e with ne_continuation; ne_binds }

    | NoMatch, Zbinds (ne_continuation, ne_binds) ->
       next_n NoMatch { e with ne_continuation; ne_binds }

  and sub_engines (e : engine) (p : pattern) : engine list =
    match e.e_head with
    | Omem _,_  -> []
    | Ompath_top _,_ -> []
    | Oform f, binds ->
       match f_node f with
       | Flet _
         | FhoareF _
         | FhoareS _
         | FbdHoareF _
         | FbdHoareS _
         | FequivF _
         | FequivS _
         | FeagerF _
         | Fint _
         | Flocal _
         | Fop _-> []
       | Fif (cond,f1,f2) ->
          List.map (sub_engine e p) [ Oform cond,binds ; Oform f1,binds ; Oform f2,binds ]
       | Fapp (f, args) ->
          List.map (sub_engine e p) ((Oform f,binds)::(List.map (fun x -> Oform x, binds) args))
       | Ftuple args ->
          List.map (sub_engine e p) (List.map (fun x -> Oform x, binds) args)
       | Fproj (f,_) -> [sub_engine e p (Oform f, binds)]
       | Fmatch (f,fl,_) ->
          List.map (sub_engine e p) ((Oform f, binds)::(List.map (fun x -> Oform x, binds) fl))
       | Fpr pr ->
          List.map (sub_engine e p) [ Omem pr.pr_mem   , binds ;
                                      Oform pr.pr_args , binds ;
                                      Oform pr.pr_event, binds ]
       | Fquant (_,bs,f1) ->
          [sub_engine e p (Oform f1, Mid.set_union binds (Mid.of_list (List.map (fun (x,y) -> (x,(x,y)))bs)))]
       | Fglob (mp,mem) ->
          List.map (sub_engine e p) [ Ompath_top mp.m_top,binds ;
                                      Omem mem, binds ]
       | Fpvar (_pv,mem) ->
          List.map (sub_engine e p) [ Omem mem, binds ]

  (* and process_higer_order (e : engine) = match e.e_head with *)
  (*   | Omem _,_ -> next NoMatch e (\* FIXME *\) *)
  (*   | Ompath_top _,_ -> next NoMatch e (\* FIXME *\) *)
  (*   | Oform f, _binds -> *)
  (*      match e.e_pattern,f.f_node with *)
  (*      | Pquant _,Fquant _ -> process e *)
  (*      | Pquant (_,[],p1), _ -> process { e with e_pattern = p1 } *)
  (*      | Pquant ((Lexists|Lforall),_,_),_ -> next NoMatch e *)
  (*      | Pquant (Llambda,(_x,_gty)::_args,_p1), _ -> *)
  (*         next NoMatch e *)

  (*      | Papp (pop, pargs), Fapp (fop,fargs) -> begin *)
  (*          let lp,lf = List.length pargs, List.length fargs in *)
  (*          let m x = min x 0 in *)
  (*          match List.split_at (m (lf-lp)) fargs, *)
  (*                List.split_at (m (lp-lf)) pargs with *)
  (*          | (_::_,_), (_::_,_) -> assert false *)
  (*          | ([],_), (_,_) -> process e *)
  (*          | (args,pargs), ([],fargs) -> *)

  (*          | _ -> next NoMatch e (\* FIXME *\) *)
  (*        end *)

  (*      | _,_ -> next NoMatch e (\* FIXME *\) *)



  let get_matches (e : engine) : map = e.e_map
  let get_n_matches (e : nengine) : map = e.ne_map

  let search_eng e =
    try Some (process e) with
    | NoMatches -> None

  let search (f : form) (p : pattern) (h : LDecl.hyps) =
    try Some (get_n_matches (process (mkengine f p h))) with
    | NoMatches -> None

  let pattern_of_form (bindings: bindings) (f : form) =
    let sbd = Sid.of_list (List.map fst bindings) in
    let rec aux f =
      if Mid.set_disjoint sbd f.f_fv then Pobject (Oform f)
      else
        match f.f_node with
        | Fif(f1,f2,f3)      -> Pif(aux f1, aux f2, aux f3)
        | Fapp(f,args)       -> Papp(aux f, List.map aux args)
        | Ftuple args        -> Ptuple(List.map aux args)
        | Fmatch(f,args,_ty) -> Pmatch(aux f, List.map aux args)
        | Fproj(f,i)         -> Pproj(aux f, i)
        | Flocal id          -> Pnamed (Ptype (Panything,f.f_ty), id)
        | Fpvar(x,m)         -> Ppvar(Pprog_var x, aux_mem m)
        | Fglob(mp, m)       -> Pglob(aux_mp mp, aux_mem m)
        | Fpr(pr)            -> Ppr (aux_mem pr.pr_mem,
                                     aux_xpath pr.pr_fun,
                                     aux pr.pr_args,
                                     aux_event pr.pr_event)
        | Fquant(quant,binds,f) -> Pquant (quant,binds,aux f)
        | _ -> raise (Invalid_argument "match case non-exhaustive in pattern_of_form")

    and aux_mem m =
      if Sid.mem m sbd then Pnamed (Panything, m)
      else Pobject(Omem m)

    and aux_mp mp =
      Pmpath (aux_mp_top mp.m_top, List.map aux_mp mp.m_args)

    and aux_mp_top mpt =
      match mpt with
      | `Local id when Sid.mem id sbd -> Pnamed (Panything, id)
      | _                             -> Pobject (Ompath_top mpt)

    and aux_xpath xpath = Pxpath xpath (* FIXME ?? *)

    and aux_event event = aux event
    in

    aux f




  let rec rewrite_term map f = match f.f_node with
    | Flocal id -> begin
        match Mid.find_opt id map with
        | None -> f
        | Some (Oform f', _) -> rewrite_term map f'
        | _ -> f
      end
    | Fquant (quant,bs,f') ->
       let f' = rewrite_term map f' in
       f_quant quant bs f'
    | Fif (f1,f2,f3) ->
       f_if (rewrite_term map f1) (rewrite_term map f2) (rewrite_term map f3)
    | Fmatch _ | Flet _-> f (* FIXME *)
    | Fint _ -> f
    | Fpvar (pvar,mem) ->
       begin match Mid.find_opt mem map with
       | None -> f
       | Some (Omem mem,_) -> f_pvar pvar f.f_ty mem
       | _ -> f
       end
    | Fglob (mpath,mem) ->
       begin match Mid.find_opt mem map with
       | None -> f
       | Some (Omem mem,_) -> f_glob mpath mem
       | _ -> f
       end
    | Fop _ -> f (* FIXME *)
    | Fapp (f1,fargs) ->
       f_app (rewrite_term map f1) (List.map (rewrite_term map) fargs) f.f_ty
    | Ftuple t -> f_tuple (List.map (rewrite_term map) t)
    | Fproj (f1,i) -> f_proj (rewrite_term map f1) i f.f_ty
    | _ -> (* FIXME *) f



end











(* (\* -------------------------------------------------------------------------- *\) *)

(* module IPattern = struct *)
(*   open FPattern *)
(*   open EcModules *)
(*   open Zipper *)

(*   exception AtEnd *)

(*   type anchor = Start | End *)

(*   type stmt_pattern = *)
(*     | Anchor of anchor *)
(*     | Any *)
(*     | Base   of instr_pattern *)
(*     | Choice of stmt_pattern list *)
(*     | Named  of stmt_pattern * EcIdent.t *)
(*     | Repeat of stmt_pattern * int option EcUtils.pair * *)
(*                   [ `Greedy | `Lazy ] *)
(*     | Seq    of stmt_pattern list *)

(*    and instr_pattern = *)
(*      | RAssign of pattern * pattern *)
(*      | RSample of pattern * pattern *)
(*      | RCall   of pattern * pattern * pattern *)
(*      | RIf     of pattern * stmt_pattern * stmt_pattern *)
(*      | RWhile  of pattern * stmt_pattern *)


(*   type stmt_engine = { *)
(*       se_head         : instr list; *)
(*       se_pattern      : stmt_pattern; *)
(*       se_zipper       : zipper; *)
(*       se_map          : instr list Mid.t; *)
(*       se_fmap         : tobject Mid.t; *)
(*       se_hyps         : LDecl.hyps; *)
(*       se_continuation : continuation; *)
(*     } *)

(*   and instr_engine = { *)
(*       ie_head         : instr; *)
(*       ie_pattern      : instr_pattern; *)
(*       ie_zipper       : zipper; *)
(*       ie_fmap         : tobject Mid.t; *)
(*       ie_hyps         : LDecl.hyps; *)
(*       ie_continuation : continuation; *)
(*     } *)

(*   and continuation = *)
(*     | Ctop *)
(*     | Cnamed of EcIdent.t * continuation *)
(*     | Cseq   of stmt_pattern list * continuation *)


(*   let mk_engine (stmt : stmt) (ps : stmt_pattern) (hyps : LDecl.hyps) = { *)
(*       se_head         = stmt.s_node; *)
(*       se_pattern      = ps; *)
(*       se_zipper       = zipper [] [] ZTop; *)
(*       se_map          = Mid.empty; *)
(*       se_fmap         = Mid.empty; *)
(*       se_hyps         = hyps; *)
(*       se_continuation = Ctop; *)
(*     } *)

(*   let process_stmt (se : stmt_engine) : instr_engine = *)
(*     match se.se_pattern with *)
(*     | Anchor Start when *)
(*            se.se_zipper.z_head = [] && se.se_zipper.z_path = ZTop -> *)
(*        next Match se *)
(*     | Anchor Start -> next NoMatch se *)

(*     | Anchor End when *)
(*            se.se_zipper.z_tail = [] && se.se_zipper.z_path = ZTop -> *)
(*        next Match se *)
(*     | Anchor End -> next NoMatch se *)
(*     | Seq [] -> next Match se *)
(*     | Seq (p::after) -> *)
(*        process_stmt { se with *)
(*                       se_pattern = p; *)
(*                       se_continuation = Cseq (after,se.se_continuation); *)
(*                     } *)

(*   and next m se = match se.se_continuation, m with *)
(*     | Ctop, Match -> Some se *)
(*     | Ctop, NoMatch -> None *)
(*     | Cnamed  *)


(*   and process_instr (ie : instr_engine) = *)

(* end *)
back to top