Syntactic metaprogramming enables programs to manipulate code fragments by generating, embedding or evaluating them. It can be seen in many applications such as macros, staged computation and proof assistants. Type safety of syntactic metaprogramming is extensively researched especially for staged computation, and many type systems including MetaML [13, 22] have been developed. Under the Curry-Howard isomorphism , those type systems correspond to constructive modal logic including S4 modal logic [7, 17] and linear temporal logic [6, 23]. While those modal type theories give logical foundations of various aspects of staged computation, the logical counterpart of manipulation of variable binding structures has been unclear. MacroML  and SND , which are surface type systems on MetaML, tackle this problem, but they only allow a restricted form of binding manipulation.
Nanevski’s contextual modal type theory (CMTT)  partly solves this problem. CMTT extends S4 modal types to have context, where stands for an open code of type under the environment . Contextual modal types allow programs access to free variables in open code, and hence enables to express binding manipulation. However, contextual modal types are less flexible than those of linear temporal types in some cases. For example, a linear temporal type stands for a function that takes open code under arbitrary environment. CMTT cannot express this type because contextual modal type only accepts specific context . Nanevski and Pfenning  proposed support polymorphism for this purpose in their former work, but its relation to neither contextual modality nor is not formalized.
We aim to give a logical foundation for syntactic metaprogramming with flexible binding manipulation. To this end, we introduce two novel type theories. First one is , which is a Fitch-style reconstruction of Nanevski’s contextual modal type theory. This reconstruction generalizes contextual modality to accommodate K, T, K4 and S4 modalities and gives lisp-like quasiquotation syntax, which many macro systems adopt [11, 16]. The second one is , which is a generalization of with contextual polymorphism. The notion of contextual polymorphism is obtained by internalizing context weakening of hypothetical judgment. Despite the logical background of contextual polymorphism, it also endows excellent expressibility of code generation. Finally, we formally show that terms are embeddable to terms, through context extraction.
Organization. Section 2 presents former results of logical foundations of syntactic meta-programming and compare our work with them. Section 3 shows how to reconstruct contextual modal type theory based on Fitch-style judgment. Section 4 extends Fitch-style contextual modal type theory by introducing contextual polymorphism. Section 5 proves that can be embedded into . Section 6 concludes the paper.
2 Related Work
2.1 Modal Type Theory and Staged Computation
Through the research on the Curry-Howard isomorphism between logics and calculi, it is considered that constructive modal logic corresponds to multi-stage calculi.
In staged computation, two kinds of modalities have been mainly used. Davies’ corresponds to linear temporal logic. The type can be interpreted as “open code of type T”, and provides logical basis for MetaML  and its variant MetaOCaml . is not capable of run-time code evaluation because evaluating code at a different stage will cause “undefined variable error”. Taha and Nielsen’s  solves this problem by labeling stages with environment classifiers. Tsukada and Igarashi’s  provides a logical foundation of
, where environment classifiers are interpreted as polymorphism over stage transitions. Polymorphic contexts inand environment classifiers are similar notions in the sense that both are polymorphism related to environments. However, they are essentially different notions: environment classifiers abstract stage transition while polymorphic contexts abstract context itself.
Another is S4 modality, which we simply call “box modality”. A box modal type can be interpreted as “closed code of type T”. S4 modal types are capable of code evaluation both at run-time and through multiple stages, and hence they are used as a logical foundation for code evaluation [7, 13, 24]. We refer to two formulations for box modalities. Dual-context formulation [17, 7] uses two-level hypothetical judgment to describe S4 modality and introduces meta variables as terms. Recent work of Kavvos  generalizes dual-context formulation to K, T, K4 and GL modality. On the other hand, Fitch-style formulation [12, 18, 7, 4] uses hypothetical judgment with context stack and introduces lisp-like quasiquotation syntax. Martini and Masini  point out that this formulation introduces K, T, K4 and S4 modalities. These formulations are compared by Davies and Pfenning  for the case of S4 modality, and they prove both formulations are logically equivalent.
2.2 Contextual Modal Type Theory
There is some work that generalizes box modality with environment[10, 14, 19]. CMTT by Nanevski et al.  provides logical foundations for those calculi. CMTT generalizes S4 modality of dual-context into contextual modality. is a Fitch-style reconstruction of CMTT, and hence it allows K, T, K4 and S4 modalities.
Fitch-style formulation makes it easier to reason calculi with quasiquotation from the viewpoint of contextual modality. and by Kim et al.  are multi-stage calculi with quasiquotation syntax, and and can be regarded as their logical foundations. Particularly, introduces let-polymorphism for type environment, which is the special case of polymorphic contexts in . and by Rhiger  are also multi-staged calculi similar to both and .
Contextual modal types and linear temporal types are similar in that they handle open code. In fact, the existence of embeddings from into and was claimed. However, the former embedding is claimed to be unsound by Davies . The latter embedding to Rhiger’s is also unsound. One of the counterexamples is the type judgment , which is translated into an ill-typed judgment. Therefore our translation into K is the first work that formalizes the relationship between contextual modal types and linear temporal types.
Contextual modality is also applied in proof assistants. Nanevski et al. provide contextual extension of dependent types in their work of CMTT. Cave and Pientka [2, 3] develop it as the basis of Beluga, a programming language for theorem proving. Beluga can type object-level LF terms with contextual types, and it uses first-class contexts as meta-level values. First-class contexts of Beluga are similar to polymorphic contexts in ; we consider there may be close a relationship between them.
3 Fitch-Style Contextual Modal Type Theory
In this section, we introduce Fitch-style contextual modal type theory . First, we informally explain quasiquotation syntax and Fitch-style hypothetical judgment. Then we give a formal description of the calculus and its properties. Finally, we show examples.
3.1 Quasiquotation with Explicit Environment
Quasiquotation plays an essential role in syntactic metaprogramming, especially in macros [11, 16]. However, a naive implementation of quasiquotation causes unintended variable capture. The bind macro in Common Lisp reveals the problem.
(defmacro bind (x) ‘(lambda (y) ,x))
This macro takes a code fragment x and embed it into a lambda expression. Therefore
(bind (+ x y)) will expand to
(lambda (y) (+ x y)), where y is captured by the introduced lambda expression. The problem is that this bind macro captures free variables no matter whether the programmer intends. In practice, Common Lisp provides gensym which generates fresh identifier which does not conflict with existing identifiers.
Our solution to this problem is to annotate quasiquotation with explicit environment. In this approach, quoted codes come with their environments like ‘<x y>(+ x y). Here, the part <x y> represents free variables of code. Unquotation comes with definition of free variables like ,<z (+ z w)>x. Therefore, ,<z (+ z w)>‘<x y>(+ x y) is equivalent to (+ z (+ z w)). With this idea, the bind macro can be rewritten as follows.
(defmacro bind1 (x) ‘<y>(lambda (z) ,<y z>x)) (defmacro bind2 (x) ‘<y z>(lambda (w) ,<y z>x))
Both macros assume that x is a code with two free variables and unquote x with instantiating its free variables with y and z. bind1 binds the second free variable in x while bind2 introduces a lambda abstraction which binds nothing.
Still, those macros produce broken codes given unintended inputs e.g. with free variables not listed in the annotations, or given inconsistent terms, e.g., with quotations and unquotations with unmatched numbers of variables in the annotations. To avoid this, we propose adequate type systems by exploiting Fitch-style hypothetical judgments.
3.2 Fitch-style Formulation of Contextual Modality
In the long history of modal logic, many formulations of natural deduction were proposed. Some work extends hypothetical judgment to handle multiple meta-levels [1, 12, 18, 7] although they differ in notation. We call this idea Fitch-style following Clouston .
In natural deduction for propositional logic, a hypothetical judgment states that “ holds assuming ”. Fitch-style formulation generalizes this to have a context stack as following.
In this judgment, each context in the context stack is an assumption for each meta-level: for object level, for meta level, for meta-meta level and so on.
Using Fitch-style hypothetical judgments, contextual modality is defined by following rules. Here we write for a context stack. -introduction states that object-level hypothetical judgment corresponds to contextual modality . -elimination is defined so that they make proof-theoretic harmony.
I for E
It is worth noting that this rules corresponds to K modal logic when is always empty. We can also obtain T, K4 and S4 contextual modality slightly changing the elimination rule ins the same way as Martini and Masini’s method .
The syntax of is given as follows. We write for variables and .
For a context , we write for the domain (i.e., the list of variables) of , and for the range (i.e., the list of types) of . Any context is required that its domain is distinct. Note that it is acceptable that the domains of contexts in a context stack overlap, like . In , free variables have their levels: is the set of level- free variables in , which corresponds to the -th context in the context stack.
A type is either a base type, a function type or a contextual modal type. In addition to the standard -terms, two terms are added. A quotation stands for code, where binds . An unquotation stands for code evaluation. Term/type sequence are also added to the syntax. We assume that -renaming is implicitly performed whenever it is necessary to avoid variable capture.
3.4 Type System
Figure 1 shows the typing rules in . The judgment denotes that has type under the context stack , and the judgment denotes that each term of has each type of . In the rules (Var), (Abs), and (App), variables in the object-level context are only concerned. The rules (Quo) and (Unq) correspond to introduction and elimination of contextual modal types.
By slightly changing the rule, We can think of four variations of (Unq). K is the most basic variant where is always 1. T variant allows , K4 variant allows , and S4 variant allows both. We write when holds especially in of variant for each .
There are two sorts of meta operations in : substitution and level-substitution. We omit the definitions, which is obtained by extending those of Fitch-style modal calculus [12, 7]. For , a substitution is a meta operation that maps a term to a term. It substitutes level- free variables in a term with terms , respectively. We also write for point-wise composition when and are the same length. The following substitution lemma formally states the property of substitution.
Lemma 3.1 (Substitution Lemma).
If and where , then .
For and , a level substitution is a meta operation that maps a term to a term. Proof theoretically, a level substitution manipulates the structure of the context-stack. The following lemma formally states this idea. Note that this lemma varies among four variations K, T, K4, and S4.
Lemma 3.2 (Level Substitution Lemma).
If holds, then also holds for any if and in K, in T, in K4, and in S4.
3.5 Reduction and Expansion
Now we are ready to define -reduction and -expansion rules.
-reduction and -expansion are the relations on terms which are closed under the following rules and congruence rules, which are omitted here.
|when is defined|
Theorem 3.4 (Subject Reduction/Expansion).
If and , then .
If and , then .
Strong normalization can be proved by extending Martini and Masini’s method , which proves strong normalization of Fitch-style modal calculi through a translation to the implicational fragment of simply typed lambda calculus. Confluence is derived from strong normalization, weak confluence and Newmann’s lemma .
enjoys strong normalization, weak confluence, and confluence.
We show some examples of terms. We omit type annotation of abstraction due to the limitation of space. (1-3) correspond to the contextual variant of modal axioms K, T and 4. Contextual modality may be viewed as a metatheoretical framework of propositional logic. (4-6) represent weakening, exchange, and contraction of hypothetical judgment.
From the viewpoint of syntactic metaprogramming, can handle open code. Suppose has the if statement and the boolean type. The or macro, which takes two code fragments
y and produces
if x then true else y, can be represented as .
This or macro has the type , where and are code fragments of type under the context . We can also represent the bind macro, which was introduced in the beginning of this section, as the following terms:
bind1 has type , and bind2 has type . Given a code fragment of type , bind1 binds the free variable in of type while bind2 binds nothing.
4 Polymorphic Context
While contextual modal types enable us to handle open code with explicit context, the type system is too strict to be used in practice. Let us review the example of the or macro. Its type only accepts code with context , so we have to define different functions for all possible contexts. This inflexibility is critical when we attempt to apply contextual modality in real-world code generation.
To solve this problem, we introduce polymorphic context to contextual modality. Using polymorphic context, the type of the generalized or macro is generalized as . In this type, is a context variable which stands for an arbitrary context and quantifies occurrences of . This or macro accepts code with arbitrary context by substituting .
From the viewpoint of the Curry-Howard isomorphism, polymorphic context is interpreted as the internalization of context weakening. In natural deduction for propositional logic, weakening can be written as the following statement.
If holds then also holds for any context .
Here, a meta variable stands for arbitrary context irrelevant to the proof. We gain polymorphic context by embedding this meta variable into the object system of natural deduction. As a result, context weakening is written as where is now an object variable.
When we assign terms, we obtain another sort of variables, weakening variables which we denote by or . In a type system, contexts come with variables which label each assumption. This principle is also applied to context variables. For example, assigning terms to a judgment , we obtain the following type judgment.
A weakening variable stands for a sequence of variables distinct from the rest of the context ( and in this case), and therefore stands for a context. When we substitute with some context, is also replaced by a sequence of variables which are fresh to and . Therefore we gain the following judgment substituting with .
This is the basic concept of polymorphic context. In the rest of this section, we give formal definition and properties of as an extension of with polymorphic context. subsumes hypothetical judgment as quotation and unquotation, and therefore the discussion on context variables in hypothetical judgment is generalized to terms and types.
Let be the set of context variables and the set of weakening variables. We use meta variables , and . terms and types are defined as follows in addition to .
The type is polymorphic context type which abstracts a context variable while a context abstraction and a context application correspond to the introduction and elimination rules for polymorphic context type. Context variables and weakening variables extend type sequences, term sequences, and contexts. This extension is natural since context variables stand for sequences of types while weakening variables stand for sequences of variables.
Free variables and free weakening variables are defined as free variables in . Besides, we define the set of free context variables of objects as follows. Note that free context variables do not have a level, as opposed to variables or weakening variables.
|Type Sequence, Term Sequence,
Context, Context Stack
|(omitted: defined as point-wise union)|
The additional typing rules of are shown in Figure 2. For the sequence judgment, (SeqC) is added for weakening variables and context variables. This addition indirectly changes the (Quo) and (Unq) rules. For the term judgment, (Poly) and (Inst) rules are added which corresponds to the introduction and elimination rules for polymorphic context type. Those rules are similar to the rules for polymorphic type in System F : a context variable can be quantified when there is no free occurrence in the context stack, and a quantified context variable can be replaced by any type sequence.
In , there are three kinds of substitution. Level substitution is almost the same as that of . Term substitution is obtained by generalizing substitution in . In , substitution content is defined inductively as follows.
Given a substitution content and a level , a term substitution is a meta-operation on terms. We omit the definition because it is almost the same as substitution in .
In addition, a meta operation called context substitution is defined for . Given a type sequence and a context variable , context substitution is a meta operation inductively defined on objects (see Figure 3).
|Type Sequence, Term Sequence|
|(omitted||: defined point-wise)|
Although most of the cases are straightforward, the definition for the case of a quotation is quite complicated. The basic idea is that to replace free occurrences of in is to weaken the context . performs weakening inductively and returns a pair of a context and a substitution content where stands for the replaced context, and for how weakening variables corresponding to are to be substituted with fresh variables.
Given a type sequence and a context variable , is defined using some auxiliary functions. is the main component of . Given a finite set of variables and fresh variables , generates a sequence of variables which are fresh with respect to .
We also define context substitution on type judgment.
As a result, the following context substitution lemma holds.
Lemma 4.1 (Context Substitution Lemma).
If holds, holds for any and .
4.3 Reduction/Expansion Rules
Given a context and a term sequence , we define a substitution where , and .
-reduction and -reduction are the relations closed under the following rules and congruence rules, which we omit here.
|when is defined|
Theorem 4.3 (Subject Reduction/Expansion).
If and , then .
If and , then .
As in Section 3, admits generalized modal axioms and metatheorems of hypothetical judgments. For example, context weakening is represented as .
From the viewpoint of syntactic metaprogramming, polymorphic context allows flexible manipulation of open code. As discussed in the beginning of this section, the or macro is generalized as the term . It is typed as and thus accepts code with any environment by virtue of polymorphic context. The bind macros can also be represented as the following term:
bind1 has type , and bind2 has type . Clearly, bind1 macro binds free variable of type among the context while bind2 binds no variable in . The point is that weakening variables , will not be replaced with bound variables such as due to capture avoiding substitution. This systematically prevents macros from unintended variable capture. In other words, polymorphic context preserves lexical scoping and achieves hygienic code generation.
5 Context Extraction for Linear Temporal Type Theory
As we have seen, allows flexible manipulation of open code. In this section, we formalize the relationship between K and by giving a sound translation from to K , which extracts implicit contexts of . We call this translation context extraction. The key observation is the following construction: with K-S4 modality, it is known that the proposition is not provable. However, a very similar proposition is, in fact, provable with polymorphic context.
This suggests has some relation to , which is characterized by the axiom . We further analyze this relation in the following.
5.1 as Fitch-style Linear Temporal Type Theory
Figure 4 shows an overview of the type theory . Although this definition is arranged in accordance with , it is essentially the same as the formulation given by Davies [5, 6]. Variables and base types in are common with those of . To distinguish from those of , we use meta variables for types. This convention is also applied to other kinds of metavariables for . Note that and have nothing to do with each other.
In , type judgments are in form . The difference from and is the existence of two context stacks which represent time axis: the rightmost context in represents the current context, the rest of represents past contexts, and represents future contexts. The rules (Quo) and (Unq) correspond to the introduction and elimination rules for linear temporal types, in which the current position is moved in the time axis.
|Past Context Stack|
|Future Context Stack|
5.2 Context Extraction
First we introduce the notion of context/type sequence allocator. We fix for the set of context, and for the set of type sequence. We also write and for the concatenation of and , and .
Definition 5.1 (Context / Type Sequence Allocator).
A context allocator is a function . For context allocators and , we define the following operations on context allocators.
is a context allocator where
is a cotext allocator where and .
is a context allocator where .
A type sequence allocator is a function . For type sequence allocators and , type sequence allocators , , are defined in the same way as the case of context allocators.
For a context allocator , the range of , written as , is a type sequence allocator where .
is an empty context allocator where .
For a type , the context depth of , written as , is inductively defined as follows:
For , generates a pair of a context allocator and a sequence of context variables:
where for fresh variables and
Now we are ready to define a translation from types to types. We use the following abbreviations for context abstraction/application. Given a sequence of context variables , we write for and for . Given a type sequence allocator , we write for .
Definition 5.3 (Context Extraction for Linear Temporal Types).
Given a type sequence allocator , we define a translation from types to types: