CookBook/Package/Ind_Interface.thy
changeset 120 c39f83d8daeb
parent 118 5f003fdf2653
child 124 0b9fa606a746
equal deleted inserted replaced
119:4536782969fa 120:c39f83d8daeb
     1 theory Ind_Interface
     1 theory Ind_Interface
     2 imports "../Base" Simple_Inductive_Package
     2 imports "../Base" "../Parsing" Simple_Inductive_Package
     3 begin
     3 begin
     4 
     4 
     5 section {* The Interface \label{sec:ind-interface} *}
     5 section {* The Interface \label{sec:ind-interface} *}
     6 
     6 
     7 text {* 
     7 text {* 
     8   The purpose of the package we show next is that the user just specifies the
     8   The purpose of the package we show next is that the user just specifies the
     9   inductive predicate by stating some introduction rules and then the packages
     9   inductive predicate by stating some introduction rules and then the packages
    10   makes the equivalent definition and derives from it useful properties.
    10   makes the equivalent definition and derives from it the needed properties.
    11   To be able to write down the specification in Isabelle, we have to introduce
    11   To be able to write down the specification in Isabelle, we have to introduce
    12   a new command (see Section~\ref{sec:newcommand}).  As the keyword for the new
    12   a new command (see Section~\ref{sec:newcommand}).  As the keyword for the new
    13   command we use \simpleinductive{}. The specifications corresponding to our
    13   command we chose \simpleinductive{}. The specifications corresponding to our
    14   examples described earlier are:
    14   examples described earlier are:
    15 *}
    15 *}
    16 
    16 
    17 simple_inductive
    17 simple_inductive
    18   trcl :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool"
    18   trcl :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool"
    31   accpart :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> bool"
    31   accpart :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> bool"
    32 where
    32 where
    33   accpartI: "(\<forall>y. R y x \<longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
    33   accpartI: "(\<forall>y. R y x \<longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
    34 
    34 
    35 text {*
    35 text {*
    36   We expect a constant (or constants) with possible typing annotations and a
    36   After the keyword we expect a constant (or constants) with possible typing 
       
    37   annotations and a
    37   list of introduction rules. While these specifications are all
    38   list of introduction rules. While these specifications are all
    38   straightforward, there is a technicality we like to deal with to do with
    39   straightforward, there is a technicality we like to deal with to do with
    39   fixed parameters and locales. Remember we pointed out that the parameter
    40   fixed parameters and locales. Remember we pointed out that the parameter
    40   @{text R} is fixed throughout the specifications of @{text trcl} and @{text
    41   @{text R} is fixed throughout the specifications of @{text trcl} and @{text
    41   accpart}. The point is that they might be fixed in a locale and we like to
    42   accpart}. The point is that they might be fixed in a locale and we like to
    44   closure and accessible part are defined with a fixed parameter @{text R} and
    45   closure and accessible part are defined with a fixed parameter @{text R} and
    45   also inside a locale fixing @{text R}.
    46   also inside a locale fixing @{text R}.
    46 *}
    47 *}
    47 
    48 
    48 text_raw {*
    49 text_raw {*
    49 \begin{figure}[p]
    50   \begin{figure}[p]
    50 \begin{isabelle}
    51   \begin{isabelle}
    51 *}
    52 *}
    52 simple_inductive
    53 simple_inductive
    53   trcl' for R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
    54   trcl' for R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
    54 where
    55 where
    55   base: "trcl' R x x"
    56   base: "trcl' R x x"
    70 
    71 
    71 simple_inductive (in rel) accpart''
    72 simple_inductive (in rel) accpart''
    72 where
    73 where
    73   accpartI: "(\<forall>y. R y x \<longrightarrow> accpart'' y) \<Longrightarrow> accpart'' x"
    74   accpartI: "(\<forall>y. R y x \<longrightarrow> accpart'' y) \<Longrightarrow> accpart'' x"
    74 text_raw {*
    75 text_raw {*
    75 \end{isabelle}
    76   \end{isabelle}
    76 \caption{The first definition is for the transitive closure where the
    77   \caption{The first definition is for the transitive closure where the
    77 relation @{text R} is explicitly fixed. Simiraly the second definition
    78   relation @{text R} is explicitly fixed. Simiraly the second definition
    78 of the accessible part of the relation @{text R}. The last two definitions
    79   of the accessible part of the relation @{text R}. The last two definitions
    79 specify the same inductive predicates, but this time defined inside
    80   specify the same inductive predicates, but this time defined inside
    80 a locale.\label{fig:inddefsfixed}}
    81   a locale.\label{fig:inddefsfixed}}
    81 \end{figure}
    82   \end{figure}
    82 *}
    83 *}
    83 
    84 
    84 text {*
    85 text {*
    85 \begin{figure}[p]
    86   From a high-level perspective the package consists of 6 subtasks:
    86 \begin{isabelle}
    87 
       
    88   \begin{itemize}
       
    89   \item reading the various parts of specification (i.e.~parser),
       
    90   \item transforming the parser outut into an internal 
       
    91   (typed) datastructure,
       
    92   \item making the definitions, 
       
    93   \item deriving the induction principles,
       
    94   \item deriving the introduction rules, and
       
    95   \item storing the results in the given theory to be visible 
       
    96   to the user. 
       
    97   \end{itemize}
       
    98 
       
    99 *}
       
   100 
       
   101 text {*
       
   102   \begin{figure}[p]
       
   103   \begin{isabelle}
    87   \railnontermfont{\rmfamily\itshape}
   104   \railnontermfont{\rmfamily\itshape}
    88   \railterm{simpleinductive,where,for}
   105   \railterm{simpleinductive,where,for}
    89   \railalias{simpleinductive}{\simpleinductive{}}
   106   \railalias{simpleinductive}{\simpleinductive{}}
    90   \railalias{where}{\isacommand{where}}
   107   \railalias{where}{\isacommand{where}}
    91   \railalias{for}{\isacommand{for}}
   108   \railalias{for}{\isacommand{for}}
    92   \begin{rail}
   109   \begin{rail}
    93   simpleinductive target? fixes (for fixes)? \\
   110   simpleinductive target? fixes (for fixes)? \\
    94   (where (thmdecl? prop + '|'))?
   111   (where (thmdecl? prop + '|'))?
    95   ;
   112   ;
    96   \end{rail}
   113   \end{rail}
    97 \end{isabelle}
   114   \end{isabelle}
    98 \caption{A railroad diagram describing the syntax of \simpleinductive{}. 
   115   \caption{A railroad diagram describing the syntax of \simpleinductive{}. 
    99 The \emph{target} indicates an optional locale; the \emph{fixes} are an 
   116   The \emph{target} indicates an optional locale; the \emph{fixes} are an 
   100 \isacommand{and}-separated list of names for the inductive predicates (they
   117   \isacommand{and}-separated list of names for the inductive predicates (they
   101 can also contain typing- and syntax anotations); similarly the \emph{fixes} 
   118   can also contain typing- and syntax anotations); similarly the \emph{fixes} 
   102 after \isacommand{for} to indicate fixed parameters; \emph{prop} stands for a 
   119   after \isacommand{for} to indicate fixed parameters; \emph{prop} stands for a 
   103 introduction rule with an optional theorem declaration (\emph{thmdecl}).
   120   introduction rule with an optional theorem declaration (\emph{thmdecl}).
   104 \label{fig:railroad}}
   121   \label{fig:railroad}}
   105 \end{figure}
   122   \end{figure}
   106 *}
   123 *}
   107 
   124 
   108 text {*
   125 text {*
   109   The syntax of the \simpleinductive{} command can be described by the
   126   For the first subtask, the syntax of the \simpleinductive{} command can be
   110   railroad diagram in Figure~\ref{fig:railroad}. This diagram more or less
   127   described by the railroad diagram in Figure~\ref{fig:railroad}. This diagram
   111   translates directly into the parser:
   128   more or less translates directly into the parser:
       
   129 
   112 
   130 
   113   @{ML_chunk [display,gray] parser}
   131   @{ML_chunk [display,gray] parser}
   114 
   132 
   115   which we also described in Section~\ref{sec:parsingspecs}. Its return value
   133   which we described in Section~\ref{sec:parsingspecs}. If we feed into the 
   116   of this parser is a locale, the predicates, parameters and specifications of 
   134   parser the string (which corresponds to our definition of @{term even} and 
   117   the introduction rules. This is all the information we need to call the package. 
   135   @{term odd}):
       
   136 
       
   137   @{ML_response [display,gray]
       
   138 "let
       
   139   val input = filtered_input
       
   140      (\"even and odd \" ^  
       
   141       \"where \" ^
       
   142       \"  even0[intro]: \\\"even 0\\\" \" ^ 
       
   143       \"| evenS[intro]: \\\"odd n \<Longrightarrow> even (Suc n)\\\" \" ^ 
       
   144       \"| oddS[intro]:  \\\"even n \<Longrightarrow> odd (Suc n)\\\"\")
       
   145 in
       
   146   parse spec_parser input
       
   147 end"
       
   148 "((((NONE, [(even, NONE, NoSyn), (odd, NONE, NoSyn)]), []),
       
   149      [((even0,\<dots>), \"\\^E\\^Ftoken\\^Eeven 0\\^E\\^F\\^E\"),
       
   150       ((evenS,\<dots>), \"\\^E\\^Ftoken\\^Eodd n \<Longrightarrow> even (Suc n)\\^E\\^F\\^E\"),
       
   151       ((oddS,\<dots>), \"\\^E\\^Ftoken\\^Eeven n \<Longrightarrow> odd (Suc n)\\^E\\^F\\^E\")]), [])"}
       
   152 *}
       
   153 
       
   154 
       
   155 text {*
       
   156   then we get back a locale (in this case @{ML NONE}), the predicates (with type
       
   157   and syntax annotations), the parameters (similar as the predicates) and
       
   158   the specifications of the introduction rules. 
       
   159 
       
   160 
       
   161 
       
   162   This is all the information we
       
   163   need for calling the package and setting up the keyword. The latter is
       
   164   done in Lines 6 and 7 in the code below.
   118 
   165 
   119   @{ML_chunk [display,gray,linenos] syntax}
   166   @{ML_chunk [display,gray,linenos] syntax}
   120 
   167   
   121   The locale is passed as argument to the function 
   168   We call @{ML OuterSyntax.command} with the kind-indicator @{ML
   122   @{ML Toplevel.local_theory}.\footnote{FIXME Is this already described?} The
   169   OuterKeyword.thy_decl} since the package does not need to open up any goal
   123   other arguments, i.e.~the predicates, parameters and specifications, are passed
   170   state (see Section~\ref{sec:newcommand}). Note that the predicates and
   124   to the function @{ML add_inductive in SimpleInductivePackage} (Line 4). The
   171   parameters are at the moment only some ``naked'' variables: they have no
   125   actual command is defined in Lines 6 and 7. We called @{ML OuterSyntax.command}
   172   type yet (even if we annotate them with types) and they are also no defined
   126   with the kind-indicator @{ML OuterKeyword.thy_decl} since the package does
   173   constants yet (which the predicates will eventually be).  In Lines 1 to 4 we
   127   not need to open up any goal state (see Section~\ref{sec:newcommand}).
   174   gather the information from the parser to be processed further. The locale
       
   175   is passed as argument to the function @{ML
       
   176   Toplevel.local_theory}.\footnote{FIXME Is this already described?} The other
       
   177   arguments, i.e.~the predicates, parameters and intro rule specifications,
       
   178   are passed to the function @{ML add_inductive in SimpleInductivePackage}
       
   179   (Line 4).
       
   180 
       
   181   We now come to the second subtask of the package, namely transforming the 
       
   182   parser output into some internal datastructures that can be processed further. 
       
   183   Remember that at the moment the introduction rules are just strings, and even
       
   184   if the predicates and parameters can contain some typing annotations, they
       
   185   are not yet in any way reflected in the introduction rules. So the task of
       
   186   @{ML add_inductive in SimpleInductivePackage} is to transform the strings
       
   187   into properly typed terms. For this it can use the function 
       
   188   @{ML read_specification in Specification}. This function takes some constants
       
   189   with possible typing annotations and some rule specifications and attempts to
       
   190   find a type according to the given type constraints and the type constraints
       
   191   by the surrounding (local theory). However this function is a bit
       
   192   too general for our purposes: we want that each introduction rule has only 
       
   193   name (for example @{text even0} or @{text evenS}), if a name is given at all.
       
   194   The function @{ML read_specification in Specification} however allows more
       
   195   than one rule. Since it is quite convenient to rely on this function (instead of
       
   196   building your own) we just quick ly write a wrapper function that translates
       
   197   between our specific format and the general format expected by 
       
   198   @{ML read_specification in Specification}. The code of this wrapper is as follows:
       
   199 
       
   200   @{ML_chunk [display,gray,linenos] read_specification}
       
   201 
       
   202   It takes a list of constants, a list of rule specifications and a local theory 
       
   203   as input. Does the transformation of the rule specifications in Line 3; calls
       
   204   the function and transforms the now typed rule specifications back into our
       
   205   format and returns the type parameter and typed rule specifications. 
       
   206 
       
   207 
       
   208    @{ML_chunk [display,gray,linenos] add_inductive}
       
   209 
   128 
   210 
   129   In order to add a new inductive predicate to a theory with the help of our
   211   In order to add a new inductive predicate to a theory with the help of our
   130   package, the user must \emph{invoke} it. For every package, there are
   212   package, the user must \emph{invoke} it. For every package, there are
   131   essentially two different ways of invoking it, which we will refer to as
   213   essentially two different ways of invoking it, which we will refer to as
   132   \emph{external} and \emph{internal}. By external invocation we mean that the
   214   \emph{external} and \emph{internal}. By external invocation we mean that the
   134   specification of the inductive predicate, including type annotations and
   216   specification of the inductive predicate, including type annotations and
   135   introduction rules, are given as strings by the user. Before the package can
   217   introduction rules, are given as strings by the user. Before the package can
   136   actually make the definition, the type and introduction rules have to be
   218   actually make the definition, the type and introduction rules have to be
   137   parsed. In contrast, internal invocation means that the package is called by
   219   parsed. In contrast, internal invocation means that the package is called by
   138   some other package. For example, the function definition package
   220   some other package. For example, the function definition package
   139   \cite{Krauss-IJCAR06} calls the inductive definition package to define the
   221   calls the inductive definition package to define the
   140   graph of the function. However, it is not a good idea for the function
   222   graph of the function. However, it is not a good idea for the function
   141   definition package to pass the introduction rules for the function graph to
   223   definition package to pass the introduction rules for the function graph to
   142   the inductive definition package as strings. In this case, it is better to
   224   the inductive definition package as strings. In this case, it is better to
   143   directly pass the rules to the package as a list of terms, which is more
   225   directly pass the rules to the package as a list of terms, which is more
   144   robust than handling strings that are lacking the additional structure of
   226   robust than handling strings that are lacking the additional structure of