src/Pure/unify.ML
changeset 48263 94a7dc2276e4
parent 48262 a0d8abca8d7a
child 51700 c8f2bad67dbb
equal deleted inserted replaced
48262:a0d8abca8d7a 48263:94a7dc2276e4
   271   Does not perform assignments for flex-flex pairs:
   271   Does not perform assignments for flex-flex pairs:
   272     may create nonrigid paths, which prevent other assignments.
   272     may create nonrigid paths, which prevent other assignments.
   273   Does not even identify Vars in dpairs such as ?a =?= ?b; an attempt to
   273   Does not even identify Vars in dpairs such as ?a =?= ?b; an attempt to
   274     do so caused numerous problems with no compensating advantage.
   274     do so caused numerous problems with no compensating advantage.
   275 *)
   275 *)
   276 fun SIMPL0 thy (dp0, (env,flexflex,flexrigid)) : Envir.env * dpair list * dpair list =
   276 fun SIMPL0 thy dp0 (env,flexflex,flexrigid) : Envir.env * dpair list * dpair list =
   277   let
   277   let
   278     val (dp as (rbinder, t, u), env) = head_norm_dpair thy (env, dp0);
   278     val (dp as (rbinder, t, u), env) = head_norm_dpair thy (env, dp0);
   279     fun SIMRANDS (f $ t, g $ u, env) =
   279     fun SIMRANDS (f $ t, g $ u, env) =
   280           SIMPL0 thy ((rbinder, t, u), SIMRANDS (f, g, env))
   280           SIMPL0 thy (rbinder, t, u) (SIMRANDS (f, g, env))
   281       | SIMRANDS (t as _$_, _, _) =
   281       | SIMRANDS (t as _$_, _, _) =
   282           raise TERM ("SIMPL: operands mismatch", [t, u])
   282           raise TERM ("SIMPL: operands mismatch", [t, u])
   283       | SIMRANDS (t, u as _ $ _, _) =
   283       | SIMRANDS (t, u as _ $ _, _) =
   284           raise TERM ("SIMPL: operands mismatch", [t, u])
   284           raise TERM ("SIMPL: operands mismatch", [t, u])
   285       | SIMRANDS (_, _, env) = (env, flexflex, flexrigid);
   285       | SIMRANDS (_, _, env) = (env, flexflex, flexrigid);
   316 
   316 
   317 (*Recursion needed if any of the 'head variables' have been updated
   317 (*Recursion needed if any of the 'head variables' have been updated
   318   Clever would be to re-do just the affected dpairs*)
   318   Clever would be to re-do just the affected dpairs*)
   319 fun SIMPL thy (env,dpairs) : Envir.env * dpair list * dpair list =
   319 fun SIMPL thy (env,dpairs) : Envir.env * dpair list * dpair list =
   320   let
   320   let
   321     val all as (env', flexflex, flexrigid) = List.foldr (SIMPL0 thy) (env, [], []) dpairs;
   321     val all as (env', flexflex, flexrigid) = fold_rev (SIMPL0 thy) dpairs (env, [], []);
   322     val dps = flexrigid @ flexflex;
   322     val dps = flexrigid @ flexflex;
   323   in
   323   in
   324     if exists (fn (_, t, u) => changed (env', t) orelse changed (env', u)) dps
   324     if exists (fn (_, t, u) => changed (env', t) orelse changed (env', u)) dps
   325     then SIMPL thy (env', dps) else all
   325     then SIMPL thy (env', dps) else all
   326   end;
   326   end;
   494       | change lev (t $ u) = change lev t $ change lev u
   494       | change lev (t $ u) = change lev t $ change lev u
   495       | change lev t = t;
   495       | change lev t = t;
   496   in change 0 end;
   496   in change 0 end;
   497 
   497 
   498 (*Change indices, delete the argument if it contains a banned Bound*)
   498 (*Change indices, delete the argument if it contains a banned Bound*)
   499 fun change_arg banned ({j, t, T}, args) : flarg list =
   499 fun change_arg banned {j, t, T} args : flarg list =
   500   if rigid_bound (0, banned) t then args  (*delete argument!*)
   500   if rigid_bound (0, banned) t then args  (*delete argument!*)
   501   else {j = j, t = change_bnos banned t, T = T} :: args;
   501   else {j = j, t = change_bnos banned t, T = T} :: args;
   502 
   502 
   503 
   503 
   504 (*Sort the arguments to create assignments if possible:
   504 (*Sort the arguments to create assignments if possible:
   526 fun clean_term banned (env,t) =
   526 fun clean_term banned (env,t) =
   527   let
   527   let
   528     val (Var (v, T), ts) = strip_comb t;
   528     val (Var (v, T), ts) = strip_comb t;
   529     val (Ts, U) = strip_type env T
   529     val (Ts, U) = strip_type env T
   530     and js = length ts - 1  downto 0;
   530     and js = length ts - 1  downto 0;
   531     val args = sort_args (List.foldr (change_arg banned) [] (flexargs (js, ts, Ts)))
   531     val args = sort_args (fold_rev (change_arg banned) (flexargs (js, ts, Ts)) [])
   532     val ts' = map #t args;
   532     val ts' = map #t args;
   533   in
   533   in
   534     if decreasing (length Ts) args then (env, (list_comb (Var (v, T), ts')))
   534     if decreasing (length Ts) args then (env, (list_comb (Var (v, T), ts')))
   535     else
   535     else
   536       let
   536       let
   577 
   577 
   578 (*IF the flex-flex dpair is an assignment THEN do it  ELSE  put in tpairs
   578 (*IF the flex-flex dpair is an assignment THEN do it  ELSE  put in tpairs
   579   eliminates trivial tpairs like t=t, as well as repeated ones
   579   eliminates trivial tpairs like t=t, as well as repeated ones
   580   trivial tpairs can easily escape SIMPL:  ?A=t, ?A=?B, ?B=t gives t=t
   580   trivial tpairs can easily escape SIMPL:  ?A=t, ?A=?B, ?B=t gives t=t
   581   Resulting tpairs MAY NOT be in normal form:  assignments may occur here.*)
   581   Resulting tpairs MAY NOT be in normal form:  assignments may occur here.*)
   582 fun add_ffpair thy ((rbinder,t0,u0), (env,tpairs)) : Envir.env * (term * term) list =
   582 fun add_ffpair thy (rbinder,t0,u0) (env,tpairs) : Envir.env * (term * term) list =
   583   let
   583   let
   584     val t = Envir.norm_term env t0
   584     val t = Envir.norm_term env t0
   585     and u = Envir.norm_term env u0;
   585     and u = Envir.norm_term env u0;
   586   in
   586   in
   587     (case (head_of t, head_of u) of
   587     (case (head_of t, head_of u) of
   625            (if tdepth > trace_bnd andalso trace_smp
   625            (if tdepth > trace_bnd andalso trace_smp
   626             then print_dpairs thy "Enter SIMPL" (env, dpairs) else ();
   626             then print_dpairs thy "Enter SIMPL" (env, dpairs) else ();
   627             SIMPL thy (env, dpairs));
   627             SIMPL thy (env, dpairs));
   628         in
   628         in
   629           (case flexrigid of
   629           (case flexrigid of
   630             [] => SOME (List.foldr (add_ffpair thy) (env', []) flexflex, reseq)
   630             [] => SOME (fold_rev (add_ffpair thy) flexflex (env', []), reseq)
   631           | dp :: frigid' =>
   631           | dp :: frigid' =>
   632               if tdepth > search_bnd then
   632               if tdepth > search_bnd then
   633                 (warning "Unification bound exceeded"; Seq.pull reseq)
   633                 (warning "Unification bound exceeded"; Seq.pull reseq)
   634               else
   634               else
   635                (if tdepth > trace_bnd then
   635                (if tdepth > trace_bnd then
   662   Unfortunately, unifies ?f(t,u) with ?g(t,u) by ?f, ?g -> %(x,y)?a,
   662   Unfortunately, unifies ?f(t,u) with ?g(t,u) by ?f, ?g -> %(x,y)?a,
   663   though just ?g->?f is a more general unifier.
   663   though just ?g->?f is a more general unifier.
   664   Unlike Huet (1975), does not smash together all variables of same type --
   664   Unlike Huet (1975), does not smash together all variables of same type --
   665     requires more work yet gives a less general unifier (fewer variables).
   665     requires more work yet gives a less general unifier (fewer variables).
   666   Handles ?f(t1...rm) with ?f(u1...um) to avoid multiple updates. *)
   666   Handles ?f(t1...rm) with ?f(u1...um) to avoid multiple updates. *)
   667 fun smash_flexflex1 ((t, u), env) : Envir.env =
   667 fun smash_flexflex1 (t, u) env : Envir.env =
   668   let
   668   let
   669     val vT as (v, T) = var_head_of (env, t)
   669     val vT as (v, T) = var_head_of (env, t)
   670     and wU as (w, U) = var_head_of (env, u);
   670     and wU as (w, U) = var_head_of (env, u);
   671     val (env', var) = Envir.genvar (#1 v) (env, body_type env T);
   671     val (env', var) = Envir.genvar (#1 v) (env, body_type env T);
   672     val env'' = Envir.vupdate ((wU, type_abs (env', U, var)), env');
   672     val env'' = Envir.vupdate ((wU, type_abs (env', U, var)), env');
   676   end;
   676   end;
   677 
   677 
   678 
   678 
   679 (*Smash all flex-flexpairs.  Should allow selection of pairs by a predicate?*)
   679 (*Smash all flex-flexpairs.  Should allow selection of pairs by a predicate?*)
   680 fun smash_flexflex (env, tpairs) : Envir.env =
   680 fun smash_flexflex (env, tpairs) : Envir.env =
   681   List.foldr smash_flexflex1 env tpairs;
   681   fold_rev smash_flexflex1 tpairs env;
   682 
   682 
   683 (*Returns unifiers with no remaining disagreement pairs*)
   683 (*Returns unifiers with no remaining disagreement pairs*)
   684 fun smash_unifiers thy tus env =
   684 fun smash_unifiers thy tus env =
   685   Seq.map smash_flexflex (unifiers (thy, env, tus));
   685   Seq.map smash_flexflex (unifiers (thy, env, tus));
   686 
   686