Skip to main content
Erschienen in:
Buchtitelbild

Open Access 2018 | OriginalPaper | Buchkapitel

Towards Certified Meta-Programming with Typed Template-Coq

verfasst von : Abhishek Anand, Simon Boulier, Cyril Cohen, Matthieu Sozeau, Nicolas Tabareau

Erschienen in: Interactive Theorem Proving

Verlag: Springer International Publishing

Aktivieren Sie unsere intelligente Suche, um passende Fachinhalte oder Patente zu finden.

search-config
loading …

Abstract

Template-Coq (https://​template-coq.​github.​io/​template-coq) is a plugin for Coq, originally implemented by Malecha [18], which provides a reifier for Coq terms and global declarations, as represented in the Coq kernel, as well as a denotation command. Initially, it was developed for the purpose of writing functions on Coq’s AST in Gallina. Recently, it was used in the CertiCoq certified compiler project [4], as its front-end language, to derive parametricity properties [3], and to extract Coq terms to a CBV \(\lambda \)-calculus [13]. However, the syntax lacked semantics, be it typing semantics or operational semantics, which should reflect, as formal specifications in Coq, the semantics of Coq’s type theory itself. The tool was also rather bare bones, providing only rudimentary quoting and unquoting commands. We generalize it to handle the entire Calculus of Inductive Constructions (CIC), as implemented by Coq, including the kernel’s declaration structures for definitions and inductives, and implement a monad for general manipulation of Coq’s logical environment. We demonstrate how this setup allows Coq users to define many kinds of general purpose plugins, whose correctness can be readily proved in the system itself, and that can be run efficiently after extraction. We give a few examples of implemented plugins, including a parametricity translation. We also advocate the use of Template-Coq as a foundation for higher-level tools.

1 Introduction

Meta-programming is the art of writing programs (in a meta-language) that produce or manipulate programs (written in an object language). In the setting of dependent type theory, the expressivity of the language permits to consider the case were the meta and object languages are actually the same, accounting for well-typedness. This idea has been pursued in the work on inductive-recursive (IR) and quotient inductive-inductive types (QIIT) in Agda to reflect a syntactic model of a dependently-typed language within another one [2, 9]. These term encodings include type-correctness internally by considering only well-typed terms of the syntax, i.e. derivations. However, the use of IR or QIITs complicates considerably the meta-theory of the meta-language which makes it difficult to coincide with the object language represented by an inductive type. More problematically in practice, the concision and encapsulation of the syntactic encoding has the drawback that it is very difficult to use because any function from the syntax can be built only at the price of a proof that it respects typing, conversion or any other features described by the intrinsically typed syntax right away.
Other works have taken advantage of the power of dependent types to do meta-programming in a more progressive manner, by first defining the syntax of terms and types; and then defining out of it the notions of reduction, conversion and typing derivation [11, 26] (the introduction of [11] provides a comprehensive review of related work in this area). This can be seen as a type-theoretic version of the functional programming language designs such as Template Haskell [22] or MetaML [24]. This is also the approach taken by Malecha in his thesis [18], where he defined Template-Coq, a plugin which defines a correspondence—using quoting and unquoting functions—between Coq kernel terms and inhabitants of an inductive type representing internally the syntax of the calculus of inductive constructions (CIC), as implemented in Coq. It becomes thus possible to define programs in Coq that manipulate the representation of Coq terms and reify them as functions on Coq terms. Recently, its use was extended for the needs of the CertiCoq certified compiler project [4], which uses it as its front-end language. It was also used by Anand and Morissett [3] to formalize a modified parametricity translation, and to extract Coq terms to a CBV \(\lambda \)-calculus [13]. All of these translations however lacked any means to talk about the semantics of the reified programs, only syntax was provided by Template-Coq. This is an issue for CertiCoq for example where both a non-deterministic small step semantics and a deterministic call-by-value big step semantics for CIC terms had to be defined and preserved by the compiler, without an “official” specification to refer to.
This paper proposes to remedy this situation and provides a formal semantics of Coq’s implemented type theory, that can independently be refined and studied. The advantage of having a very concrete untyped description of Coq terms (as opposed to IR or QIITs definitions) together with an explicit type checker is that the extracted type-checking algorithm gives rise to an OCaml program that can directly be used to type-check Coq kernel terms. This opens a way to a concrete solution to bootstrap Coq by implementing the Coq kernel in Coq. However, a complete reification of CIC terms and a definition of the checker are not enough to provide a meta-programming framework in which Coq plugins could be implemented. One needs to get access to Coq logical environments. This is achieved using a monad that reifies Coq general commands, such as lookups and declarations of constants and inductive types.
As far as we know this is the only reflection framework in a dependently-typed language allowing such manipulations of terms and datatypes, thanks to the relatively concise representation of terms and inductive families in CIC. Compared to the MetaCoq project [27], Lean ’s tactic monad [12], or Agda ’s reflection framework [26], our ultimate goal is not to interface with Coq’s unification and type-checking algorithms, but to provide a self-hosted, bootstrappable and verifiable implementation of these algorithms. On one hand, this opens the possibility to verify the kernel’s implementation, a problem tackled by Barras [6] using set-theoretic models. On the other hand we also advocate for the use of Template-Coq as a foundation on which higher-level tools can be built: meta-programs implementing translations, boilerplate-generating tools, domain-specific proof languages, or even general purpose tactic languages.
Plan of the Paper. In Sect. 2, we present the complete reification of Coq terms, covering the entire CIC and define in Sect. 3 the type-checking algorithm of Coq reified terms in Coq. In Sect. 4, we show the definition of a monad for general manipulation of Coq’s logical environment and use it to define plugins for various translations from Coq to Coq (Sect. 5). Finally, we discuss related and future work in Sect. 6.

2 Reification of Coq Terms

Reification of Syntax. The central piece of Template-Coq is the inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq3_HTML.gif which represents the syntax of Coq terms, as defined in Fig. 1. This inductive follows directly the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq4_HTML.gif datatype of Coq terms in the OCaml code of Coq, except for the use of OCaml ’s native arrays and strings; an upcoming extension of Coq [5] with such features should solve this mismatch.
Constructor https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq5_HTML.gif represents variables bound by abstractions (introduced by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq6_HTML.gif ), dependent products (introduced by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq7_HTML.gif ) and local definitions (introduced by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq8_HTML.gif ), the natural number is a De Bruijn index. The https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq9_HTML.gif is a printing annotation.
Sorts are represented with https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq10_HTML.gif , which takes a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq11_HTML.gif as argument. A universe is the supremum of a (non-empty) list of level expressions, and a level is either https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq12_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq13_HTML.gif , a global level or a De Bruijn polymorphic level variable. The application (introduced by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq14_HTML.gif ) is n-ary. The https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq15_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq16_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq17_HTML.gif constructors represent references to constants (definitions or axioms), inductives, or constructors of an inductive type. The https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq18_HTML.gif are non-empty only for polymorphic constants. Finally, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq19_HTML.gif represents pattern-matchings, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq20_HTML.gif primitive projections, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq21_HTML.gif fixpoints and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq22_HTML.gif cofixpoints.
Quoting and Unquoting of Terms. Template-Coq provides a lifting from concrete syntax to reified syntax (quoting) and the converse (unquoting). It can reify and reflect all kernel Coq terms.
The command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq23_HTML.gif reifies the syntax of a term. For instance, generates the term https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq24_HTML.gif defined as
On the converse, the command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq25_HTML.gif constructs a term from its syntax. This example below defines https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq26_HTML.gif to be https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq27_HTML.gif of type \(\mathbb {N}\). where https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq29_HTML.gif is the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq30_HTML.gif inductive of the mutual block of the name https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq31_HTML.gif .
Reification of Environment. In Coq, the meaning of a term is relative to an environment, which must be reified as well. Environments consist of three parts: (i) a graph of universes (ii) declarations of definitions, axioms and inductives (iii) a local context registering types of De Bruijn indexes.
As we have seen in the syntax of terms, universe levels are not given explicitly in Coq. Instead, level variables are introduced and constraints between them are registered in a graph of universes. This is the way typical ambiguity is implemented in Coq. A constraint is given by two levels and a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq32_HTML.gif Then the graph is given by a set of level variables and one of constraints. Sets, coming from the Coq standard library, are implemented using lists without duplicates. https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq33_HTML.gif means the type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq34_HTML.gif of the module https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq35_HTML.gif . Functions to query the graph are provided, for the moment they rely on a naive implementation of the Bellman-Ford algorithm. https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq36_HTML.gif checks if the graph enforces https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq37_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq38_HTML.gif checks that the graph has no negative cycle.
Constant and inductive declarations are grouped together, properly ordered according to dependencies, in a global context ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq39_HTML.gif ), which is a list of global declarations ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq40_HTML.gif ). Definitions and axioms just associate a name to a universe context, and two terms for the optional body and type. Inductives are more involved: In Coq internals, there are in fact two ways of representing a declaration: either as a “declaration” or as an “entry”. The kernel takes entries as input, type-check them and elaborate them to declarations. In Template-Coq, we provide both, and provide an erasing function https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq41_HTML.gif from declarations to entries for inductive types.
Finally, local contexts are just list of local declarations: a type for lambda bindings and a type and a body for let bindings.
Quoting and Unquoting the Environment. Template-Coq provides the command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq42_HTML.gif to quote an environment. This command crawls the environment and quote all declarations needed to typecheck a given term.
The other way, the commands https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq43_HTML.gif allows declaring an inductive type from its entry. For instance the following redefines a copy of \(\mathbb {N}\):
More examples of use of quoting/unquoting commands can be found in the file https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq46_HTML.gif .

