src/Pure/pattern.ML
changeset 15797 a63605582573
parent 15574 b1d1b5bfc464
child 16651 40b96a501773
equal deleted inserted replaced
15796:348ce23d2fc2 15797:a63605582573
    20   val eta_contract      : term -> term
    20   val eta_contract      : term -> term
    21   val eta_long          : typ list -> term -> term
    21   val eta_long          : typ list -> term -> term
    22   val beta_eta_contract : term -> term
    22   val beta_eta_contract : term -> term
    23   val eta_contract_atom : term -> term
    23   val eta_contract_atom : term -> term
    24   val match             : Type.tsig -> term * term
    24   val match             : Type.tsig -> term * term
    25                           -> (indexname*typ)list * (indexname*term)list
    25                           -> Type.tyenv * Envir.tenv
    26   val first_order_match : Type.tsig -> term * term
    26   val first_order_match : Type.tsig -> term * term
    27                           -> (indexname*typ)list * (indexname*term)list
    27                           -> Type.tyenv * Envir.tenv
    28   val matches           : Type.tsig -> term * term -> bool
    28   val matches           : Type.tsig -> term * term -> bool
    29   val matches_subterm   : Type.tsig -> term * term -> bool
    29   val matches_subterm   : Type.tsig -> term * term -> bool
    30   val unify             : Sign.sg * Envir.env * (term * term)list -> Envir.env
    30   val unify             : Sign.sg * Envir.env * (term * term)list -> Envir.env
    31   val first_order       : term -> bool
    31   val first_order       : term -> bool
    32   val pattern           : term -> bool
    32   val pattern           : term -> bool
    70 
    70 
    71 fun clashB binders i s =
    71 fun clashB binders i s =
    72   if !trace_unify_fail then clash (boundVar binders i) s
    72   if !trace_unify_fail then clash (boundVar binders i) s
    73   else ()
    73   else ()
    74 
    74 
    75 fun proj_fail sg (env,binders,F,is,t) =
    75 fun proj_fail sg (env,binders,F,_,is,t) =
    76   if !trace_unify_fail
    76   if !trace_unify_fail
    77   then let val f = Syntax.string_of_vname F
    77   then let val f = Syntax.string_of_vname F
    78            val xs = bnames binders is
    78            val xs = bnames binders is
    79            val u = string_of_term sg env binders t
    79            val u = string_of_term sg env binders t
    80            val ys = bnames binders (loose_bnos t \\ is)
    80            val ys = bnames binders (loose_bnos t \\ is)
    92                   "\nCannot unify!\n")
    92                   "\nCannot unify!\n")
    93        end
    93        end
    94   else ()
    94   else ()
    95 
    95 
    96 fun occurs(F,t,env) =
    96 fun occurs(F,t,env) =
    97     let fun occ(Var(G,_))   = (case Envir.lookup(env,G) of
    97     let fun occ(Var (G, T))   = (case Envir.lookup (env, (G, T)) of
    98                                  SOME(t) => occ t
    98                                  SOME(t) => occ t
    99                                | NONE    => F=G)
    99                                | NONE    => F=G)
   100           | occ(t1$t2)      = occ t1 orelse occ t2
   100           | occ(t1$t2)      = occ t1 orelse occ t2
   101           | occ(Abs(_,_,t)) = occ t
   101           | occ(Abs(_,_,t)) = occ t
   102           | occ _           = false
   102           | occ _           = false
   151 
   151 
   152 fun mkhnf (binders,is,G,js) = mkabs (binders, is, app(G,js));
   152 fun mkhnf (binders,is,G,js) = mkabs (binders, is, app(G,js));
   153 
   153 
   154 fun mknewhnf(env,binders,is,F as (a,_),T,js) =
   154 fun mknewhnf(env,binders,is,F as (a,_),T,js) =
   155   let val (env',G) = Envir.genvar a (env,type_of_G env (T,length is,js))
   155   let val (env',G) = Envir.genvar a (env,type_of_G env (T,length is,js))
   156   in Envir.update((F,mkhnf(binders,is,G,js)),env') end;
   156   in Envir.update (((F, T), mkhnf (binders, is, G, js)), env') end;
   157 
   157 
   158 
   158 
   159 (* mk_proj_list(is) = [ |is| - k | 1 <= k <= |is| and is[k] >= 0 ] *)
   159 (* mk_proj_list(is) = [ |is| - k | 1 <= k <= |is| and is[k] >= 0 ] *)
   160 fun mk_proj_list is =
   160 fun mk_proj_list is =
   161     let fun mk(i::is,j) = if isSome i then j :: mk(is,j-1) else mk(is,j-1)
   161     let fun mk(i::is,j) = if isSome i then j :: mk(is,j-1) else mk(is,j-1)
   184                           val ks = mk_proj_list js';
   184                           val ks = mk_proj_list js';
   185                           val ls = List.mapPartial I js'
   185                           val ls = List.mapPartial I js'
   186                           val Hty = type_of_G env (Fty,length js,ks)
   186                           val Hty = type_of_G env (Fty,length js,ks)
   187                           val (env',H) = Envir.genvar a (env,Hty)
   187                           val (env',H) = Envir.genvar a (env,Hty)
   188                           val env'' =
   188                           val env'' =
   189                                 Envir.update((F,mkhnf(binders,js,H,ks)),env')
   189                             Envir.update (((F, Fty), mkhnf (binders, js, H, ks)), env')
   190                       in (app(H,ls),env'') end
   190                       in (app(H,ls),env'') end
   191                  | _  => raise Pattern))
   191                  | _  => raise Pattern))
   192         and prs(s::ss,env,d,binders) =
   192         and prs(s::ss,env,d,binders) =
   193               let val (s',env1) = pr(s,env,d,binders)
   193               let val (s',env1) = pr(s,env,d,binders)
   194                   val (ss',env2) = prs(ss,env1,d,binders)
   194                   val (ss',env2) = prs(ss,env1,d,binders)
   214 
   214 
   215 fun flexflex2(env,binders,F,Fty,is,G,Gty,js) =
   215 fun flexflex2(env,binders,F,Fty,is,G,Gty,js) =
   216   let fun ff(F,Fty,is,G as (a,_),Gty,js) =
   216   let fun ff(F,Fty,is,G as (a,_),Gty,js) =
   217             if js subset_int is
   217             if js subset_int is
   218             then let val t= mkabs(binders,is,app(Var(G,Gty),map (idx is) js))
   218             then let val t= mkabs(binders,is,app(Var(G,Gty),map (idx is) js))
   219                  in Envir.update((F,t),env) end
   219                  in Envir.update (((F, Fty), t), env) end
   220             else let val ks = is inter_int js
   220             else let val ks = is inter_int js
   221                      val Hty = type_of_G env (Fty,length is,map (idx is) ks)
   221                      val Hty = type_of_G env (Fty,length is,map (idx is) ks)
   222                      val (env',H) = Envir.genvar a (env,Hty)
   222                      val (env',H) = Envir.genvar a (env,Hty)
   223                      fun lam(is) = mkabs(binders,is,app(H,map (idx is) ks));
   223                      fun lam(is) = mkabs(binders,is,app(H,map (idx is) ks));
   224                  in Envir.update((G,lam js), Envir.update((F,lam is),env'))
   224                  in Envir.update (((G, Gty), lam js), Envir.update (((F, Fty), lam is), env'))
   225                  end;
   225                  end;
   226   in if xless(G,F) then ff(F,Fty,is,G,Gty,js) else ff(G,Gty,js,F,Fty,is) end
   226   in if xless(G,F) then ff(F,Fty,is,G,Gty,js) else ff(G,Gty,js,F,Fty,is) end
   227 
   227 
   228 fun unify_types sg (T,U, env as Envir.Envir{asol,iTs,maxidx}) =
   228 fun unify_types sg (T,U, env as Envir.Envir{asol,iTs,maxidx}) =
   229   if T=U then env
   229   if T=U then env
   241 
   241 
   242 and cases sg (binders,env,(s,t)) = case (strip_comb s,strip_comb t) of
   242 and cases sg (binders,env,(s,t)) = case (strip_comb s,strip_comb t) of
   243        ((Var(F,Fty),ss),(Var(G,Gty),ts)) =>
   243        ((Var(F,Fty),ss),(Var(G,Gty),ts)) =>
   244          if F = G then flexflex1(env,binders,F,Fty,ints_of' env ss,ints_of' env ts)
   244          if F = G then flexflex1(env,binders,F,Fty,ints_of' env ss,ints_of' env ts)
   245                   else flexflex2(env,binders,F,Fty,ints_of' env ss,G,Gty,ints_of' env ts)
   245                   else flexflex2(env,binders,F,Fty,ints_of' env ss,G,Gty,ints_of' env ts)
   246       | ((Var(F,_),ss),_)             => flexrigid sg (env,binders,F,ints_of' env ss,t)
   246       | ((Var(F,Fty),ss),_)           => flexrigid sg (env,binders,F,Fty,ints_of' env ss,t)
   247       | (_,(Var(F,_),ts))             => flexrigid sg (env,binders,F,ints_of' env ts,s)
   247       | (_,(Var(F,Fty),ts))           => flexrigid sg (env,binders,F,Fty,ints_of' env ts,s)
   248       | ((Const c,ss),(Const d,ts))   => rigidrigid sg (env,binders,c,d,ss,ts)
   248       | ((Const c,ss),(Const d,ts))   => rigidrigid sg (env,binders,c,d,ss,ts)
   249       | ((Free(f),ss),(Free(g),ts))   => rigidrigid sg (env,binders,f,g,ss,ts)
   249       | ((Free(f),ss),(Free(g),ts))   => rigidrigid sg (env,binders,f,g,ss,ts)
   250       | ((Bound(i),ss),(Bound(j),ts)) => rigidrigidB sg (env,binders,i,j,ss,ts)
   250       | ((Bound(i),ss),(Bound(j),ts)) => rigidrigidB sg (env,binders,i,j,ss,ts)
   251       | ((Abs(_),_),_)                => raise Pattern
   251       | ((Abs(_),_),_)                => raise Pattern
   252       | (_,(Abs(_),_))                => raise Pattern
   252       | (_,(Abs(_),_))                => raise Pattern
   264 
   264 
   265 and rigidrigidB sg (env,binders,i,j,ss,ts) =
   265 and rigidrigidB sg (env,binders,i,j,ss,ts) =
   266      if i <> j then (clashBB binders i j; raise Unif)
   266      if i <> j then (clashBB binders i j; raise Unif)
   267      else Library.foldl (unif sg binders) (env ,ss~~ts)
   267      else Library.foldl (unif sg binders) (env ,ss~~ts)
   268 
   268 
   269 and flexrigid sg (params as (env,binders,F,is,t)) =
   269 and flexrigid sg (params as (env,binders,F,Fty,is,t)) =
   270       if occurs(F,t,env) then (ocheck_fail sg (F,t,binders,env); raise Unif)
   270       if occurs(F,t,env) then (ocheck_fail sg (F,t,binders,env); raise Unif)
   271       else (let val (u,env') = proj(t,env,binders,is)
   271       else (let val (u,env') = proj(t,env,binders,is)
   272             in Envir.update((F,mkabs(binders,is,u)),env') end
   272             in Envir.update (((F, Fty), mkabs (binders, is, u)), env') end
   273             handle Unif => (proj_fail sg params; raise Unif));
   273             handle Unif => (proj_fail sg params; raise Unif));
   274 
   274 
   275 fun unify(sg,env,tus) = Library.foldl (unif sg []) (env,tus);
   275 fun unify(sg,env,tus) = Library.foldl (unif sg []) (env,tus);
   276 
   276 
   277 
   277 
   356 fun fomatch tsig =
   356 fun fomatch tsig =
   357   let
   357   let
   358     fun mtch (instsp as (tyinsts,insts)) = fn
   358     fun mtch (instsp as (tyinsts,insts)) = fn
   359         (Var(ixn,T), t)  =>
   359         (Var(ixn,T), t)  =>
   360           if loose_bvar(t,0) then raise MATCH
   360           if loose_bvar(t,0) then raise MATCH
   361           else (case assoc_string_int(insts,ixn) of
   361           else (case Envir.lookup' (instsp, (ixn, T)) of
   362                   NONE => (typ_match tsig (tyinsts, (T, fastype_of t)),
   362                   NONE => (typ_match tsig (tyinsts, (T, fastype_of t)),
   363                            (ixn,t)::insts)
   363                            Vartab.update_new ((ixn, (T, t)), insts))
   364                 | SOME u => if t aeconv u then instsp else raise MATCH)
   364                 | SOME u => if t aeconv u then instsp else raise MATCH)
   365       | (Free (a,T), Free (b,U)) =>
   365       | (Free (a,T), Free (b,U)) =>
   366           if a=b then (typ_match tsig (tyinsts,(T,U)), insts) else raise MATCH
   366           if a=b then (typ_match tsig (tyinsts,(T,U)), insts) else raise MATCH
   367       | (Const (a,T), Const (b,U))  =>
   367       | (Const (a,T), Const (b,U))  =>
   368           if a=b then (typ_match tsig (tyinsts,(T,U)), insts) else raise MATCH
   368           if a=b then (typ_match tsig (tyinsts,(T,U)), insts) else raise MATCH
   372       | (f$t, g$u) => mtch (mtch instsp (f,g)) (t, u)
   372       | (f$t, g$u) => mtch (mtch instsp (f,g)) (t, u)
   373       | (t, Abs(_,U,u))  =>  mtch instsp ((incr t)$(Bound 0), u)
   373       | (t, Abs(_,U,u))  =>  mtch instsp ((incr t)$(Bound 0), u)
   374       | _ => raise MATCH
   374       | _ => raise MATCH
   375   in mtch end;
   375   in mtch end;
   376 
   376 
   377 fun first_order_match tsig = apfst Vartab.dest o fomatch tsig (Vartab.empty, []);
   377 fun first_order_match tsig = fomatch tsig (Vartab.empty, Vartab.empty);
   378 
   378 
   379 (* Matching of higher-order patterns *)
   379 (* Matching of higher-order patterns *)
   380 
   380 
   381 fun match_bind(itms,binders,ixn,is,t) =
   381 fun match_bind(itms,binders,ixn,T,is,t) =
   382   let val js = loose_bnos t
   382   let val js = loose_bnos t
   383   in if null is
   383   in if null is
   384      then if null js then (ixn,t)::itms else raise MATCH
   384      then if null js then Vartab.update_new ((ixn, (T, t)), itms) else raise MATCH
   385      else if js subset_int is
   385      else if js subset_int is
   386           then let val t' = if downto0(is,length binders - 1) then t
   386           then let val t' = if downto0(is,length binders - 1) then t
   387                             else mapbnd (idx is) t
   387                             else mapbnd (idx is) t
   388                in (ixn, mkabs(binders,is,t')) :: itms end
   388                in Vartab.update_new ((ixn, (T, mkabs (binders, is, t'))), itms) end
   389           else raise MATCH
   389           else raise MATCH
   390   end;
   390   end;
   391 
   391 
   392 fun match tsg (po as (pat,obj)) =
   392 fun match tsg (po as (pat,obj)) =
   393 let
   393 let
   395   fun mtch binders (env as (iTs,itms),(pat,obj)) =
   395   fun mtch binders (env as (iTs,itms),(pat,obj)) =
   396     case pat of
   396     case pat of
   397       Abs(ns,Ts,ts) =>
   397       Abs(ns,Ts,ts) =>
   398         (case obj of
   398         (case obj of
   399            Abs(nt,Tt,tt) => mtch ((nt,Tt)::binders) (env,(ts,tt))
   399            Abs(nt,Tt,tt) => mtch ((nt,Tt)::binders) (env,(ts,tt))
   400          | _ => let val Tt = typ_subst_TVars_Vartab iTs Ts
   400          | _ => let val Tt = Envir.typ_subst_TVars iTs Ts
   401                 in mtch((ns,Tt)::binders)(env,(ts,(incr obj)$Bound(0))) end)
   401                 in mtch((ns,Tt)::binders)(env,(ts,(incr obj)$Bound(0))) end)
   402     | _ => (case obj of
   402     | _ => (case obj of
   403               Abs(nt,Tt,tt) =>
   403               Abs(nt,Tt,tt) =>
   404                 mtch((nt,Tt)::binders)(env,((incr pat)$Bound(0),tt))
   404                 mtch((nt,Tt)::binders)(env,((incr pat)$Bound(0),tt))
   405             | _ => cases(binders,env,pat,obj))
   405             | _ => cases(binders,env,pat,obj))
   410               Library.foldl (mtch binders) ((iTs,itms), pargs~~oargs)
   410               Library.foldl (mtch binders) ((iTs,itms), pargs~~oargs)
   411         fun rigrig2((a,Ta),(b,Tb),oargs) =
   411         fun rigrig2((a,Ta),(b,Tb),oargs) =
   412               if a<> b then raise MATCH
   412               if a<> b then raise MATCH
   413               else rigrig1(typ_match tsg (iTs,(Ta,Tb)), oargs)
   413               else rigrig1(typ_match tsg (iTs,(Ta,Tb)), oargs)
   414     in case ph of
   414     in case ph of
   415          Var(ixn,_) =>
   415          Var(ixn,T) =>
   416            let val is = ints_of pargs
   416            let val is = ints_of pargs
   417            in case assoc_string_int(itms,ixn) of
   417            in case Envir.lookup' (env, (ixn, T)) of
   418                 NONE => (iTs,match_bind(itms,binders,ixn,is,obj))
   418                 NONE => (iTs,match_bind(itms,binders,ixn,T,is,obj))
   419               | SOME u => if obj aeconv (red u is []) then env
   419               | SOME u => if obj aeconv (red u is []) then env
   420                           else raise MATCH
   420                           else raise MATCH
   421            end
   421            end
   422        | _ =>
   422        | _ =>
   423            let val (oh,oargs) = strip_comb obj
   423            let val (oh,oargs) = strip_comb obj
   433     end;
   433     end;
   434 
   434 
   435   val pT = fastype_of pat
   435   val pT = fastype_of pat
   436   and oT = fastype_of obj
   436   and oT = fastype_of obj
   437   val iTs = typ_match tsg (Vartab.empty, (pT,oT))
   437   val iTs = typ_match tsg (Vartab.empty, (pT,oT))
   438   val insts2 = (iTs,[])
   438   val insts2 = (iTs, Vartab.empty)
   439 
   439 
   440 in apfst Vartab.dest (mtch [] (insts2, po)
   440 in mtch [] (insts2, po)
   441    handle Pattern => fomatch tsg insts2 po)
   441    handle Pattern => fomatch tsg insts2 po
   442 end;
   442 end;
   443 
   443 
   444 (*Predicate: does the pattern match the object?*)
   444 (*Predicate: does the pattern match the object?*)
   445 fun matches tsig po = (match tsig po; true) handle MATCH => false;
   445 fun matches tsig po = (match tsig po; true) handle MATCH => false;
   446 
   446 
   484         val t' = subst_bound (Free (x', T), t);
   484         val t' = subst_bound (Free (x', T), t);
   485       in (fn u => Abs (x, T, abstract_over (Free (x', T), u)), t') end;
   485       in (fn u => Abs (x, T, abstract_over (Free (x', T), u)), t') end;
   486 
   486 
   487     fun match_rew tm (tm1, tm2) =
   487     fun match_rew tm (tm1, tm2) =
   488       let val rtm = getOpt (Term.rename_abs tm1 tm tm2, tm2)
   488       let val rtm = getOpt (Term.rename_abs tm1 tm tm2, tm2)
   489       in SOME (subst_vars (match tsig (tm1, tm)) rtm, rtm)
   489       in SOME (Envir.subst_vars (match tsig (tm1, tm)) rtm, rtm)
   490         handle MATCH => NONE
   490         handle MATCH => NONE
   491       end;
   491       end;
   492 
   492 
   493     fun rew (Abs (_, _, body) $ t) = SOME (subst_bound (t, body), skel0)
   493     fun rew (Abs (_, _, body) $ t) = SOME (subst_bound (t, body), skel0)
   494       | rew tm = (case get_first (match_rew tm) rules of
   494       | rew tm = (case get_first (match_rew tm) rules of