1signature patternMatchesLib = 2sig 3 include Abbrev 4 type ssfrag = simpLib.ssfrag 5 6 (********************************) 7 (* parsing *) 8 (********************************) 9 10 (* ENABLE_PMATCH_CASES() turns on parsing for 11 PMATCH style case expressions. After calling it 12 expressions like `case ... of ...` are not parsed 13 to decision trees any more, but to PMATCH expressions. 14 Decision tree case expressions are afterwards available 15 via `dtcase ... of ...`. *) 16 val ENABLE_PMATCH_CASES : unit -> unit 17 18 19 (********************************) 20 (* Naming conventions *) 21 (********************************) 22 23 (* Many PMATCH related tools need to prove various forms of 24 preconditions, in particular they need to prove that certain 25 patterns are injective or don't overlap. For this they need 26 information about the used constructors, in particular 27 injectivity theorems about the used constructors and theorems 28 about the distinctiveness of constructors. For most conversions 29 there are therefore 4 forms: 30 31 XXX_CONV : conv 32 33 uses a default set of theorem for proving preconditions enriched 34 with information from TypeBase. 35 36 XXX_CONV_GEN : ssfrag list -> conv 37 38 additionally uses the given list of ssfrags for proving preconditions. 39 40 XXX_ss : ssfrag 41 42 uses the default set + the simplifier using it as a callback to prove 43 preconditions. 44 45 XXX_ss_GEN : ssfrag list -> ssfrag 46 47 uses additionally the given list of ssfrags. 48 *) 49 50 51 (********************************) 52 (* Normalise PMATCH-terms *) 53 (********************************) 54 55 (* remove unused pattern variables *) 56 val PMATCH_CLEANUP_PVARS_CONV : conv 57 58 (* Use same variable names for pattern, guard and rhs *) 59 val PMATCH_FORCE_SAME_VARS_CONV : conv 60 61 (* Rename pattern variables unused in guard and rhs into 62 wildcards. *) 63 val PMATCH_INTRO_WILDCARDS_CONV : conv 64 65 (* Enforce each pattern to have the same number of columns, i.e. 66 explicit elements of a top-level tuple. *) 67 val PMATCH_EXPAND_COLS_CONV : conv 68 69 (* A combination of the normalisations above. *) 70 val PMATCH_NORMALISE_CONV : conv 71 val PMATCH_NORMALISE_ss : simpLib.ssfrag 72 73 (********************************) 74 (* Evaluate PMATCH-terms *) 75 (********************************) 76 77 (* PMATCH_CLEANUP_CONV removes rows that can't match, 78 removes all rows after the first matching row and 79 evaluates the whole expression in case the first row matches. *) 80 val PMATCH_CLEANUP_CONV : conv 81 val PMATCH_CLEANUP_CONV_GEN : ssfrag list -> conv 82 83 val PMATCH_CLEANUP_GEN_ss : ssfrag list -> ssfrag 84 val PMATCH_CLEANUP_ss : ssfrag 85 86 (* PMATCH_SIMP_COLS_CONV partially evaluates columns that all contain 87 either the same constructor or a variable. *) 88 val PMATCH_SIMP_COLS_CONV : conv 89 val PMATCH_SIMP_COLS_CONV_GEN : ssfrag list -> conv 90 91 (* A combination of PMATCH_CLEANUP_CONV and PMATCH_SIMP_COLS_CONV *) 92 val PMATCH_FAST_SIMP_CONV : conv 93 val PMATCH_FAST_SIMP_CONV_GEN : ssfrag list -> conv 94 val PMATCH_FAST_SIMP_GEN_ss : ssfrag list -> ssfrag 95 val PMATCH_FAST_SIMP_ss : ssfrag 96 97 98 (********************************) 99 (* simplify PMATCH-terms *) 100 (********************************) 101 102 (* Remove easily detectable redundant rows *) 103 val PMATCH_REMOVE_FAST_REDUNDANT_CONV : conv 104 val PMATCH_REMOVE_FAST_REDUNDANT_CONV_GEN : ssfrag list -> conv 105 106 (* Remove easily detectable subsumed rows *) 107 val PMATCH_REMOVE_FAST_SUBSUMED_CONV : bool -> conv 108 val PMATCH_REMOVE_FAST_SUBSUMED_CONV_GEN : bool -> ssfrag list -> conv 109 110 (* Full simplification of PMATCH expressions: 111 normalise, partially evaluate rows and columns and 112 try to remove redundant and subsumed rows. *) 113 val PMATCH_SIMP_CONV : conv 114 val PMATCH_SIMP_CONV_GEN : ssfrag list -> conv 115 val PMATCH_SIMP_GEN_ss : ssfrag list -> ssfrag 116 val PMATCH_SIMP_ss : ssfrag 117 118 119 (********************************) 120 (* removing double variable *) 121 (* bindings *) 122 (********************************) 123 124 val PMATCH_REMOVE_DOUBLE_BIND_CONV_GEN : ssfrag list -> conv 125 val PMATCH_REMOVE_DOUBLE_BIND_CONV : conv 126 val PMATCH_REMOVE_DOUBLE_BIND_GEN_ss : ssfrag list -> ssfrag 127 val PMATCH_REMOVE_DOUBLE_BIND_ss : ssfrag 128 129 130 (********************************) 131 (* removing GUARDS *) 132 (********************************) 133 134 val PMATCH_REMOVE_GUARDS_CONV_GEN : ssfrag list -> conv 135 val PMATCH_REMOVE_GUARDS_CONV : conv 136 val PMATCH_REMOVE_GUARDS_GEN_ss : ssfrag list -> ssfrag 137 val PMATCH_REMOVE_GUARDS_ss : ssfrag 138 139 140 (********************************) 141 (* extending input *) 142 (********************************) 143 144 val PMATCH_EXTEND_INPUT_CONV_GEN : ssfrag list -> term -> conv 145 val PMATCH_EXTEND_INPUT_CONV : term -> conv 146 147 (********************************) 148 (* removing PMATCH-terms *) 149 (* via lifting it to the nearest*) 150 (* boolean term and then *) 151 (* unfolding *) 152 (********************************) 153 154 (* One can eliminate PMATCHs by unfolding all 155 cases explicitly. This is often handy to 156 prove properties about functions defined 157 via pattern matches without the need to 158 do the case-splits manually. 159 160 This tactic looks for the smallest wrapper 161 around a PMATCH such that the term is of type 162 bool. This term is then expanded into a big 163 conjunction. For each case of the pattern match, 164 one conjunct is created. 165 166 If the flag "check_exh" is is set to true, the 167 conversion tries to prove the exhaustiveness of 168 the expanded pattern match. This is slow, but if 169 successful allows to eliminate the last 170 generated conjunct. 171 *) 172 val PMATCH_LIFT_BOOL_CONV : bool -> conv 173 174 (* There is also a more generic version that 175 allows to provide extra ssfrags. This might 176 be handy, if the PMATCH contains functions 177 not known by the default methods. *) 178 val PMATCH_LIFT_BOOL_CONV_GEN : ssfrag list -> bool -> conv 179 180 (* corresponding ssfrags *) 181 val PMATCH_LIFT_BOOL_GEN_ss : ssfrag list -> bool -> ssfrag 182 val PMATCH_LIFT_BOOL_ss : bool -> ssfrag 183 184 (* A special case of lifting are function definitions, 185 which use PMATCH. In order to use such definitions 186 with the rewriting tools, it is often handy to 187 move the PMATCH to the toplevel and introduce 188 multiple cases, one case for each row of the 189 PMATCH. This is automated by the following rules. *) 190 val PMATCH_TO_TOP_RULE_GEN : ssfrag list -> rule 191 val PMATCH_TO_TOP_RULE : rule 192 193 (********************************) 194 (* convert between *) 195 (* case and pmatch *) 196 (********************************) 197 198 (* without proof convert a case to a pmatch expression. 199 If the flag is set, optimise the result by 200 introducing wildcards reordering rows ... *) 201 val case2pmatch : bool -> term -> term 202 203 (* convert a pmatch expression to a case expression. 204 Fails, if the pmatch expression uses guards or 205 non-constructor patterns. *) 206 val pmatch2case : term -> term 207 208 (* The following conversions call 209 case2pmatch and pmatch2case and 210 afterwards prove the equivalence of 211 the result. *) 212 val PMATCH_INTRO_CONV : conv 213 val PMATCH_INTRO_CONV_NO_OPTIMISE : conv 214 val PMATCH_ELIM_CONV : conv 215 216 217 (*************************************) 218 (* Analyse PMATCH expressions to *) 219 (* check whether they can be *) 220 (* translated to ML or OCAML *) 221 (*************************************) 222 223 (* Record storing detailed information about a PMATCH *) 224 type pmatch_info = { 225 (* Is it a well formed PMATCH, i.e. is it of 226 the from PMATCH input row_list, where 227 every row is given explicitly via PMATCH_MATCH_ROW 228 and is wellformed itself? *) 229 pmi_is_well_formed : bool, 230 231 (* List of all rows that are not well-formed. 232 If this list is non-empty, pmi_is_well_formed is false. *) 233 pmi_ill_formed_rows : int list, 234 235 (* List of rows that have guards *) 236 pmi_has_guards : int list, 237 238 (* List of rows that contain variables in a pattern that 239 are not bound by the pattern. These free vars are 240 returned explicitly. *) 241 pmi_has_free_pat_vars : (int * term list) list, 242 243 (* List of rows whose patterns bind variables that they 244 do not use. These unused vars are returned explicitly. *) 245 pmi_has_unused_pat_vars : (int * term list) list, 246 247 (* List of rows whose patterns use a bound variable 248 multiple times. These vars are returned explicitly. *) 249 pmi_has_double_bound_pat_vars : (int * term list) list, 250 251 (* List of rows that uses constants that are neither 252 literals nor datatype-constructors in 253 patterns. These constants are returned. *) 254 pmi_has_non_contr_in_pat : (int * term list) list, 255 256 (* List of rows that use lambda-abstractions in patterns. *) 257 pmi_has_lambda_in_pat : int list, 258 259 (* Optional information about exhaustiveness. 260 Checking exhaustiveness is expensive, therefore it 261 can be skipped. However, if a theorem is stored here, 262 it is of the form `|- ~(cond) -> exhaustive`. 263 There are no other guarantees. We don't guarantee that 264 if the condition holds, the pattern match is inexhaustive. 265 This is usually the case, put we don't guarantee it. 266 To check, whether the match is exhaustive, check whether 267 the guard is T. See below for functions using this 268 field. 269 *) 270 pmi_exhaustiveness_cond : thm option 271 } 272 273 (* Analyse a PMATCH term and return the result. If 274 the flag is set to true, an exhaustiveness check is 275 attempted, if no syntactic checks indicate that this 276 one would most likely fail. *) 277 val analyse_pmatch : bool -> term -> pmatch_info 278 279 (* Check whether the PMATCH is syntactically well-formed. *) 280 val is_well_formed_pmatch : pmatch_info -> bool 281 282 (* Check whether the PMATCH is falling into the subset 283 supported by OCAML *) 284 val is_ocaml_pmatch : pmatch_info -> bool 285 286 (* Check whether the PMATCH is falling into the subset 287 supported by SML. *) 288 val is_sml_pmatch : pmatch_info -> bool; 289 290 (* Was it proved that the PMATCH is exhaustive? If 291 the answer is no, we don't know much. *) 292 val is_proven_exhaustive_pmatch : pmatch_info -> bool 293 294 (* Get the list of patterns that are possibly missing. 295 If no exhaustiveness information is available, NONE 296 is returned. The missing patterns are returns as a list 297 of triples (`bound-vars`, `pattern`, `guard`) *) 298 val get_possibly_missing_patterns : pmatch_info -> 299 (term * term * term) list option 300 301 (** extend_possibly_missing_patterns t pmi 302 tries to extend the original pattern match t with 303 rows derived from the exhaustiveness information 304 from its info. It fails, if no exhaustiveness 305 information is available. The result should 306 be an exhaustive match, which is equivalent to 307 the input `t`. If you need a proof, use 308 PMATCH_COMPLETE_CONV and similar functions instead 309 of this syntactic one. *) 310 val extend_possibly_missing_patterns : term -> pmatch_info -> term 311 312 313 (********************************) 314 (* CASE SPLIT (pattern compile) *) 315 (********************************) 316 317 (*------------*) 318 (* Heuristics *) 319 (*------------*) 320 321 (* A column heuristic is used to figure out, in 322 which order to process columns. It gets a list of columns 323 and returns, which one to pick. *) 324 type column_heuristic = (term * (term list * term) list) list -> int 325 326 (* Many heuristics are build on ranking funs. 327 A ranking fun assigns an integer to a column. Larger 328 numbers are preferred. If two columns have the same 329 value, either another ranking fun is used to decide or 330 just the first one is used, if no ranking fun is available. *) 331 type column_ranking_fun = term * (term list * term) list -> int 332 val colHeu_rank : column_ranking_fun list -> column_heuristic 333 334 val colRank_first_row : column_ranking_fun 335 val colRank_first_row_constr : constrFamiliesLib.pmatch_compile_db -> 336 column_ranking_fun 337 val colRank_arity : constrFamiliesLib.pmatch_compile_db -> column_ranking_fun 338 val colRank_constr_prefix : column_ranking_fun 339 val colRank_small_branching_factor : constrFamiliesLib.pmatch_compile_db -> 340 column_ranking_fun 341 342 (* Some heuristics *) 343 val colHeu_first_col : column_heuristic 344 val colHeu_last_col : column_heuristic 345 val colHeu_first_row : column_heuristic 346 val colHeu_constr_prefix : column_heuristic 347 val colHeu_cqba : constrFamiliesLib.pmatch_compile_db -> column_heuristic 348 val colHeu_qba : constrFamiliesLib.pmatch_compile_db -> column_heuristic 349 350 (* the default heuristic, currently it is 351 colHeu_qba applied to the default db. However, 352 this might change. You can just rely on a decent heuristic, 353 that often works. No specific properties guaranteed. *) 354 val colHeu_default : column_heuristic 355 356 357 (*---------------------*) 358 (* PATTERN COMPILATION *) 359 (*---------------------*) 360 361 (* [PMATCH_CASE_SPLIT_CONV_GEN ssl db col_heu] 362 is a conversion that tries to compile PMATCH expressions 363 to decision trees using database [db], column heuristic 364 [col_heu] and additional ssfrags [ssl]. *) 365 val PMATCH_CASE_SPLIT_CONV_GEN : 366 ssfrag list -> 367 constrFamiliesLib.pmatch_compile_db -> 368 column_heuristic -> conv 369 370 (* A simplified version of PMATCH_CASE_SPLIT_CONV that 371 uses the default database and default column heuristic as 372 well as no extra ssfrags. *) 373 val PMATCH_CASE_SPLIT_CONV : conv 374 375 (* lets choose at least the heuristic *) 376 val PMATCH_CASE_SPLIT_CONV_HEU : column_heuristic -> conv 377 378 (* ssfrag corresponding to PMATCH_CASE_SPLIT_CONV_GEN *) 379 val PMATCH_CASE_SPLIT_GEN_ss : 380 ssfrag list -> 381 constrFamiliesLib.pmatch_compile_db -> 382 column_heuristic -> ssfrag 383 384 (* ssfrag corresponding to PMATCH_CASE_SPLIT_CONV, since 385 it needs to get the current version of the default db, 386 it gets a unit argument. *) 387 val PMATCH_CASE_SPLIT_ss : unit -> ssfrag 388 389 (* lets choose at least the heuristic *) 390 val PMATCH_CASE_SPLIT_HEU_ss : column_heuristic -> ssfrag 391 392 393 (* Pattern compilation builds for a list of patterns, implicitly 394 a nchotomy theorem, i.e. a list of patterns that cover all the 395 original ones and are exhaustive. Moreover these patterns usually 396 have some nice properties like e.g. not overlapping with each other. 397 Such a nchotomy theorem is often handy. We use it to check for 398 exhaustiveness for example. The interface 399 to compute such an nchotomy is exposed here as well. *) 400 401 (* [nchotomy_of_pats_GEN db colHeu pats] computes an nchotomy-theorem 402 for a list of patterns. A pattern is written as for PMATCH, i.e. in the form ``\(v1, ..., vn). p v1 ... vn``. *) 403 val nchotomy_of_pats_GEN : constrFamiliesLib.pmatch_compile_db -> 404 column_heuristic -> term list -> thm 405 val nchotomy_of_pats : term list -> thm 406 407 408 (*-----------------------*) 409 (* Remove redundant rows *) 410 (*-----------------------*) 411 412 (* fancy, slow conversion for detecting and removing 413 redundant rows. Internally this uses [nchotomy_of_pats] and 414 therefore requires a pmatch-compile db and a column-heuristic. *) 415 val PMATCH_REMOVE_REDUNDANT_CONV_GEN : 416 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> ssfrag list -> 417 conv 418 val PMATCH_REMOVE_REDUNDANT_CONV : conv 419 420 val PMATCH_REMOVE_REDUNDANT_GEN_ss : 421 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> ssfrag list -> 422 ssfrag 423 val PMATCH_REMOVE_REDUNDANT_ss : unit -> ssfrag 424 425 426 (* The redundancy removal conversion works by 427 first creating a is-redundant-rows-info theorem and 428 then turning it into a PMATCH equation. One can 429 separate these steps, this allows using interactive proofs 430 for showing that a row is redundant. *) 431 val COMPUTE_REDUNDANT_ROWS_INFO_OF_PMATCH_GEN : 432 ssfrag list -> constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 433 term -> thm 434 val COMPUTE_REDUNDANT_ROWS_INFO_OF_PMATCH : term -> thm 435 436 (* Apply the resulting redundant rows-info *) 437 val IS_REDUNDANT_ROWS_INFO_TO_PMATCH_EQ_THM : thm -> thm 438 439 440 (* prove redundancy of given row given an info-thm *) 441 val IS_REDUNDANT_ROWS_INFO_SHOW_ROW_IS_REDUNDANT : 442 thm -> int -> tactic -> thm 443 444 val IS_REDUNDANT_ROWS_INFO_SHOW_ROW_IS_REDUNDANT_set_goal : 445 thm -> int -> proofManagerLib.proofs 446 447 448 (*-----------------------*) 449 (* Exhaustiveness *) 450 (*-----------------------*) 451 452 (* A IS_REDUNDANT_ROW_INFO theorem contains already 453 information, whether the pattern match is exhaustive. 454 455 IS_REDUNDANT_ROWS_INFO_TO_PMATCH_IS_EXHAUSTIVE extracts 456 this information in the form of an implication. Ideally, 457 the precondition is ~F, but the user has to check. *) 458 459 val IS_REDUNDANT_ROWS_INFO_TO_PMATCH_IS_EXHAUSTIVE : thm -> thm 460 461 (* For convenience this is combined with the computation of the 462 IS_REDUNDANT_ROWS_INFO. So given a PMATCH term, the following 463 functions compute an implication, whose conclusion is the 464 exhaustiveness of the PMATCH. *) 465 466 val PMATCH_IS_EXHAUSTIVE_COMPILE_CONSEQ_CHECK : term -> thm 467 val PMATCH_IS_EXHAUSTIVE_COMPILE_CONSEQ_CHECK_GEN : 468 ssfrag list -> term -> thm 469 val PMATCH_IS_EXHAUSTIVE_COMPILE_CONSEQ_CHECK_FULLGEN : 470 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 471 (ssfrag list * conv option) -> term -> thm 472 473 (* One can usually even derive an equality. *) 474 475 val PMATCH_IS_EXHAUSTIVE_COMPILE_CHECK : term -> thm 476 val PMATCH_IS_EXHAUSTIVE_COMPILE_CHECK_GEN : 477 ssfrag list -> term -> thm 478 val PMATCH_IS_EXHAUSTIVE_COMPILE_CHECK_FULLGEN : 479 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 480 (ssfrag list * conv option) -> term -> thm 481 482 483 (* Computing the IS_REDUNDANT_ROWS_INFO takes time and 484 is often not necessary. Many pattern matches contain 485 for example and catch-all pattern as the last row. 486 The following functions try to compute the redundancy 487 fast by searching such rows. If they succeed they result 488 in a theorem of the form 489 490 EHX_STATEMENT = T 491 492 or 493 494 EHX_STATEMENT = F 495 496 So, this time, there is an equation, not an implication 497 and the right-hand-side is always T or F. 498 *) 499 val PMATCH_IS_EXHAUSTIVE_FAST_CHECK : term -> thm 500 val PMATCH_IS_EXHAUSTIVE_FAST_CHECK_GEN : ssfrag list -> term -> thm 501 502 503 (* Both methods can be combined to combine the speed of 504 the fast version with the power of the slow one. 505 506 There are two versions of this, one resulting in an 507 equation and one resulting in an implication. The 508 equation one is suitable, if one just wants yes/no 509 answers, the implicational one to analyse what is missing 510 to make the pattern match exhaustive. *) 511 512 val PMATCH_IS_EXHAUSTIVE_CHECK : term -> thm 513 val PMATCH_IS_EXHAUSTIVE_CHECK_GEN : ssfrag list -> term -> thm 514 val PMATCH_IS_EXHAUSTIVE_CHECK_FULLGEN : 515 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 516 (ssfrag list * conv option) -> term -> thm 517 518 val PMATCH_IS_EXHAUSTIVE_CONSEQ_CHECK : term -> thm 519 val PMATCH_IS_EXHAUSTIVE_CONSEQ_CHECK_GEN : ssfrag list -> term -> thm 520 val PMATCH_IS_EXHAUSTIVE_CONSEQ_CHECK_FULLGEN : 521 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 522 (ssfrag list * conv option) -> term -> thm 523 524 525 (* More interesting than just computing whether a PMATCH 526 expression is exhaustive might be adding at the end 527 additional rows that explicitly list the missing pats 528 and return ARB for them. This is achieved by the following 529 functions. 530 531 The additional patterns can use guards or not. If not 532 guards are used, the added patterns are more coarse, but 533 simpler. *) 534 535 val PMATCH_COMPLETE_CONV : bool -> conv 536 val PMATCH_COMPLETE_ss : bool -> ssfrag 537 538 (* and as usual more general versions that allows using 539 own pattern compilation settings *) 540 val PMATCH_COMPLETE_CONV_GEN : ssfrag list -> 541 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 542 bool -> conv 543 544 val PMATCH_COMPLETE_GEN_ss : 545 ssfrag list -> 546 constrFamiliesLib.pmatch_compile_db -> 547 column_heuristic -> bool -> ssfrag 548 549 550 (* Versions with suffix "WITH_EXH_PROOF" return a theorem stating 551 that the resulting case split is exhaustive is returned as well. 552 In case the original case split is already exhaustive, no 553 conversion theorem is returned. However a theorem stating that the 554 original case split is exhaustive is still computed. *) 555 val PMATCH_COMPLETE_CONV_WITH_EXH_PROOF : bool -> (term -> (thm option * thm)) 556 557 val PMATCH_COMPLETE_CONV_GEN_WITH_EXH_PROOF : ssfrag list -> 558 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 559 bool -> (term -> (thm option * thm)) 560 561 (*-----------------------*) 562 (* Show nchotomy *) 563 (*-----------------------*) 564 565 (* [show_nchotomy t] tries to prove an nchotomy-theorem. 566 Given an nchotomy theorem of the form 567 ``!x. (?xs1. v = p1 xs1 /\ g1 xs1) \/ ... \/ 568 (?xsn. v = pn xsn /\ gn xsn)``. 569 It returns a theorem that is an implication with 570 the input as conclusion. *) 571 val SHOW_NCHOTOMY_CONSEQ_CONV : ConseqConv.conseq_conv 572 573 (* A generalised version that allows specifying additional 574 parameters. *) 575 val SHOW_NCHOTOMY_CONSEQ_CONV_GEN : 576 ssfrag list -> constrFamiliesLib.pmatch_compile_db -> 577 column_heuristic -> ConseqConv.conseq_conv 578 579 580 (********************************) 581 (* General Lifting *) 582 (********************************) 583 584 (* One can also lift to arbitrary levels. This requires forcing the 585 lifted case expression to be exhaustive though. Therefore, 586 PMATCH_COMPLETE_CONV is used internally and a compilation database 587 and a column heuristic are needed. Similarly to lifting, there is 588 also a version that returns an exhaustiveness statement of the 589 result. *) 590 591 val PMATCH_LIFT_CONV : conv 592 593 val PMATCH_LIFT_CONV_GEN : ssfrag list -> 594 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 595 conv 596 597 val PMATCH_LIFT_CONV_WITH_EXH_PROOF : term -> (thm * thm) 598 599 val PMATCH_LIFT_CONV_GEN_WITH_EXH_PROOF : ssfrag list -> 600 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 601 term -> (thm * thm) 602 603 604 (********************************) 605 (* Flattening *) 606 (********************************) 607 608 (* Flattening tries to flatten nested PMATCH case expressions into a 609 single one. It needs to enforce exhaustiveness. Therefore a 610 compilation database and a column heuristic are needed. The 611 additional flag states whether lifting should be attempted. If 612 set to false, only nested PMATCH expressions directly at the top 613 of the rhs of a row are considered for flattening. Otherwise, 614 lifting is attempted. *) 615 616 val PMATCH_FLATTEN_CONV_GEN : ssfrag list -> 617 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 618 bool -> conv 619 620 val PMATCH_FLATTEN_CONV : bool -> conv 621 622 val PMATCH_FLATTEN_GEN_ss : ssfrag list -> 623 constrFamiliesLib.pmatch_compile_db -> column_heuristic -> 624 bool -> ssfrag 625 626 val PMATCH_FLATTEN_ss : bool -> ssfrag 627 628 (********************************) 629 (* eliminating select *) 630 (********************************) 631 632 (* PMATCH leads to selects consisting of 633 conjunctions that determine the value of one 634 component of the variable. An example is 635 636 @x. SND (SND x = ..) /\ (FST x = ..) /\ (FST (SND x) = ..) 637 638 by resorting these conjunctions, one can 639 easily derive a form 640 641 @x. x = .. 642 643 and therefore eliminate the select operator. 644 This is done by the following conversion + ssfrag. 645 These are used internally by the pattern matches 646 infrastructure. *) 647 val ELIM_FST_SND_SELECT_CONV : conv 648 val elim_fst_snd_select_ss : ssfrag 649 650end 651