summaryrefslogtreecommitdiff
path: root/matcher.mli
diff options
context:
space:
mode:
Diffstat (limited to 'matcher.mli')
-rw-r--r--matcher.mli192
1 files changed, 192 insertions, 0 deletions
diff --git a/matcher.mli b/matcher.mli
new file mode 100644
index 0000000..3e20e73
--- /dev/null
+++ b/matcher.mli
@@ -0,0 +1,192 @@
+(***************************************************************************)
+(* This is part of aac_tactics, it is distributed under the terms of the *)
+(* GNU Lesser General Public License version 3 *)
+(* (see file LICENSE for more details) *)
+(* *)
+(* Copyright 2009-2010: Thomas Braibant, Damien Pous. *)
+(***************************************************************************)
+
+(** Standalone module containing the algorithm for matching modulo
+ associativity and associativity and commutativity (AAC).
+
+ This module could be reused ouside of the Coq plugin.
+
+ Matching modulo AAC a pattern [p] against a term [t] boils down to
+ finding a substitution [env] such that the pattern [p] instantiated
+ with [env] is equal to [t] modulo AAC.
+
+ We proceed by structural decomposition of the pattern, trying all
+ possible non-deterministic split of the subject, when needed. The
+ function {!matcher} is limited to top-level matching, that is, the
+ subject must make a perfect match against the pattern ([x+x] does
+ not match [a+a+b] ).
+
+ We use a search monad {!Search} to perform non-deterministic
+ choices in an almost transparent way.
+
+ We also provide a function {!subterm} for finding a match that is
+ a subterm of the subject modulo AAC. In particular, this function
+ gives a solution to the aforementioned case ([x+x] against
+ [a+b+a]).
+*)
+
+(** {2 Utility functions} *)
+
+type symbol = int
+type var = int
+
+(** The {!Search} module contains a search monad that allows to
+ express our non-deterministic and back-tracking algorithm in a
+ legible maner.
+
+ @see <http://spivey.oriel.ox.ac.uk/mike/search-jfp.pdf> the
+ inspiration of this module
+*)
+module Search :
+sig
+ (** A data type that represent a collection of ['a] *)
+ type 'a m
+ (** bind and return *)
+ val ( >> ) : 'a m -> ('a -> 'b m) -> 'b m
+ val return : 'a -> 'a m
+ (** non-deterministic choice *)
+ val ( >>| ) : 'a m -> 'a m -> 'a m
+ (** failure *)
+ val fail : unit -> 'a m
+ (** folding through the collection *)
+ val fold : ('a -> 'b -> 'b) -> 'a m -> 'b -> 'b
+ (** derived facilities *)
+ val sprint : ('a -> string) -> 'a m -> string
+ val count : 'a m -> int
+ val choose : 'a m -> 'a option
+ val to_list : 'a m -> 'a list
+ val sort : ('a -> 'a -> int) -> 'a m -> 'a m
+ val is_empty: 'a m -> bool
+end
+
+(** The arguments of sums (or AC operators) are represented using finite multisets.
+ (Typically, [a+b+a] corresponds to [2.a+b], i.e. [Sum[a,2;b,1]]) *)
+type 'a mset = ('a * int) list
+
+(** [linear] expands a multiset into a simple list *)
+val linear : 'a mset -> 'a list
+
+(** Representations of expressions
+
+ The module {!Terms} defines two different types for expressions.
+ - a public type {!Terms.t} that represents abstract syntax trees
+ of expressions with binary associative and commutative operators
+ - a private type {!Terms.nf_term}, corresponding to a canonical
+ representation for the above terms modulo AAC. The construction
+ functions on this type ensure that these terms are in normal form
+ (that is, no sum can appear as a subterm of the same sum, no
+ trailing units, lists corresponding to multisets are sorted,
+ etc...).
+
+*)
+module Terms :
+sig
+
+ (** {2 Abstract syntax tree of terms and patterns}
+
+ We represent both terms and patterns using the following datatype.
+
+ Values of type [symbol] are used to index symbols. Typically,
+ given two associative operations [(^)] and [( * )], and two
+ morphisms [f] and [g], the term [f (a^b) (a*g b)] is represented
+ by the following value
+ [Sym(0,[| Dot(1, Sym(2,[||]), Sym(3,[||]));
+ Dot(4, Sym(2,[||]), Sym(5,[|Sym(3,[||])|])) |])]
+ where the implicit symbol environment associates
+ [f] to [0], [(^)] to [1], [a] to [2], [b] to [3], [( * )] to [4], and [g] to [5],
+
+ Accordingly, the following value, that contains "variables"
+ [Sym(0,[| Dot(1, Var x, Dot(4,[||]));
+ Dot(4, Var x, Sym(5,[|Sym(3,[||])|])) |])]
+ represents the pattern [forall x, f (x^1) (x*g b)], where [1] is the
+ unit associated with [( * )].
+ *)
+
+ type t =
+ Dot of (symbol * t * t)
+ | One of symbol
+ | Plus of (symbol * t * t)
+ | Zero of symbol
+ | Sym of (symbol * t array)
+ | Var of var
+
+ (** Test for equality of terms modulo AAC (relies on the following
+ canonical representation of terms) *)
+ val equal_aac : t -> t -> bool
+
+
+ (** {2 Normalised terms (canonical representation) }
+
+ A term in normal form is the canonical representative of the
+ equivalence class of all the terms that are equal modulo AAC
+ This representation is only used internally; it is exported here
+ for the sake of completeness *)
+
+ type nf_term
+
+ (** {3 Comparisons} *)
+
+ val nf_term_compare : nf_term -> nf_term -> int
+ val nf_equal : nf_term -> nf_term -> bool
+
+ (** {3 Printing function} *)
+
+ val sprint_nf_term : nf_term -> string
+
+ (** {3 Conversion functions} *)
+
+ (** we have the following property: [a] and [b] are equal modulo AAC
+ iif [nf_equal (term_of_t a) (term_of_t b) = true] *)
+ val term_of_t : t -> nf_term
+ val t_of_term : nf_term -> t
+
+end
+
+
+(** Substitutions (or environments)
+
+ The module {!Subst} contains infrastructure to deal with
+ substitutions, i.e., functions from variables to terms. Only a
+ restricted subsets of these functions need to be exported.
+
+ As expected, a particular substitution can be used to
+ instantiate a pattern.
+*)
+module Subst :
+sig
+ type t
+ val sprint : t -> string
+ val instantiate : t -> Terms.t-> Terms.t
+ val to_list : t -> (var*Terms.t) list
+end
+
+
+(** {2 Main functions exported by this module} *)
+
+(** [matcher p t] computes the set of solutions to the given top-level
+ matching problem ([p] is the pattern, [t] is the term). If the
+ [strict] flag is set, solutions where units are used to
+ instantiate some variables are excluded, unless this unit appears
+ directly under a function symbol (e.g., f(x) still matches f(1),
+ while x+x+y does not match a+b+c, since this would require to
+ assign 1 to x).
+*)
+val matcher : ?strict:bool -> Terms.t -> Terms.t -> Subst.t Search.m
+
+(** [subterm p t] computes a set of solutions to the given
+ subterm-matching problem.
+
+ @return a collection of possible solutions (each with the
+ associated depth, the context, and the solutions of the matching
+ problem). The context is actually a {!Terms.t} where the variables
+ are yet to be instantiated by one of the associated substitutions
+*)
+val subterm : ?strict:bool -> Terms.t -> Terms.t -> (int * Terms.t * Subst.t Search.m) Search.m
+
+(** pretty printing of the solutions *)
+val pp_all : (Terms.t -> Pp.std_ppcmds) -> (int * Terms.t * Subst.t Search.m) Search.m -> Pp.std_ppcmds