src/Doc/Implementation/Syntax.thy
changeset 61854 38b049cd3aad
parent 61656 cfabbc083977
child 69597 ff784d5a5bfb
equal deleted inserted replaced
61853:fb7756087101 61854:38b049cd3aad
     4 imports Base
     4 imports Base
     5 begin
     5 begin
     6 
     6 
     7 chapter \<open>Concrete syntax and type-checking\<close>
     7 chapter \<open>Concrete syntax and type-checking\<close>
     8 
     8 
     9 text \<open>Pure \<open>\<lambda>\<close>-calculus as introduced in \chref{ch:logic} is
     9 text \<open>
    10   an adequate foundation for logical languages --- in the tradition of
    10   Pure \<open>\<lambda>\<close>-calculus as introduced in \chref{ch:logic} is an adequate
    11   \<^emph>\<open>higher-order abstract syntax\<close> --- but end-users require
    11   foundation for logical languages --- in the tradition of \<^emph>\<open>higher-order
    12   additional means for reading and printing of terms and types.  This
    12   abstract syntax\<close> --- but end-users require additional means for reading and
    13   important add-on outside the logical core is called \<^emph>\<open>inner
    13   printing of terms and types. This important add-on outside the logical core
    14   syntax\<close> in Isabelle jargon, as opposed to the \<^emph>\<open>outer syntax\<close> of
    14   is called \<^emph>\<open>inner syntax\<close> in Isabelle jargon, as opposed to the \<^emph>\<open>outer
    15   the theory and proof language @{cite "isabelle-isar-ref"}.
    15   syntax\<close> of the theory and proof language @{cite "isabelle-isar-ref"}.
    16 
    16 
    17   For example, according to @{cite church40} quantifiers are represented as
    17   For example, according to @{cite church40} quantifiers are represented as
    18   higher-order constants \<open>All :: ('a \<Rightarrow> bool) \<Rightarrow> bool\<close> such that \<open>All (\<lambda>x::'a. B x)\<close> faithfully represents the idea that is displayed in
    18   higher-order constants \<open>All :: ('a \<Rightarrow> bool) \<Rightarrow> bool\<close> such that \<open>All (\<lambda>x::'a. B
    19   Isabelle as \<open>\<forall>x::'a. B x\<close> via @{keyword "binder"} notation.
    19   x)\<close> faithfully represents the idea that is displayed in Isabelle as \<open>\<forall>x::'a.
    20   Moreover, type-inference in the style of Hindley-Milner @{cite hindleymilner}
    20   B x\<close> via @{keyword "binder"} notation. Moreover, type-inference in the style
    21   (and extensions) enables users to write \<open>\<forall>x. B x\<close> concisely, when
    21   of Hindley-Milner @{cite hindleymilner} (and extensions) enables users to
    22   the type \<open>'a\<close> is already clear from the
    22   write \<open>\<forall>x. B x\<close> concisely, when the type \<open>'a\<close> is already clear from the
    23   context.\<^footnote>\<open>Type-inference taken to the extreme can easily confuse
    23   context.\<^footnote>\<open>Type-inference taken to the extreme can easily confuse users.
    24   users. Beginners often stumble over unexpectedly general types inferred by
    24   Beginners often stumble over unexpectedly general types inferred by the
    25   the system.\<close>
    25   system.\<close>
    26 
    26 
    27   \<^medskip>
    27   \<^medskip>
    28   The main inner syntax operations are \<^emph>\<open>read\<close> for
    28   The main inner syntax operations are \<^emph>\<open>read\<close> for parsing together with
    29   parsing together with type-checking, and \<^emph>\<open>pretty\<close> for formatted
    29   type-checking, and \<^emph>\<open>pretty\<close> for formatted output. See also
    30   output.  See also \secref{sec:read-print}.
    30   \secref{sec:read-print}.
    31 
    31 
    32   Furthermore, the input and output syntax layers are sub-divided into
    32   Furthermore, the input and output syntax layers are sub-divided into
    33   separate phases for \<^emph>\<open>concrete syntax\<close> versus \<^emph>\<open>abstract
    33   separate phases for \<^emph>\<open>concrete syntax\<close> versus \<^emph>\<open>abstract syntax\<close>, see also
    34   syntax\<close>, see also \secref{sec:parse-unparse} and
    34   \secref{sec:parse-unparse} and \secref{sec:term-check}, respectively. This
    35   \secref{sec:term-check}, respectively.  This results in the
    35   results in the following decomposition of the main operations:
    36   following decomposition of the main operations:
    36 
    37 
    37     \<^item> \<open>read = parse; check\<close>
    38   \<^item> \<open>read = parse; check\<close>
    38 
    39 
    39     \<^item> \<open>pretty = uncheck; unparse\<close>
    40   \<^item> \<open>pretty = uncheck; unparse\<close>
       
    41 
       
    42 
    40 
    43   For example, some specification package might thus intercept syntax
    41   For example, some specification package might thus intercept syntax
    44   processing at a well-defined stage after \<open>parse\<close>, to a augment the
    42   processing at a well-defined stage after \<open>parse\<close>, to a augment the resulting
    45   resulting pre-term before full type-reconstruction is performed by \<open>check\<close>. Note that the formal status of bound variables, versus free
    43   pre-term before full type-reconstruction is performed by \<open>check\<close>. Note that
    46   variables, versus constants must not be changed between these phases.
    44   the formal status of bound variables, versus free variables, versus
    47 
    45   constants must not be changed between these phases.
    48   \<^medskip>
    46 
    49   In general, \<open>check\<close> and \<open>uncheck\<close> operate
    47   \<^medskip>
    50   simultaneously on a list of terms. This is particular important for
    48   In general, \<open>check\<close> and \<open>uncheck\<close> operate simultaneously on a list of terms.
    51   type-checking, to reconstruct types for several terms of the same context
    49   This is particular important for type-checking, to reconstruct types for
    52   and scope. In contrast, \<open>parse\<close> and \<open>unparse\<close> operate separately
    50   several terms of the same context and scope. In contrast, \<open>parse\<close> and
    53   on single terms.
    51   \<open>unparse\<close> operate separately on single terms.
    54 
    52 
    55   There are analogous operations to read and print types, with the same
    53   There are analogous operations to read and print types, with the same
    56   sub-division into phases.
    54   sub-division into phases.
    57 \<close>
    55 \<close>
    58 
    56 
    59 
    57 
    60 section \<open>Reading and pretty printing \label{sec:read-print}\<close>
    58 section \<open>Reading and pretty printing \label{sec:read-print}\<close>
    61 
    59 
    62 text \<open>
    60 text \<open>
    63   Read and print operations are roughly dual to each other, such that for the
    61   Read and print operations are roughly dual to each other, such that for the
    64   user \<open>s' = pretty (read s)\<close> looks similar to the original source
    62   user \<open>s' = pretty (read s)\<close> looks similar to the original source text \<open>s\<close>,
    65   text \<open>s\<close>, but the details depend on many side-conditions. There are
    63   but the details depend on many side-conditions. There are also explicit
    66   also explicit options to control the removal of type information in the
    64   options to control the removal of type information in the output. The
    67   output. The default configuration routinely looses information, so \<open>t' = read (pretty t)\<close> might fail, or produce a differently typed term, or
    65   default configuration routinely looses information, so \<open>t' = read (pretty
    68   a completely different term in the face of syntactic overloading.
    66   t)\<close> might fail, or produce a differently typed term, or a completely
       
    67   different term in the face of syntactic overloading.
    69 \<close>
    68 \<close>
    70 
    69 
    71 text %mlref \<open>
    70 text %mlref \<open>
    72   \begin{mldecls}
    71   \begin{mldecls}
    73   @{index_ML Syntax.read_typs: "Proof.context -> string list -> typ list"} \\
    72   @{index_ML Syntax.read_typs: "Proof.context -> string list -> typ list"} \\
    80   @{index_ML Syntax.pretty_term: "Proof.context -> term -> Pretty.T"} \\
    79   @{index_ML Syntax.pretty_term: "Proof.context -> term -> Pretty.T"} \\
    81   @{index_ML Syntax.string_of_typ: "Proof.context -> typ -> string"} \\
    80   @{index_ML Syntax.string_of_typ: "Proof.context -> typ -> string"} \\
    82   @{index_ML Syntax.string_of_term: "Proof.context -> term -> string"} \\
    81   @{index_ML Syntax.string_of_term: "Proof.context -> term -> string"} \\
    83   \end{mldecls}
    82   \end{mldecls}
    84 
    83 
    85   \<^descr> @{ML Syntax.read_typs}~\<open>ctxt strs\<close> parses and checks a
    84   \<^descr> @{ML Syntax.read_typs}~\<open>ctxt strs\<close> parses and checks a simultaneous list
    86   simultaneous list of source strings as types of the logic.
    85   of source strings as types of the logic.
    87 
    86 
    88   \<^descr> @{ML Syntax.read_terms}~\<open>ctxt strs\<close> parses and checks a
    87   \<^descr> @{ML Syntax.read_terms}~\<open>ctxt strs\<close> parses and checks a simultaneous list
    89   simultaneous list of source strings as terms of the logic.
    88   of source strings as terms of the logic. Type-reconstruction puts all parsed
    90   Type-reconstruction puts all parsed terms into the same scope: types of
    89   terms into the same scope: types of free variables ultimately need to
    91   free variables ultimately need to coincide.
    90   coincide.
    92 
    91 
    93   If particular type-constraints are required for some of the arguments, the
    92   If particular type-constraints are required for some of the arguments, the
    94   read operations needs to be split into its parse and check phases. Then it
    93   read operations needs to be split into its parse and check phases. Then it
    95   is possible to use @{ML Type.constraint} on the intermediate pre-terms
    94   is possible to use @{ML Type.constraint} on the intermediate pre-terms
    96   (\secref{sec:term-check}).
    95   (\secref{sec:term-check}).
    97 
    96 
    98   \<^descr> @{ML Syntax.read_props}~\<open>ctxt strs\<close> parses and checks a
    97   \<^descr> @{ML Syntax.read_props}~\<open>ctxt strs\<close> parses and checks a simultaneous list
    99   simultaneous list of source strings as terms of the logic, with an implicit
    98   of source strings as terms of the logic, with an implicit type-constraint
   100   type-constraint for each argument to enforce type @{typ prop}; this also
    99   for each argument to enforce type @{typ prop}; this also affects the inner
   101   affects the inner syntax for parsing. The remaining type-reconstruction
   100   syntax for parsing. The remaining type-reconstruction works as for @{ML
   102   works as for @{ML Syntax.read_terms}.
   101   Syntax.read_terms}.
   103 
   102 
   104   \<^descr> @{ML Syntax.read_typ}, @{ML Syntax.read_term}, @{ML Syntax.read_prop}
   103   \<^descr> @{ML Syntax.read_typ}, @{ML Syntax.read_term}, @{ML Syntax.read_prop} are
   105   are like the simultaneous versions, but operate on a single argument only.
   104   like the simultaneous versions, but operate on a single argument only. This
   106   This convenient shorthand is adequate in situations where a single item in
   105   convenient shorthand is adequate in situations where a single item in its
   107   its own scope is processed. Do not use @{ML "map o Syntax.read_term"} where
   106   own scope is processed. Do not use @{ML "map o Syntax.read_term"} where @{ML
   108   @{ML Syntax.read_terms} is actually intended!
   107   Syntax.read_terms} is actually intended!
   109 
   108 
   110   \<^descr> @{ML Syntax.pretty_typ}~\<open>ctxt T\<close> and @{ML
   109   \<^descr> @{ML Syntax.pretty_typ}~\<open>ctxt T\<close> and @{ML Syntax.pretty_term}~\<open>ctxt t\<close>
   111   Syntax.pretty_term}~\<open>ctxt t\<close> uncheck and pretty-print the given type
   110   uncheck and pretty-print the given type or term, respectively. Although the
   112   or term, respectively. Although the uncheck phase acts on a simultaneous
   111   uncheck phase acts on a simultaneous list as well, this is rarely used in
   113   list as well, this is rarely used in practice, so only the singleton case is
   112   practice, so only the singleton case is provided as combined pretty
   114   provided as combined pretty operation. There is no distinction of term vs.\
   113   operation. There is no distinction of term vs.\ proposition.
   115   proposition.
   114 
   116 
   115   \<^descr> @{ML Syntax.string_of_typ} and @{ML Syntax.string_of_term} are convenient
   117   \<^descr> @{ML Syntax.string_of_typ} and @{ML Syntax.string_of_term} are
   116   compositions of @{ML Syntax.pretty_typ} and @{ML Syntax.pretty_term} with
   118   convenient compositions of @{ML Syntax.pretty_typ} and @{ML
   117   @{ML Pretty.string_of} for output. The result may be concatenated with other
   119   Syntax.pretty_term} with @{ML Pretty.string_of} for output. The result may
   118   strings, as long as there is no further formatting and line-breaking
   120   be concatenated with other strings, as long as there is no further
   119   involved.
   121   formatting and line-breaking involved.
       
   122 
   120 
   123 
   121 
   124   @{ML Syntax.read_term}, @{ML Syntax.read_prop}, and @{ML
   122   @{ML Syntax.read_term}, @{ML Syntax.read_prop}, and @{ML
   125   Syntax.string_of_term} are the most important operations in practice.
   123   Syntax.string_of_term} are the most important operations in practice.
   126 
   124 
   127   \<^medskip>
   125   \<^medskip>
   128   Note that the string values that are passed in and out are
   126   Note that the string values that are passed in and out are annotated by the
   129   annotated by the system, to carry further markup that is relevant for the
   127   system, to carry further markup that is relevant for the Prover IDE @{cite
   130   Prover IDE @{cite "isabelle-jedit"}. User code should neither compose its
   128   "isabelle-jedit"}. User code should neither compose its own input strings,
   131   own input strings, nor try to analyze the output strings. Conceptually this
   129   nor try to analyze the output strings. Conceptually this is an abstract
   132   is an abstract datatype, encoded as concrete string for historical reasons.
   130   datatype, encoded as concrete string for historical reasons.
   133 
   131 
   134   The standard way to provide the required position markup for input works via
   132   The standard way to provide the required position markup for input works via
   135   the outer syntax parser wrapper @{ML Parse.inner_syntax}, which is already
   133   the outer syntax parser wrapper @{ML Parse.inner_syntax}, which is already
   136   part of @{ML Parse.typ}, @{ML Parse.term}, @{ML Parse.prop}. So a string
   134   part of @{ML Parse.typ}, @{ML Parse.term}, @{ML Parse.prop}. So a string
   137   obtained from one of the latter may be directly passed to the corresponding
   135   obtained from one of the latter may be directly passed to the corresponding
   145 text \<open>
   143 text \<open>
   146   Parsing and unparsing converts between actual source text and a certain
   144   Parsing and unparsing converts between actual source text and a certain
   147   \<^emph>\<open>pre-term\<close> format, where all bindings and scopes are already resolved
   145   \<^emph>\<open>pre-term\<close> format, where all bindings and scopes are already resolved
   148   faithfully. Thus the names of free variables or constants are determined in
   146   faithfully. Thus the names of free variables or constants are determined in
   149   the sense of the logical context, but type information might be still
   147   the sense of the logical context, but type information might be still
   150   missing. Pre-terms support an explicit language of \<^emph>\<open>type constraints\<close>
   148   missing. Pre-terms support an explicit language of \<^emph>\<open>type constraints\<close> that
   151   that may be augmented by user code to guide the later \<^emph>\<open>check\<close> phase.
   149   may be augmented by user code to guide the later \<^emph>\<open>check\<close> phase.
   152 
   150 
   153   Actual parsing is based on traditional lexical analysis and Earley parsing
   151   Actual parsing is based on traditional lexical analysis and Earley parsing
   154   for arbitrary context-free grammars. The user can specify the grammar
   152   for arbitrary context-free grammars. The user can specify the grammar
   155   declaratively via mixfix annotations. Moreover, there are \<^emph>\<open>syntax
   153   declaratively via mixfix annotations. Moreover, there are \<^emph>\<open>syntax
   156   translations\<close> that can be augmented by the user, either declaratively via
   154   translations\<close> that can be augmented by the user, either declaratively via
   168   @{index_ML Syntax.parse_prop: "Proof.context -> string -> term"} \\[0.5ex]
   166   @{index_ML Syntax.parse_prop: "Proof.context -> string -> term"} \\[0.5ex]
   169   @{index_ML Syntax.unparse_typ: "Proof.context -> typ -> Pretty.T"} \\
   167   @{index_ML Syntax.unparse_typ: "Proof.context -> typ -> Pretty.T"} \\
   170   @{index_ML Syntax.unparse_term: "Proof.context -> term -> Pretty.T"} \\
   168   @{index_ML Syntax.unparse_term: "Proof.context -> term -> Pretty.T"} \\
   171   \end{mldecls}
   169   \end{mldecls}
   172 
   170 
   173   \<^descr> @{ML Syntax.parse_typ}~\<open>ctxt str\<close> parses a source string as
   171   \<^descr> @{ML Syntax.parse_typ}~\<open>ctxt str\<close> parses a source string as pre-type that
   174   pre-type that is ready to be used with subsequent check operations.
   172   is ready to be used with subsequent check operations.
   175 
   173 
   176   \<^descr> @{ML Syntax.parse_term}~\<open>ctxt str\<close> parses a source string as
   174   \<^descr> @{ML Syntax.parse_term}~\<open>ctxt str\<close> parses a source string as pre-term that
   177   pre-term that is ready to be used with subsequent check operations.
   175   is ready to be used with subsequent check operations.
   178 
   176 
   179   \<^descr> @{ML Syntax.parse_prop}~\<open>ctxt str\<close> parses a source string as
   177   \<^descr> @{ML Syntax.parse_prop}~\<open>ctxt str\<close> parses a source string as pre-term that
   180   pre-term that is ready to be used with subsequent check operations. The
   178   is ready to be used with subsequent check operations. The inner syntax
   181   inner syntax category is @{typ prop} and a suitable type-constraint is
   179   category is @{typ prop} and a suitable type-constraint is included to ensure
   182   included to ensure that this information is observed in subsequent type
   180   that this information is observed in subsequent type reconstruction.
   183   reconstruction.
   181 
   184 
   182   \<^descr> @{ML Syntax.unparse_typ}~\<open>ctxt T\<close> unparses a type after uncheck
   185   \<^descr> @{ML Syntax.unparse_typ}~\<open>ctxt T\<close> unparses a type after
   183   operations, to turn it into a pretty tree.
   186   uncheck operations, to turn it into a pretty tree.
   184 
   187 
   185   \<^descr> @{ML Syntax.unparse_term}~\<open>ctxt T\<close> unparses a term after uncheck
   188   \<^descr> @{ML Syntax.unparse_term}~\<open>ctxt T\<close> unparses a term after
   186   operations, to turn it into a pretty tree. There is no distinction for
   189   uncheck operations, to turn it into a pretty tree. There is no distinction
   187   propositions here.
   190   for propositions here.
       
   191 
   188 
   192 
   189 
   193   These operations always operate on a single item; use the combinator @{ML
   190   These operations always operate on a single item; use the combinator @{ML
   194   map} to apply them to a list.
   191   map} to apply them to a list.
   195 \<close>
   192 \<close>
   196 
   193 
   197 
   194 
   198 section \<open>Checking and unchecking \label{sec:term-check}\<close>
   195 section \<open>Checking and unchecking \label{sec:term-check}\<close>
   199 
   196 
   200 text \<open>These operations define the transition from pre-terms and
   197 text \<open>
   201   fully-annotated terms in the sense of the logical core
   198   These operations define the transition from pre-terms and fully-annotated
   202   (\chref{ch:logic}).
   199   terms in the sense of the logical core (\chref{ch:logic}).
   203 
   200 
   204   The \<^emph>\<open>check\<close> phase is meant to subsume a variety of mechanisms
   201   The \<^emph>\<open>check\<close> phase is meant to subsume a variety of mechanisms in the manner
   205   in the manner of ``type-inference'' or ``type-reconstruction'' or
   202   of ``type-inference'' or ``type-reconstruction'' or ``type-improvement'',
   206   ``type-improvement'', not just type-checking in the narrow sense.
   203   not just type-checking in the narrow sense. The \<^emph>\<open>uncheck\<close> phase is roughly
   207   The \<^emph>\<open>uncheck\<close> phase is roughly dual, it prunes type-information
   204   dual, it prunes type-information before pretty printing.
   208   before pretty printing.
       
   209 
   205 
   210   A typical add-on for the check/uncheck syntax layer is the @{command
   206   A typical add-on for the check/uncheck syntax layer is the @{command
   211   abbreviation} mechanism @{cite "isabelle-isar-ref"}. Here the user specifies
   207   abbreviation} mechanism @{cite "isabelle-isar-ref"}. Here the user specifies
   212   syntactic definitions that are managed by the system as polymorphic \<open>let\<close> bindings. These are expanded during the \<open>check\<close> phase, and
   208   syntactic definitions that are managed by the system as polymorphic \<open>let\<close>
   213   contracted during the \<open>uncheck\<close> phase, without affecting the
   209   bindings. These are expanded during the \<open>check\<close> phase, and contracted during
   214   type-assignment of the given terms.
   210   the \<open>uncheck\<close> phase, without affecting the type-assignment of the given
   215 
   211   terms.
   216   \<^medskip>
   212 
   217   The precise meaning of type checking depends on the context ---
   213   \<^medskip>
   218   additional check/uncheck modules might be defined in user space.
   214   The precise meaning of type checking depends on the context --- additional
   219 
   215   check/uncheck modules might be defined in user space.
   220   For example, the @{command class} command defines a context where
   216 
   221   \<open>check\<close> treats certain type instances of overloaded
   217   For example, the @{command class} command defines a context where \<open>check\<close>
   222   constants according to the ``dictionary construction'' of its
   218   treats certain type instances of overloaded constants according to the
   223   logical foundation.  This involves ``type improvement''
   219   ``dictionary construction'' of its logical foundation. This involves ``type
   224   (specialization of slightly too general types) and replacement by
   220   improvement'' (specialization of slightly too general types) and replacement
   225   certain locale parameters.  See also @{cite "Haftmann-Wenzel:2009"}.
   221   by certain locale parameters. See also @{cite "Haftmann-Wenzel:2009"}.
   226 \<close>
   222 \<close>
   227 
   223 
   228 text %mlref \<open>
   224 text %mlref \<open>
   229   \begin{mldecls}
   225   \begin{mldecls}
   230   @{index_ML Syntax.check_typs: "Proof.context -> typ list -> typ list"} \\
   226   @{index_ML Syntax.check_typs: "Proof.context -> typ list -> typ list"} \\
   232   @{index_ML Syntax.check_props: "Proof.context -> term list -> term list"} \\[0.5ex]
   228   @{index_ML Syntax.check_props: "Proof.context -> term list -> term list"} \\[0.5ex]
   233   @{index_ML Syntax.uncheck_typs: "Proof.context -> typ list -> typ list"} \\
   229   @{index_ML Syntax.uncheck_typs: "Proof.context -> typ list -> typ list"} \\
   234   @{index_ML Syntax.uncheck_terms: "Proof.context -> term list -> term list"} \\
   230   @{index_ML Syntax.uncheck_terms: "Proof.context -> term list -> term list"} \\
   235   \end{mldecls}
   231   \end{mldecls}
   236 
   232 
   237   \<^descr> @{ML Syntax.check_typs}~\<open>ctxt Ts\<close> checks a simultaneous list
   233   \<^descr> @{ML Syntax.check_typs}~\<open>ctxt Ts\<close> checks a simultaneous list of pre-types
   238   of pre-types as types of the logic.  Typically, this involves normalization
   234   as types of the logic. Typically, this involves normalization of type
   239   of type synonyms.
   235   synonyms.
   240 
   236 
   241   \<^descr> @{ML Syntax.check_terms}~\<open>ctxt ts\<close> checks a simultaneous list
   237   \<^descr> @{ML Syntax.check_terms}~\<open>ctxt ts\<close> checks a simultaneous list of pre-terms
   242   of pre-terms as terms of the logic. Typically, this involves type-inference
   238   as terms of the logic. Typically, this involves type-inference and
   243   and normalization term abbreviations. The types within the given terms are
   239   normalization term abbreviations. The types within the given terms are
   244   treated in the same way as for @{ML Syntax.check_typs}.
   240   treated in the same way as for @{ML Syntax.check_typs}.
   245 
   241 
   246   Applications sometimes need to check several types and terms together. The
   242   Applications sometimes need to check several types and terms together. The
   247   standard approach uses @{ML Logic.mk_type} to embed the language of types
   243   standard approach uses @{ML Logic.mk_type} to embed the language of types
   248   into that of terms; all arguments are appended into one list of terms that
   244   into that of terms; all arguments are appended into one list of terms that
   249   is checked; afterwards the type arguments are recovered with @{ML
   245   is checked; afterwards the type arguments are recovered with @{ML
   250   Logic.dest_type}.
   246   Logic.dest_type}.
   251 
   247 
   252   \<^descr> @{ML Syntax.check_props}~\<open>ctxt ts\<close> checks a simultaneous list
   248   \<^descr> @{ML Syntax.check_props}~\<open>ctxt ts\<close> checks a simultaneous list of pre-terms
   253   of pre-terms as terms of the logic, such that all terms are constrained by
   249   as terms of the logic, such that all terms are constrained by type @{typ
   254   type @{typ prop}. The remaining check operation works as @{ML
   250   prop}. The remaining check operation works as @{ML Syntax.check_terms}
   255   Syntax.check_terms} above.
   251   above.
   256 
   252 
   257   \<^descr> @{ML Syntax.uncheck_typs}~\<open>ctxt Ts\<close> unchecks a simultaneous
   253   \<^descr> @{ML Syntax.uncheck_typs}~\<open>ctxt Ts\<close> unchecks a simultaneous list of types
   258   list of types of the logic, in preparation of pretty printing.
   254   of the logic, in preparation of pretty printing.
   259 
   255 
   260   \<^descr> @{ML Syntax.uncheck_terms}~\<open>ctxt ts\<close> unchecks a simultaneous
   256   \<^descr> @{ML Syntax.uncheck_terms}~\<open>ctxt ts\<close> unchecks a simultaneous list of terms
   261   list of terms of the logic, in preparation of pretty printing. There is no
   257   of the logic, in preparation of pretty printing. There is no distinction for
   262   distinction for propositions here.
   258   propositions here.
   263 
   259 
   264 
   260 
   265   These operations always operate simultaneously on a list; use the combinator
   261   These operations always operate simultaneously on a list; use the combinator
   266   @{ML singleton} to apply them to a single item.
   262   @{ML singleton} to apply them to a single item.
   267 \<close>
   263 \<close>