3 Type Checking Coq in Coq

In Fig. 2, we present (an excerpt of) the specification of the typing judgment of the kernel of Coq using the inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq47_HTML.gif . It represents all the typing rules of Coq1. This includes the basic dependent lambda calculus with lets, global references to inductives and constants, the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq48_HTML.gif construct and primitive projections. Universe polymorphic definitions and the well-formedness judgment for global declarations are dealt with as well.
The only ingredients missing are the guard check for fixpoint and productivity of cofixpoints and the positivity condition of mutual (co-) inductive types. They are work-in-progress.
The typing judgment https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq49_HTML.gif is mutually defined with https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq50_HTML.gif to account for n-ary applications. Untyped reduction https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq51_HTML.gif and cumulativity https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq52_HTML.gif can be defined separately.
Implementation. To test this specification, we have implemented the basic algorithms for type-checking in Coq, that is, we implement type inference: given a context and a term, output its type or produce a type error. All the rules of type inference are straightforward except for cumulativity. The cumulativity test is implemented by comparing head normal forms for a fast-path failure and potentially calling itself recursively, unfolding definitions at the head in Coq’s kernel in case the heads are equal. We implemented weak-head reduction by mimicking Coq’s kernel implementation, which is based on an abstract machine inspired by the KAM. Coq’s machine optionally implements a variant of lazy, memoizing evaluation (which can have mixed results, see Coq’s PR #555 for example), that feature has not been implemented yet.
The main difference with the OCaml implementation is that all of the functions are required to be shown terminating in Coq. One possibility could be to prove the termination of type-checking separately but this amounts to prove in particular the normalization of CIC which is a complex task. Instead, we simply add a fuel parameter to make them syntactically recursive and make https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq53_HTML.gif a type error, i.e., we are working in a variant of the option monad.
Bootstrapping It. We can extract this checker to OCaml and reuse the setup described in Sect. 2 to connect it with the reifier and easily derive a (partialy verified) alternative checker for Coq’s https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq54_HTML.gif object files. Our plugin provides a new command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq55_HTML.gif for typechecking definitions using the alternative checker, that can be used as follows: Our initial tests indicate that its running time is comparable to the coqchk checker of Coq, as expected.

4 Reification of Coq Commands

Coq plugins need to interact with the environment, for example by repeatedly looking up definitions by name, declaring new constants using fresh names, or performing computations. It is desirable to allow such programs to be written in Coq (Gallina) because of the two following advantages. Plugin-writers no longer need to understand the OCaml implementation of Coq and plugins are no longer sensitive to changes made in the OCaml implementation. Also, when plugins implementing syntactic models are proven correct in Coq, they provide a mechanism to add axioms to Coq without compromising consistency (Sect. 5.3).
In general, interactions with the environment have side effects, e.g. the declaration of new constants, which must be described in Coq’s pure setting. To overcome this difficulty, we use the standard “free” monadic setting to represent the operations involved in interacting with the environment, as done for instance in Mtac [27].
Table 1.
Main Template-Coq commands
Vernacular command
Reified command with its arguments
Description
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq56_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq57_HTML.gif
Returns the evaluation of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq58_HTML.gif following the evaluation strategy https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq59_HTML.gif ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq60_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq61_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq62_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq63_HTML.gif or https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq64_HTML.gif )
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq65_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq66_HTML.gif
Makes the definition https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq67_HTML.gif and returns the created constant https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq68_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq69_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq70_HTML.gif
Adds the axiom https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq71_HTML.gif of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq72_HTML.gif and returns the created constant https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq73_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq74_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq75_HTML.gif
Generates an obligation of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq76_HTML.gif , returns the created constant https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq77_HTML.gif after all obligations close
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq78_HTML.gif or https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq79_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq80_HTML.gif
Returns https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq81_HTML.gif if https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq82_HTML.gif is a constant in the current environment and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq83_HTML.gif is the corresponding global reference. Returns https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq84_HTML.gif otherwise.
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq85_HTML.gif
Returns the syntax of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq86_HTML.gif (of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq87_HTML.gif )
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq88_HTML.gif
Returns the syntax of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq89_HTML.gif and all the declarations on which it depends
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq90_HTML.gif
Returns the declaration of the inductive https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq91_HTML.gif
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq92_HTML.gif
Returns the declaration of the constant https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq93_HTML.gif , if https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq94_HTML.gif is https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq95_HTML.gif the implementation bypass opacity to get the body of the constant
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq96_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq97_HTML.gif
Adds the definition https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq98_HTML.gif where https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq99_HTML.gif is denoted by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq100_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq101_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq102_HTML.gif
Declares the inductive denoted by the declaration https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq103_HTML.gif
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq104_HTML.gif
Returns the pair https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq105_HTML.gif where https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq106_HTML.gif is the term whose syntax is https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq107_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq108_HTML.gif it’s type
 
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq109_HTML.gif
Returns the term whose syntax is https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq110_HTML.gif and checks that it is indeed of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq111_HTML.gif
https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq112_HTML.gif is an inductive family (Fig. 3) such that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq113_HTML.gif represents a program which will finally output a term of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq114_HTML.gif . There are special constructor https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq115_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq116_HTML.gif to provide (freely) the basic monadic operations. We use the monadic syntactic sugar https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq117_HTML.gif for https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq118_HTML.gif .
The other operations of the monad can be classified in two categories: the traditional Coq operations ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq119_HTML.gif to declare a new definition, ...) and the quoting and unquoting operations to move between Coq term and their syntax or to work directly on the syntax ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq120_HTML.gif to declare a new inductive from its syntax for instance). An overview is given in Table 1.
A program https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq121_HTML.gif of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq122_HTML.gif can be executed with the command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq123_HTML.gif . This command is thus an interpreter for https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq124_HTML.gif , implemented in OCaml as a traditional Coq plugin. The term produced by the program is discarded but, and it is the point, a program can have many side effects like declaring a new definition or a new inductive type, printing something, ....
Let’s look at some examples. The following program adds the definitions https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq125_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq126_HTML.gif to the current context.
The program below asks the user to provide an inhabitant of \(\mathbb {N}\) (here we provide https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq128_HTML.gif ) and records it in the lemma https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq129_HTML.gif ; prints its normal form ; and records the syntax of its normal form in https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq130_HTML.gif (hence of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq131_HTML.gif ). We use Program ’s obligation mechanism2 to ask for missing proofs, running the rest of the program when the user finishes providing it. This enables the implementation of interactive plugins.

