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 |