1structure HolKernel = 2struct 3 4 open Feedback Globals Lib Type Term Thm Theory 5 open Definition 6 7 8(*--------------------------------------------------------------------------- 9 Miscellaneous other stuff that builds on top of kernel facilities. 10 ---------------------------------------------------------------------------*) 11 12infixr -->; infix |->; 13 14local 15 val ERR = mk_HOL_ERR "HolKernel" 16in 17 18(*--------------------------------------------------------------------------- 19 General term operations 20 ---------------------------------------------------------------------------*) 21 22fun dest_monop c e M = 23 let 24 val (c1, N) = with_exn dest_comb M e 25 in 26 if same_const c c1 then N else raise e 27 end 28 29local 30 fun dest tm = 31 let 32 val (Rator, N) = dest_comb tm 33 val (c, M) = dest_comb Rator 34 in 35 (c, (M, N)) 36 end 37in 38 fun dest_binop c e tm = 39 let 40 val (c1, pair) = with_exn dest tm e 41 in 42 if same_const c c1 then pair else raise e 43 end 44end 45 46fun dest_triop p e M = 47 let 48 val (f, z) = with_exn dest_comb M e 49 val (x, y) = dest_binop p e f 50 in 51 (x, y, z) 52 end 53 54(*---------------------------------------------------------------------------*) 55(* Take a binder apart. Fails on paired binders. *) 56(*---------------------------------------------------------------------------*) 57 58local 59 fun dest M = let val (c, Rand) = dest_comb M in (c, dest_abs Rand) end 60in 61 fun dest_binder c e M = 62 let 63 val (c1, p) = with_exn dest M e 64 in 65 if same_const c c1 then p else raise e 66 end 67end 68 69local 70 fun dest M = 71 let val (Rator, Rand) = dest_comb M in (dest_thy_const Rator, Rand) end 72in 73 fun sdest_monop (name, thy) e M = 74 let 75 val ({Name, Thy, ...}, Rand) = with_exn dest M e 76 in 77 if Name = name andalso Thy = thy then Rand else raise e 78 end 79end 80 81local 82 fun dest tm = 83 let 84 val (Rator, N) = dest_comb tm 85 val (c, M) = dest_comb Rator 86 in 87 (dest_thy_const c, (M, N)) 88 end 89in 90 fun sdest_binop (name, thy) e tm = 91 let 92 val ({Name, Thy, ...}, pair) = with_exn dest tm e 93 in 94 if Name = name andalso Thy = thy then pair else raise e 95 end 96end 97 98local 99 fun dest M = 100 let val (c, Rand) = dest_comb M 101 in (dest_thy_const c, dest_abs Rand) 102 end 103in 104 fun sdest_binder (name, thy) e M = 105 let 106 val ({Name, Thy, ...}, p) = with_exn dest M e 107 in 108 if Name = name andalso Thy = thy then p else raise e 109 end 110end 111 112(* Breaks term down until binop no longer occurs at top level in result list *) 113 114fun strip_binop_opt dest = 115 let 116 fun strip A [] = rev A 117 | strip A (h :: t) = 118 case dest h of 119 NONE => strip (h :: A) t 120 | SOME (c1, c2) => strip A (c1 :: c2 :: t) 121 in 122 strip [] o Lib.list_of_singleton 123 end 124 125fun strip_binop dest = strip_binop_opt (total dest); 126 127(* For right-associative binary operators, 128 or such as dest_abs, SPEC_VAR, dom_rng, dest_imp. Tail recursive. *) 129 130local 131fun spine_binop' dest = 132 let 133 fun strip A tm = 134 case dest tm of 135 NONE => (tm, A) 136 | SOME (l, r) => strip (l :: A) r 137 in 138 strip [] 139 end 140in 141fun spine_binop dest tm = rev ((op ::) (spine_binop' dest tm)) ; 142 143fun strip_gen_left_opt dest t = 144 let val (tm, A) = spine_binop' dest t in (rev A, tm) end ; 145end (* local fun spine_binop' *) 146 147fun strip_gen_left dest = strip_gen_left_opt (total dest) ; 148 149(* For left-associative binary operators. Tail recursive *) 150 151fun strip_gen_right_opt dest = 152 let 153 fun strip A tm = 154 case dest tm of 155 NONE => (tm, A) 156 | SOME (l, r) => strip (r :: A) l 157 in 158 strip [] 159 end 160 161fun lspine_binop dest tm = (op ::) (strip_gen_right_opt dest tm) ; 162 163fun strip_gen_right dest = strip_gen_right_opt (total dest) ; 164 165(* For right-associative binary operators. Tail recursive. *) 166 167fun list_mk_rbinop mk_binop alist = 168 case List.rev alist of 169 [] => raise ERR "list_mk_rbinop" "empty list" 170 | h :: t => rev_itlist mk_binop t h 171 172(* For left-associative binary operators. Tail recursive. *) 173 174fun list_mk_lbinop _ [] = raise ERR "list_mk_lbinop" "empty list" 175 | list_mk_lbinop mk_binop (h :: t) = rev_itlist (C mk_binop) t h 176 177fun mk_binder c f (p as (Bvar, _)) = 178 mk_comb (inst [alpha |-> type_of Bvar] c, mk_abs p) 179 handle HOL_ERR {message, ...} => raise ERR f message 180 181fun list_mk_fun (dtys, rty) = List.foldr op--> rty dtys 182 183val strip_fun = 184 let 185 val dest = total dom_rng 186 fun strip acc ty = 187 case dest ty of 188 SOME (d, r) => strip (d :: acc) r 189 | NONE => (rev acc, ty) 190 in 191 strip [] 192 end 193 194val strip_comb = 195 let 196 val destc = total dest_comb 197 fun strip rands M = 198 case destc M of 199 NONE => (M, rands) 200 | SOME (Rator, Rand) => strip (Rand :: rands) Rator 201 in 202 strip [] 203 end 204 205fun dest_quadop c e tm = 206 case with_exn strip_comb tm e of 207 (t, [t1, t2, t3, t4]) => 208 if same_const t c then (t1, t2, t3, t4) else raise e 209 | _ => raise e 210 211local 212 val mk_aty = list_mk_rbinop (Lib.curry Type.-->) 213 val args = fst o strip_fun o Term.type_of 214in 215 fun list_mk_icomb tm xs = 216 let 217 val tyl = mk_aty (Lib.with_exn List.take (args tm, List.length xs) 218 (ERR "" "too many arguments")) 219 val tyr = mk_aty (List.map Term.type_of xs) 220 in 221 Term.list_mk_comb (Term.inst (Type.match_type tyl tyr) tm, xs) 222 end 223 handle HOL_ERR {message, ...} => raise ERR "list_mk_icomb" message 224 225 fun syntax_fns 226 {n: int, make: term -> 'a -> term, dest: term -> exn -> term -> 'b} 227 thy name = 228 let 229 val ERR = Feedback.mk_HOL_ERR (thy ^ "Syntax") 230 val tm = Term.prim_mk_const {Name = name, Thy = thy} 231 val () = 232 ignore (List.length (args tm) = n 233 orelse raise ERR "syntax_fns" "bad number of arguments") 234 val d = dest tm (ERR ("dest_" ^ name) "") 235 in 236 (tm, 237 fn v => Lib.with_exn (make tm) v (ERR ("mk_" ^ name) ""): term, 238 d: term -> 'b, 239 can d) 240 end 241end 242 243fun mk_monop tm = list_mk_icomb tm o Lib.list_of_singleton 244fun mk_binop tm = list_mk_icomb tm o Lib.list_of_pair 245fun mk_triop tm = list_mk_icomb tm o Lib.list_of_triple 246fun mk_quadop tm = list_mk_icomb tm o Lib.list_of_quadruple 247 248val syntax_fns1 = syntax_fns {n = 1, make = mk_monop, dest = dest_monop} 249val syntax_fns2 = syntax_fns {n = 2, make = mk_binop, dest = dest_binop} 250val syntax_fns3 = syntax_fns {n = 3, make = mk_triop, dest = dest_triop} 251val syntax_fns4 = syntax_fns {n = 4, make = mk_quadop, dest = dest_quadop} 252 253(*---------------------------------------------------------------------------* 254 * Used to implement natural deduction style discharging of hypotheses. All * 255 * hypotheses alpha-convertible to the dischargee are removed. * 256 *---------------------------------------------------------------------------*) 257 258fun disch (w, wl) = List.filter (not o Term.aconv w) wl 259 260(*---------------------------------------------------------------------------* 261 * Search a term for a sub-term satisfying the predicate P. If application * 262 * of P raises an exception, that propagates to the caller. Therefore, * 263 * P should be a total predicate: otherwise, the caller won't know whether * 264 * the search failed because the sought-for subterm is not there, or because * 265 * P failed. * 266 *---------------------------------------------------------------------------*) 267 268fun find_term P = 269 let 270 fun find_tm tm = 271 if P tm 272 then tm 273 else if is_abs tm 274 then find_tm (body tm) 275 else case Lib.total dest_comb tm of 276 SOME (Rator, Rand) => 277 (find_tm Rator handle HOL_ERR _ => find_tm Rand) 278 | NONE => raise ERR "find_term" "" 279 in 280 find_tm 281 end 282 283 284local 285 datatype action = SEARCH of term | POP 286in 287 fun gen_find_term f t = 288 let 289 fun search bvs actions = 290 case actions of 291 [] => NONE 292 | POP :: alist => search (tl bvs) alist 293 | SEARCH t :: alist => (case f (bvs, t) of 294 NONE => subterm bvs alist t 295 | x => x) 296 and subterm bvs alist t = 297 case dest_term t of 298 COMB (t1, t2) => search bvs (SEARCH t1 :: SEARCH t2 :: alist) 299 | LAMB (bv, t) => search (bv :: bvs) (SEARCH t :: POP :: alist) 300 | _ => search bvs alist 301 in 302 search [] [SEARCH t] 303 end 304 fun gen_find_terms f t = 305 let 306 fun search bvs actions acc = 307 case actions of 308 [] => acc 309 | POP :: alist => search (tl bvs) alist acc 310 | SEARCH t :: alist => 311 (case f (bvs, t) of 312 NONE => subterm bvs alist acc t 313 | SOME x => subterm bvs alist (x::acc) t) 314 and subterm bvs alist acc t = 315 case dest_term t of 316 COMB(t1, t2) => search bvs (SEARCH t1 :: SEARCH t2 :: alist) 317 acc 318 | LAMB (bv, t) => search (bv::bvs) (SEARCH t :: POP :: alist) acc 319 | _ => search bvs alist acc 320 in 321 search [] [SEARCH t] [] 322 end 323end (* local *) 324 325(* ---------------------------------------------------------------------- 326 bvk_find_term : 327 (term list * term -> bool) -> (term -> 'a) -> term -> 'a option 328 329 [bvk_find_term P k tm] searches tm for a sub-term satisfying P and 330 calls the continuation k on the first that it finds. If k 331 succeeds on this sub-term, the result is wrapped in SOME. If k 332 raises a HOL_ERR exception, control returns to bvk_find_term, 333 which continues to look for a sub-term satisfying P. Other 334 exceptions are returned to the caller. If there is no sub-term 335 that both satisfies P and which k operates on successfully, the 336 result is NONE. 337 338 The search order is top-down, left-to-right (i.e., rators of combs 339 are examined before rands). 340 341 As with find_term, P should be total. In addition, P is given not 342 just the sub-term of interest, but also the stack of bound 343 variables that have scope over the sub-term, with the innermost 344 bound variables appearing earlier in the list. 345 ---------------------------------------------------------------------- *) 346 347fun bvk_find_term P k = 348 gen_find_term (fn x => if P x then SOME (k (#2 x)) handle HOL_ERR _ => NONE 349 else NONE) 350 351(*--------------------------------------------------------------------------- 352 * find_terms: (term -> bool) -> term -> term list 353 * 354 * Find all subterms in a term that satisfy a given predicate p. 355 * 356 * Added TFM 88.03.31 357 *---------------------------------------------------------------------------*) 358 359fun find_terms P = 360 let 361 open Uref 362 val tms = Uref.new [] 363 fun find_tms tm = 364 (if P tm then tms := tm :: (!tms) else () 365 ; find_tms (body tm) 366 handle HOL_ERR _ => 367 case Lib.total dest_comb tm of 368 SOME (r1, r2) => (find_tms r1; find_tms r2) 369 | NONE => ()) 370 in 371 fn tm => 372 let 373 val r = (find_tms tm; (!tms)) 374 in 375 tms := []; r 376 end 377 end 378 379(* ---------------------------------------------------------------------- 380 find_maximal_terms[l] 381 382 finds sub-terms within a term, but doesn't look into sub-terms that 383 match the provided predicate. The find_maximal_termsl version 384 returns the terms as a list rather than a set. 385 ---------------------------------------------------------------------- *) 386 387fun find_maximal_terms P t = 388 let 389 fun recurse acc tlist = 390 case tlist of 391 [] => acc 392 | t :: ts => 393 if P t 394 then recurse (HOLset.add (acc, t)) ts 395 else case dest_term t of 396 COMB (f, x) => recurse acc (f :: x :: ts) 397 | LAMB (v, b) => recurse acc (b :: ts) 398 | _ => recurse acc ts 399 in 400 recurse empty_tmset [t] 401 end 402 403fun find_maximal_termsl P t = HOLset.listItems (find_maximal_terms P t) 404 405(* ---------------------------------------------------------------------- 406 term_size 407 408 Returns a term's size. There's no logical significance to this 409 number, but it can be useful. 410 ---------------------------------------------------------------------- *) 411 412fun term_size t = 413 let 414 fun recurse acc tlist = 415 case tlist of 416 [] => acc 417 | t :: ts => 418 (case dest_term t of 419 COMB (f, x) => recurse acc (f :: x :: ts) 420 | LAMB (v, b) => recurse (1 + acc) (b :: ts) 421 | _ => recurse (1 + acc) ts) 422 in 423 recurse 0 [t] 424 end 425 426(*--------------------------------------------------------------------------- 427 * Subst_occs 428 * Put a new variable in tm2 at designated (and free) occurrences of redex. 429 * Rebuilds the entire term. 430 *---------------------------------------------------------------------------*) 431 432local 433fun splice ({redex, ...}:{redex:term, residue:term}) v occs tm2 = 434 let fun graft (r as {occs=[], ...}) = r 435 | graft {tm, occs, count} = 436 if term_eq redex tm 437 then if (List.hd occs = count + 1) 438 then {tm=v, occs=List.tl occs, count=count+1} 439 else {tm=tm, occs=occs, count=count+1} 440 else if (is_comb tm) 441 then let val (Rator, Rand) = dest_comb tm 442 val {tm=Rator', occs=occs', count=count'} = 443 graft {tm=Rator, occs=occs, count=count} 444 val {tm=Rand', occs=occs'', count=count''} = 445 graft {tm=Rand, occs=occs', count=count'} 446 in {tm=mk_comb (Rator', Rand'), 447 occs=occs'', count=count''} 448 end 449 else if is_abs tm 450 then let val (Bvar, Body) = dest_abs tm 451 val {tm, count, occs} = 452 graft{tm=Body, count=count, occs=occs} 453 in {tm=mk_abs (Bvar, tm), 454 count=count, occs=occs} 455 end 456 else {tm=tm, occs=occs, count=count} 457 in #tm (graft {tm=tm2, occs=occs, count=0}) 458 end 459 460fun rev_itlist3 f L1 L2 L3 base_value = 461 let fun rev_it3 (a::rst1) (b::rst2) (c::rst3) base = 462 rev_it3 rst1 rst2 rst3 (f a b c base) 463 | rev_it3 [] [] [] base = base 464 | rev_it3 _ _ _ _ = raise ERR "rev_itlist3" 465 "not all lists have same size" 466 in rev_it3 L1 L2 L3 base_value 467 end 468 469val sort = Lib.sort (Lib.curry (op <=) : int -> int -> bool) 470in 471fun subst_occs occ_lists tm_subst tm = 472 let val occ_lists' = map sort occ_lists 473 val (new_vars, theta) = 474 Lib.itlist (fn {redex, residue} => fn (V, T) => 475 let val v = genvar (type_of redex) 476 in (v::V, (v |-> residue)::T) end) 477 tm_subst ([],[]) 478 val template = rev_itlist3 splice tm_subst new_vars occ_lists' tm 479 in subst theta template 480 end 481end 482 483(*--------------------------------------------------------------------------- 484 Higher order matching (from jrh via Michael Norrish - June 2001) 485 ---------------------------------------------------------------------------*) 486 487local 488 exception NOT_FOUND 489 fun find_residue red [] = raise NOT_FOUND 490 | find_residue red ({redex, residue}::rest) = 491 if aconv red redex then residue else find_residue red rest 492 fun find_residue_eq red [] = raise NOT_FOUND 493 | find_residue_eq red ({redex, residue}::rest) = 494 if red = redex then residue else find_residue_eq red rest 495 fun in_dom x [] = false 496 | in_dom x ({redex, residue}::rest) = aconv x redex orelse in_dom x rest 497 fun in_domeq x [] = false 498 | in_domeq x ({redex,residue}::rest) = x = redex orelse in_domeq x rest 499 500 (* for terms *) 501 fun safe_insert (n as {redex, residue}) l = 502 let 503 val z = find_residue redex l 504 in 505 if aconv residue z then l 506 else failwith "match: safe_insert" 507 end handle NOT_FOUND => n::l 508 509 fun safe_inserteq (n as {redex,residue}) l = 510 let 511 val z = find_residue redex l 512 in 513 if residue = z then l 514 else failwith "match: safe_insert" 515 end handle NOT_FOUND => n::l 516 val mk_dummy = let 517 val name = fst (dest_var (genvar Type.alpha)) 518 in fn ty => mk_var (name, ty) 519 end 520 521 522 fun term_pmatch lconsts env vtm ctm (sofar as (insts, homs)) = 523 if is_var vtm then let 524 val ctm' = find_residue vtm env 525 in 526 if aconv ctm' ctm then sofar else failwith "term_pmatch" 527 end handle NOT_FOUND => 528 if HOLset.member (lconsts, vtm) then 529 if aconv ctm vtm then sofar 530 else 531 failwith "term_pmatch: can't instantiate local constant" 532 else (safe_insert (vtm |-> ctm) insts, homs) 533 else if is_const vtm then let 534 val {Thy = vthy, Name = vname, Ty = vty} = dest_thy_const vtm 535 val {Thy = cthy, Name = cname, Ty = cty} = dest_thy_const ctm 536 in 537 if vname = cname andalso vthy = cthy then 538 if cty = vty then sofar 539 else (safe_insert (mk_dummy vty |-> mk_dummy cty) insts, homs) 540 else failwith "term_pmatch" 541 end 542 else if is_abs vtm then let 543 val (vv, vbod) = dest_abs vtm 544 val (cv, cbod) = dest_abs ctm 545 val (_, vty) = dest_var vv 546 val (_, cty) = dest_var cv 547 val sofar' = (safe_insert (mk_dummy vty |-> mk_dummy cty) insts, homs) 548 in 549 term_pmatch lconsts ((vv |-> cv)::env) vbod cbod sofar' 550 end 551 else let 552 val vhop = repeat rator vtm 553 in 554 if is_var vhop andalso not (HOLset.member (lconsts, vhop)) andalso 555 not (in_dom vhop env) 556 then let 557 val vty = type_of vtm 558 val cty = type_of ctm 559 val insts' = if vty = cty then insts 560 else safe_insert (mk_dummy vty |-> mk_dummy cty) insts 561 in 562 (insts', (env, ctm, vtm)::homs) 563 end 564 else let 565 val (lv, rv) = dest_comb vtm 566 val (lc, rc) = dest_comb ctm 567 val sofar' = term_pmatch lconsts env lv lc sofar 568 in 569 term_pmatch lconsts env rv rc sofar' 570 end 571 end 572 573(* 574fun get_type_insts avoids L = 575 let val avtys = itlist (fn ty => fn (p,o) => (ty-->p, ty-->o)) 576 avoids (bool,bool) 577 val (pat,ob) = itlist (fn {redex,residue} => fn (pat,ob) => 578 (type_of redex-->pat, type_of residue-->ob)) 579 L avtys 580 581 in match_type pat ob 582 end 583 584fun get_type_insts avoids L = 585 let val tytheta = itlist (fn {redex,residue} => 586 match_type_in_context (snd (dest_var redex)) (type_of residue)) 587 L [] 588 in if null (intersect avoids (map #residue tytheta)) 589 then tytheta 590 else raise ERR "get_type_insts" "attempt to bind fixed type variable" 591 end 592*) 593fun get_type_insts avoids L (tyS, Id) = 594 itlist (fn {redex, residue} => fn Theta => 595 raw_match_type (snd (dest_var redex)) (type_of residue) Theta) 596 L (tyS, union avoids Id) 597 598fun separate_insts tyavoids insts = let 599 val (realinsts, patterns) = partition (is_var o #redex) insts 600 val betacounts = 601 if null patterns then [] 602 else 603 itlist (fn {redex = p, ...} => 604 fn sof => let 605 val (hop, args) = strip_comb p 606 in 607 safe_inserteq (hop |-> length args) sof 608 end handle HOL_ERR _ => 609 (HOL_WARNING "" "" 610 "Inconsistent patterning in h.o. match"; 611 sof)) 612 patterns [] 613 val tyins = get_type_insts tyavoids realinsts ([],[]) 614in 615 (betacounts, 616 mapfilter (fn {redex = x, residue = t} => let 617 val x' = let val (xn, xty) = dest_var x 618 in 619 mk_var (xn, type_subst (#1 tyins) xty) 620 end 621 in 622 if aconv t x' then failwith "" else {redex = x', residue = t} 623 end) realinsts, 624 tyins) 625end 626 627val tmmem = op_mem aconv 628fun tyenv_in_dom x (env, idlist) = mem x idlist orelse in_domeq x env 629fun tyenv_find_residue x (env, idlist) = if mem x idlist then x 630 else find_residue_eq x env 631fun tyenv_safe_insert (t as {redex, residue}) (E as (env, idlist)) = let 632 val existing = tyenv_find_residue redex E 633in 634 if existing = residue then E else failwith "Type bindings clash" 635end handle NOT_FOUND => if redex = residue then (env, redex::idlist) 636 else (t::env, idlist) 637 638fun beta_normalise0 t = let 639 val bn0 = beta_normalise0 640 fun bn1 t = case bn0 t of NONE => SOME t | x => x 641in 642 case dest_term t of 643 COMB (t1, t2) => let 644 in 645 case Lib.total beta_conv t of 646 NONE => let 647 in 648 case bn0 t1 of 649 NONE => Option.map (fn t2' => mk_comb (t1, t2')) (bn0 t2) 650 | SOME t1' => bn1 (mk_comb (t1', t2)) 651 end 652 | SOME t' => bn1 t' 653 end 654 | LAMB (v, t) => Option.map (fn t' => mk_abs (v, t')) (bn0 t) 655 | x => NONE 656end 657 658fun beta_normalise t = case beta_normalise0 t of NONE => t | SOME x => x 659 660fun all_abconv [] [] = true 661 | all_abconv [] _ = false 662 | all_abconv _ [] = false 663 | all_abconv (h1::t1) (h2::t2) = 664 aconv (beta_normalise h1) (beta_normalise h2) andalso all_abconv t1 t2 665 666fun term_homatch tyavoids lconsts tyins (insts, homs) = let 667 (* local constants of both terms and types never change *) 668 val term_homatch = term_homatch tyavoids lconsts 669in 670 if null homs then insts 671 else let 672 val (env, ctm, vtm) = hd homs 673 in 674 if is_var vtm then 675 if aconv ctm vtm then term_homatch tyins (insts, tl homs) 676 else let 677 val newtyins = 678 tyenv_safe_insert (snd (dest_var vtm) |-> type_of ctm) tyins 679 val newinsts = (vtm |-> ctm)::insts 680 in 681 term_homatch newtyins (newinsts, tl homs) 682 end 683 else (* vtm not a var *) let 684 val (vhop, vargs) = strip_comb vtm 685 val afvs = free_varsl vargs 686 val inst_fn = Term.inst (fst tyins) 687 in 688 (let 689 val tmins = 690 map (fn a => 691 (inst_fn a |-> 692 (find_residue a env 693 handle NOT_FOUND => 694 find_residue a insts 695 handle NOT_FOUND => 696 if HOLset.member (lconsts, a) 697 then a 698 else failwith ""))) afvs 699 val pats0 = map inst_fn vargs 700 val pats = map (Term.subst tmins) pats0 701 val vhop' = inst_fn vhop 702 val ictm = list_mk_comb (vhop', pats) 703 val ni = let 704 val (chop, cargs) = strip_comb ctm 705 in 706 if all_abconv cargs pats then 707 if aconv chop vhop then insts 708 else safe_insert (vhop |-> chop) insts 709 else let 710 val ginsts = map (fn p => (p |-> 711 (if is_var p then p 712 else genvar (type_of p)))) 713 pats 714 val ctm' = Term.subst ginsts ctm 715 val gvs = map #residue ginsts 716 val abstm = list_mk_abs (gvs, ctm') 717 val vinsts = safe_insert (vhop |-> abstm) insts 718 val icpair = (list_mk_comb (vhop', gvs) |-> ctm') 719 in 720 icpair::vinsts 721 end 722 end 723 in 724 term_homatch tyins (ni, tl homs) 725 end) handle HOL_ERR _ => let 726 val (lc, rc) = dest_comb ctm 727 val (lv, rv) = dest_comb vtm 728 val pinsts_homs' = 729 term_pmatch lconsts env rv rc 730 (insts, (env, lc, lv)::(tl homs)) 731 val tyins' = 732 get_type_insts tyavoids 733 (fst pinsts_homs') 734 ([], []) 735 in 736 term_homatch tyins' pinsts_homs' 737 end 738 end 739 end 740end 741 742in 743 744fun ho_match_term0 tyavoids lconsts vtm ctm = let 745 val pinsts_homs = term_pmatch lconsts [] vtm ctm ([], []) 746 val tyins = get_type_insts tyavoids (fst pinsts_homs) ([], []) 747 val insts = term_homatch tyavoids lconsts tyins pinsts_homs 748in 749 separate_insts tyavoids insts 750end 751 752fun ho_match_term tyavoids lconsts vtm ctm = let 753 val (bcs, tmins, tyins) = ho_match_term0 tyavoids lconsts vtm ctm 754in 755 (tmins, #1 tyins) 756end handle e => raise (wrap_exn "HolKernel" "ho_match_term" e) 757 758end (* local *) 759 760val sort_vars = 761 Portable.pull_prefix o map (fn n => equal n o #1 o dest_var) 762 763end 764end 765