5 Writing Coq Plugins in Coq

The reification of syntax, typing and commands of Coq allow writing a Coq plugin directly inside Coq, without requiring another language like OCaml and an external compilation phase.
In this section, we describe three examples of such plugins: (i) a plugin that adds a constructor to an inductive type, (ii) a re-implementation of Lasson ’s parametricity plugin3, and (iii) an implementation of a plugin that provides an extension of CIC—using a syntactic translation—in which it is possible to prove the negation of functional extensionality [8].

5.1 A Plugin to Add a Constructor

Our first example is a toy example to show the methodology of writing plugins in Template-Coq. Given an inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq132_HTML.gif , we want to declare a new inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq133_HTML.gif which corresponds to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq134_HTML.gif plus one more constructor.
For instance, let’s say we have a syntax for lambda calculus: And that in some part of our development, we want to consider a variation of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq135_HTML.gif with a new constructor, e.g., https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq136_HTML.gif . Then we declare https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq137_HTML.gif with the plugin by: This command has the same effect as declaring the inductive https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq138_HTML.gif by hand: but with the benefit that if https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq139_HTML.gif is changed, for instance by adding one new constructor, then https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq140_HTML.gif is automatically changed accordingly. We provide other examples in the file https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq141_HTML.gif , e.g. with mutual inductives.
We will see that it is fairly easy to define this plugin using Template-Coq. The main function is https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq142_HTML.gif which takes an inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq143_HTML.gif (whose type is not necessarily https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq144_HTML.gif if it is an inductive family), a name https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq145_HTML.gif for the new constructor and the type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq146_HTML.gif of the new constructor, abstracted with respect to the new inductive.
It works in the following way. First the inductive type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq147_HTML.gif is quoted, the obtained term https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq148_HTML.gif is expected to be a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq149_HTML.gif constructor otherwise the function fails. Then the declaration of this inductive is obtained by calling https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq150_HTML.gif , the constructor is reified too, and an auxiliary function is called to add the constructor to the declaration. After evaluation, the new inductive type is added to the current context with https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq151_HTML.gif .
It remains to define the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq152_HTML.gif auxiliary function to complete the definition of the plugin. It takes a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq153_HTML.gif which is the declaration of a block of mutual inductive types and returns a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq154_HTML.gif .
The declaration of the block of mutual inductive types is a record. The field https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq155_HTML.gif contains the list of declarations of each inductive of the block. We see that most of the fields of the records are propagated, except for the names which are translated to add some primes and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq156_HTML.gif the list of types of constructors, for which, in the case of the relevant inductive ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq157_HTML.gif is its number), the new constructor is added.

5.2 Parametricity Plugin

We now show how Template-Coq permits to define a parametricity plugin that computes the translation of a term following Reynolds’ parametricity [21, 25]. We follow the already known approaches of parametricity for dependent type theories [7, 15], and provide an alternative to Keller and Lasson’s plugin.
The definition in the unary case is described in Fig. 4. The soundness theorem ensures that, for a term t of type A, \([t]_1\) computes a proof of parametricity of \([t]_0\) in the sense that it has type \([A]_1\, [t]_0\). The definition of the plugin goes in two steps: first the definition of the translation on the syntax of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq161_HTML.gif in Template-Coq and then the instrumentation to connect it with terms of Coq using the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq162_HTML.gif . It can be found in the file https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq163_HTML.gif .
The parametricity translation of Fig. 4 is total and syntax directed, the two components of the translation \([\ ]_0\) and \([\ ]_1\) are implemented by two recursive functions https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq166_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq167_HTML.gif .
On Fig. 4, the translation is presented in a named setting, so the introduction of new variables does not change references to existing ones. That’s why, \([\ ]_0\) is the identity. In the De Bruijn setting of Template-Coq, the translation has to take into account the shift induced by the duplication of the context. Therefore, the implementation https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq169_HTML.gif of \([\ ]_0\) is not the identity anymore. The argument https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq171_HTML.gif of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq172_HTML.gif represents the De Bruijn level from which the variables have been duplicated. There is no need for such an argument in https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq173_HTML.gif , the implementation of \([\ ]_1\), because in this function all variables are duplicated.
The parametricity plugin not only has to be defined on terms of CIC but also on additional terms dealing with the global context. In particular, constants are translated using a translation table which records the translations of previously processed constants. If a constant is not in the translation table we return a dummy https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq175_HTML.gif , considered as an error (this could also be handled by an option monad).
We have also implemented the translation of inductives and pattern matching. For instance the translation of the equality type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq176_HTML.gif produces the inductive type: Then \([\mathtt {eq}]_1\) is given by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq178_HTML.gif and \([\mathtt {eq\_refl}]_1\) by \(\mathtt {eq\_refl^t}\).
Given https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq181_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq182_HTML.gif the translation of the declaration of a block of mutual inductive types is not so hard to get. Indeed, such a declaration mainly consists of the arities of the inductives and the types of constructors; and the one of the translated inductive are produced by translation of the original ones. In a similar manner, we can translate pattern-matching. Note that the plugin does not support fixpoints and cofixpoints for the moment.
Now, it remains to connect this translation defined on reified syntax https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq183_HTML.gif to terms of Coq. For this, we define the new command https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq184_HTML.gif in the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq185_HTML.gif . When https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq186_HTML.gif is a definition, the command recovers the body of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq187_HTML.gif (as a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq188_HTML.gif ) using https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq189_HTML.gif and then translates it and records it in a new definition https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq190_HTML.gif . The command returns the translation table https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq191_HTML.gif extended by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq192_HTML.gif . In the case https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq193_HTML.gif is an inductive type or a constructor then the command does basically the same but extends the translation table with both the inductive and the constructors. If https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq194_HTML.gif is an axiom or not a constant the command fails.
Here is an illustration coming from the work of Lasson [16] on the automatic proofs of (\(\omega \)-)groupoid laws using parametricity. We show that all function of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq196_HTML.gif are identity functions. First we need to record the translations of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq197_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq198_HTML.gif in a term https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq199_HTML.gif of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq200_HTML.gif . Then we show that every parametric function on https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq201_HTML.gif is pointwise equal to the identity using the predicate https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq202_HTML.gif . Then we define a function https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq203_HTML.gif \(p \mapsto p \centerdot p^{\text{-1 }} \centerdot p\) and get its parametricity proof using the plugin. It is then possible to deduce automatically that \(p \centerdot p^{\text{-1 }} \centerdot p = p\) for all \(p:x=y\).

5.3 Intensional Function Plugin

Our last illustration is a plugin that provides an intensional flavour to functions and thus allows negating functional extensionality (FunExt). This is a simple example of syntactical translation which enriches the logical power of Coq, in the sense that new theorems can be proven (as opposed to the parametricity translation which is conservative over CIC). See [8] for an introduction to syntactical translations and a complete description of the intensional function translation.
Even if the translation is very simple as it just adds a boolean to every function (Fig. 5), this time, it is not fully syntax directed. Indeed the notation for pairs hide some types: and we can not recover the type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq207_HTML.gif from the source term. There is thus a mismatch between the lambdas which are not fully annotated and the pairs which are.4
However we can use the type inference algorithm of Sect. 3 implemented on Template-Coq terms to recover the missing information. Compared to the parametricity plugin, the translation function has a more complex type as it requires the global and local contexts. However, we can generalize the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq208_HTML.gif command so that it can be used for both the parametricity and the intensional function plugins. The implementation is in the files https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq209_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq210_HTML.gif .
Extending Coq Using Plugins. The intensional translation extends the logical power of Coq as it is possible for instance to negate FunExt. In this perspective, we defined a new command: which computes the translation https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq211_HTML.gif of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq212_HTML.gif , then asks the user to inhabit the type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq213_HTML.gif by generating a proof obligation and then safely adds the axiom https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq214_HTML.gif of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq215_HTML.gif to the current context. By safely, we mean that the correction of the translation ensures that no inconsistencies are introduced.
For instance, here is how to negate FunExt. We use for that two pairs https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq216_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq217_HTML.gif in the interpretation of functions from https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq218_HTML.gif to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq219_HTML.gif , which are extensionally both the identity, but differ intensionally on their boolean. where https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq220_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq221_HTML.gif are special versions of the corresponding https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq222_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq223_HTML.gif tactics of Coq to deal with extra booleans appearing in the translated terms. After this command, the axiom https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq224_HTML.gif belongs to the environment, as if it where added with the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq225_HTML.gif command. But as we have inhabited the translation of its type, the correctness of the translation ensures that no inconsistency were introduced.
Note that we could also define another translation, e.g. the setoid translation, in which FunExt is inhabited. This is not contradictory as the two translations induce two different logical extensions of Coq, which can not be combined.
Meta-Programming is a whole field of research in the programming languages community, we will not attempt to give a detailed review of related work here. In contrast to most work on meta-programming, we provide a very rough interface to the object language: one can easily build ill-scoped and ill-typed terms in our framework, and staging is basic. However, with typing derivations we provide a way to verify meta-programs and ensure that they do make sense.
The closest cousin of our work is the Typed Syntactic Meta-Programming [11] proposal in Agda, which provides a well-scoped and well-typed interface to a denotation function, that can be used to implement tactics by reflection. We could also implement such an interface, asking for a proof of well-typedness on top of the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq226_HTML.gif primitive of our monad.
Intrinsically typed representations of terms in dependent type-theory is an area of active research. Most solutions are based on extensions of Martin-Löf Intensional Type Theory with inductive-recursive or quotient inductive-inductive types [2, 9], therefore extending the meta-theory. Recent work on verifying soundness and completeness of the conversion algorithm of a dependent type theory (with natural numbers, dependent products and a universe) in a type theory with IR types [1] gives us hope that this path can nonetheless be taken to provide the strongest guarantees on our conversion algorithm. The intrinsically-typed syntax used there is quite close to our typing derivations.
Another direction is taken by the Œuf certified compiler [19], which restricts itself to a fragment of Coq for which a total denotation function can be defined, in the tradition of definitional interpreters advocated by Chlipala [10]. This setup should be readily accommodated by Template-Coq.
The translation + plugin technique paves the way for certified translations and the last piece will be to prove correctness of such translations. By correctness we mean computational soundness and typing soundness (see [8]), and both can be stated in Template-Coq. Anand has made substantial attempts in this direction to prove the computational soundness, in Template-Coq, of a variant of parametricity providing stronger theorems for free on propositions [3]. This included as a first step a move to named syntax that could be reused in other translations.
Our long term goal is to leverage this technique to extend the logical and computational power of Coq using, for instance, the forcing translation [14] or the weaning translation [20].
When performance matters, we can extract the translation to OCaml and use it like any ordinary Coq plugin. This relies on the correctness of extraction, but in the untyped syntax + typing judgment setting, extraction of translations is almost an identity pretty-printing phase, so we do not lose much confidence. We can also implement a template monad runner in OCaml to run the plugins outside Coq. Our first experiments show that we could gain a factor 10 for the time needed to compute the translation of a term. Another solution would be to use the certified CertiCoq compiler, once it supports a kind of foreign function interface, to implement the https://static-content.springer.com/image/chp%3A10.1007%2F978-3-319-94821-8_2/470383_1_En_2_IEq227_HTML.gif evaluation.
The last direction of extension is to build higher-level tools on top of the syntax: the unification algorithm described in [28] is our first candidate. Once unification is implemented, we can look at even higher-level tools: elaboration from concrete syntax trees, unification hints like canonical structures and type class resolution, domain-specific and general purpose tactic languages. A key inspiration in this regard is the work of Malecha and Bengston [17] which implemented this idea on a restricted fragment of CIC.

Acknowledgments

This work is supported by the CoqHoTT ERC Grant 64399 and the NSF grants CCF-1407794, CCF-1521602, and CCF-1646417.
Open Access This chapter is licensed under the terms of the Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/), which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made.
The images or other third party material in this chapter are included in the chapter's Creative Commons license, unless indicated otherwise in a credit line to the material. If material is not included in the chapter's Creative Commons license and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.
Fußnoten
1
We do not treat metavariables which are absent from kernel terms and require a separate environment for their declarations.
 
2
In Coq, a proof obligation is a goal which has to be solved to complete a definition. Obligations were introduced by Sozeau [23] in the Program mode.
 
4
Note that there is a similar issue with applications and projections, but which can be circumvented this time using (untyped) primitive projections.
 
Literatur
3.
Zurück zum Zitat Anand, A., Morrisett, G.: Revisiting parametricity: inductives and uniformity of propositions. In: CoqPL 2018, Los Angeles, CA, USA (2018) Anand, A., Morrisett, G.: Revisiting parametricity: inductives and uniformity of propositions. In: CoqPL 2018, Los Angeles, CA, USA (2018)
6.
Zurück zum Zitat Barras, B.: Auto-validation d’un système de preuves avec familles inductives. Thèse de doctorat, Université Paris 7, November 1999 Barras, B.: Auto-validation d’un système de preuves avec familles inductives. Thèse de doctorat, Université Paris 7, November 1999
7.
Zurück zum Zitat Bernardy, J.P., Jansson, P., Paterson, R.: Proofs for free: parametricity for dependent types. J. Funct. Program. 22(2), 107–152 (2012)MathSciNetCrossRef Bernardy, J.P., Jansson, P., Paterson, R.: Proofs for free: parametricity for dependent types. J. Funct. Program. 22(2), 107–152 (2012)MathSciNetCrossRef
8.
Zurück zum Zitat Boulier, S., Pédrot, P.M., Tabareau, N.: The next 700 syntactical models of type theory. In: CPP 2017, pp. 182–194. ACM, Paris (2017) Boulier, S., Pédrot, P.M., Tabareau, N.: The next 700 syntactical models of type theory. In: CPP 2017, pp. 182–194. ACM, Paris (2017)
10.
Zurück zum Zitat Chlipala, A.: Certified Programming with Dependent Types, vol. 20. MIT Press, Cambridge (2011)MATH Chlipala, A.: Certified Programming with Dependent Types, vol. 20. MIT Press, Cambridge (2011)MATH
12.
Zurück zum Zitat Ebner, G., Ullrich, S., Roesch, J., Avigad, J., de Moura, L.: A metaprogramming framework for formal verification, pp. 34:1–34:29, September 2017 Ebner, G., Ullrich, S., Roesch, J., Avigad, J., de Moura, L.: A metaprogramming framework for formal verification, pp. 34:1–34:29, September 2017
16.
Zurück zum Zitat Lasson, M.: Canonicity of weak \(\omega \)-groupoid laws using parametricity theory. Electron. Notes Theor. Comput. Sci. 308, 229–244 (2014)MathSciNetCrossRef Lasson, M.: Canonicity of weak \(\omega \)-groupoid laws using parametricity theory. Electron. Notes Theor. Comput. Sci. 308, 229–244 (2014)MathSciNetCrossRef
18.
Zurück zum Zitat Malecha, G.M.: Extensible proof engineering in intensional type theory. Ph.D. thesis, Harvard University (2014) Malecha, G.M.: Extensible proof engineering in intensional type theory. Ph.D. thesis, Harvard University (2014)
21.
Zurück zum Zitat Reynolds, J.C.: Types, abstraction and parametric polymorphism. In: IFIP Congress, pp. 513–523 (1983) Reynolds, J.C.: Types, abstraction and parametric polymorphism. In: IFIP Congress, pp. 513–523 (1983)
25.
Zurück zum Zitat Wadler, P.: Theorems for free! In: Functional Programming Languages and Computer Architecture, pp. 347–359. ACM Press (1989) Wadler, P.: Theorems for free! In: Functional Programming Languages and Computer Architecture, pp. 347–359. ACM Press (1989)
Metadaten
Titel
Towards Certified Meta-Programming with Typed Template-Coq
verfasst von
Abhishek Anand
Simon Boulier
Cyril Cohen
Matthieu Sozeau
Nicolas Tabareau
Copyright-Jahr
2018
DOI
https://doi.org/10.1007/978-3-319-94821-8_2