Next Article in Journal
Q-Rung Probabilistic Dual Hesitant Fuzzy Sets and Their Application in Multi-Attribute Decision-Making
Previous Article in Journal
Ridge Fuzzy Regression Modelling for Solving Multicollinearity
 
 
Font Type:
Arial Georgia Verdana
Font Size:
Aa Aa Aa
Line Spacing:
Column Width:
Background:
Article

Coinductive Natural Semantics for Compiler Verification in Coq †

1
Posgrado en Ciencia e Ingeniería de la Computación, Instituto de Investigaciones en Matemáticas Aplicadas y en Sistemas, Universidad Nacional Autónoma de México, Mexico City 04510, Mexico
2
Instituto de Ingeniería, Universidad Nacional Autónoma de México, Mexico City 04510, Mexico
*
Author to whom correspondence should be addressed.
This paper is an extension of: Zúñiga, A.; Bel-Enguix, G. A Correct Compiler from Mini-ML to a Big-Step Machine Verified Using Natural Semantics in Coq. In Proceedings of the XVIII Jornadas de PROgramación y LEnguajes (PROLE 2018), Seville, Spain, 17–19 September 2018.
Mathematics 2020, 8(9), 1573; https://doi.org/10.3390/math8091573
Submission received: 4 July 2020 / Revised: 1 September 2020 / Accepted: 9 September 2020 / Published: 12 September 2020
(This article belongs to the Section Mathematics and Computer Science)

Abstract

:
(Coinductive) natural semantics is presented as a unifying framework for the verification of total correctness of compilers in Coq (with the feature that a verified compiler can be obtained). In this way, we have a simple, easy, and intuitive framework; to carry out the verification of a compiler, using a proof assistant in which both cases are considered: terminating and non-terminating computations (total correctness).

1. Introduction

This paper tackles the problem of compiler verification in proof assistants. At present, a number of long-term projects deals with several aspects of this issue, for instance, CompCert C [1,2,3,4,5], CertiCoq [6], and IRIS [7]. In this work, we address specifically the verification of total correctness of compilers of functional languages in Coq. Here, we refer to total correctness in the sense of Leroy [8] and Gregoire and Leroy [9], that is total correctness means: correctness of terminating and non-terminating computations.
In the literature, ad-hoc verifications are traditionally used; meaning, verifications that employ more than one distinct formalism.
This situation calls for a solution that abstracts away everything needed in a single unifying framework that simplifies (and perhaps, it could even make possible to automate) this task. By  unifying framework we mean a single formalism able to define each of the components of a compiler, namely: source language semantics, intermediate language semantics, abstract machine semantics, and  translations. In fact, in this work we offer (coinductive) natural semantics as a simple, easy and intuitive unifying framework to carry out (total correctness) compiler verification in Coq. Whenever we use ‘framework’, and we are referring to the (coinductive) natural semantics unifying framework as presented in this work (and only to it), we mean ‘unifying framework’. In this manner, we remark that only one formalism, (coinductive) natural semantics, is sufficient to conduct this task as opposed to usual verifications in the literature where more than one distinct formalism are needed in order to accomplish the same goal (see Section 1.1 for a discussion of the related work). In our preliminary work [10] we only address correctness for termination. In this extended and improved version, as the main novelty, we also tackle correctness for non-termination (which is the most challenging one).
Natural semantics, as introduced by Kahn [11], was initially a unifying framework. Indeed, since its inception [11], natural semantics has been able to express: source language semantics, intermediate languages semantics, abstract machine semantics and translations. Despeyroux [12] also showed how natural semantics allows proof of the correctness of the translations. Based on the work of Kahn and Despeyroux, Boutin [13] formalized a compiler from Mini-ML to the CAM in Coq (although it is not possible to obtain a verified compiler from his formalization).
It is folklore that natural semantics, as originally introduced by Kahn [11], is unqualified to express non-terminating computations (the articles of Kahn, Despeyroux, and Boutin, only address the case of terminating computations.) More precisely, Despeyroux made a preliminary attempt to cover infinite computations but it is based on denotational semantics instead of natural semantics per se. However, since the introduction of coinductive natural semantics by Leroy [14] and Leroy and Grall [15] it is a well-known practice to use a coinductively defined natural semantics to deal with non-terminating program behavior. Leroy [14] and Leroy and Grall [15] advance coinductive natural semantics as a formalism to express non-terminating computations; however, they do not use coinductive natural semantics as a unifying framework in the original sense of Kahn, but they use it only to specify the source language (a high-level language). Specifically, they make an ad-hoc formalization in which, in addition, they use small-step semantics in (what was later called) the Modern SECD (MSECD) machine [8] and a function to define the compilation.
The main idea of this work is to extend natural semantics so that it becomes a simple, easy, and intuitive unifying framework for verifying total correctness of compilers in Coq (with the ability that you can get a verified compiler that can be used in real life).
The strategy for carrying out this extension is as follows: until now, taking as reference the work of Boutin, natural semantics can be used for formalizing the correctness of a compiler in Coq (only for the termination case and a verified compiler cannot be obtained). The first thing we will do is to show how, from a natural semantics specification, one can obtain, either an interpreter (Section 2.1) or a compiler (Section 2.3.1) sound and complete regarding the natural semantics specification. Then, for natural semantics to be able to express non-terminating computations, we will use Leroy’s coinductive natural semantics. However, this semantics has only been used in the source language, in addition, we will show how to use coinductive natural semantics to specify non-terminating computations in an abstract machine (Section 3.3). We will also show that an interpreter, which was previously obtained from natural semantics, is sound and complete regarding its corresponding coinductive natural semantics specification (Section 3.1), that is, for the non-termination criteria (and not only for the termination case). In this way, we are ready to formulate and prove the correctness (semantic preservation) of a compiler, both for the termination case (Section 2.3.2), and, for the non-termination case (Section 3.3.2), completely in terms of (coinductive) natural semantics.
To illustrate the use of (coinductive) natural semantics as a framework, we mechanized a compiler from Mini-ML to a big-step version of the Modern SECD machine. We were interested in showing that in particular, (coinductive) natural semantics can express translations among high-level languages, as well as translations from a high-level language to machine code (a low-level language). Therefore, our compiler is composed of two phases (see Figure 1): translation of Mini-ML with named variables ( MiniML ) to Mini-ML in de Bruijn notation ( MiniML dB ), as an instance of the first one, and generation of code of the (big-step version of the) Modern SECD machine from Mini-ML in de Bruijn notation (Section 2.3 and Section 3.3), as an instance of the second one. In this work, we will concentrate on the code generation phase which is the most interesting one.
Traditionally, in the literature small-step semantics is used in the machine. That is why, as an alternative target machine, we offer the original small-step semantics Modern SECD machine (Section 2.2 and Section 3.2) extended to support all Mini-ML features, in particular, with native recursion support, mainly to compare it with our solution, in which a big-step machine is used, i.e., our Modern SECD machine big-step version.

1.1. Related Work

Since CompCert C [1,2,3,4,5] project’s inception led by Leroy, there has been great progress in the literature dedicated to compiler verification using proof assistants, Coq in particular. In this work, we address specifically functional programming languages verification. In principle, verification of functional programming languages to abstract machines.
An unusual technique exposed by Hardin et al. [16] to carry out the verification of a functional language to an abstract machine is to use small-step semantics, both in the source language and in the abstract machine, together with a decompilation function and a measure to establish correctness. The idea of this technique is to perform a bottom-up simulation in which every machine transition corresponds to zero or one source level reductions. The machine states are mapped back to source level expressions using a decompilation function. More precisely, if from a machine state s a state s is reached via a machine transition s s , and e is the source language expression corresponding to the state s via decompilation, then there exists an expression e corresponding to s via decompilation, such that e = e or e reduces to e via source language small-step semantics e e . When a machine performs a transition from a state to another and the decompilation of both states corresponds to the same expression in the source language, the machine performs a silent transition. To guarantee that there are not infinitely many silent machine transitions, a measure defined on the machine states is used. i.e., if  s s and the decompilation of s and s corresponds to the same expression e, then s measure is greater than that of s .
Gregoire and Leroy [9] and Gregoire [17] use this technique to verify a compiler from a strong reduction lambda calculus to an abstract machine in Coq; more precisely, to verify the correctness of a compiler from the Calculus of Inductive Constructions (CIC) to a variant of the ZAM machine [18] (adapted to support weak symbolic reduction), obtaining a compiler-based verified implementation to evaluate Coq terms. In addition, they show that this compiler-based implementation is more efficient than the original Coq interpreter as expected. More recently, Kunze et al. [19] employ a very similar technique to verify the correctness of a compiler from a call-by-value lambda calculus to an abstract machine in Coq.
However, Leroy [8,14] and Leroy and Grall [15] point out that a correctness proof using this technique is difficult, and also that the definition of a decompilation is complicated, hard to reason about, and hard to extend (especially for optimizing compilation phases). In consequence, they propose a solution based on big-step semantics. In fact, they state that proving semantic preservation for compilers both for terminating and diverging programs using big-step semantics is the original motivation of their work.
The Leroy [14] and Leroy and Grall [15] technique consists of using (coinductive) big-step semantics in the source language but small-step semantics in the machine. In this way, for the termination case, if a source language expression e evaluates to v via big-step semantics e v , then reducing the machine code c via transitive closure of small-step semantics + , takes the machine to a state with v m at the top of the stack, where c corresponds to e compilation and v m is the machine value corresponding to v. For the non-termination case, if e diverges using coinductive big-step semantics, then c also diverges in the machine. Leroy and Grall mention that their technique provides a simpler way to prove semantics preservation, in particular for the non-termination case.
Currently, it is well known [14,15,20,21] that big-step semantics are easier and more convenient for compiler correctness proofs, and also for efficient interpreters [21]. Thus, we have on one hand that Leroy and Grall main motivation is to use big-step semantics for compiler correctness proofs, and on the other that big-step semantics has proved to be easier and more convenient for compiler correctness proofs. Our aim is to take big-step semantics to its deepest consequences exploiting it where it has proved to be useful. This is why we propose (coinductive) natural semantics as framework for compiler verification.
(Coinductive) natural semantics as framework for compiler verification in Coq as proposed in this paper is a technique very similar in spirit to that of Leroy and Grall, but going further since not only (coinductive) big-step semantics is used in the source language but also in the target machine (let us recall that Leroy and Grall employ small-step semantics in the machine). Furthermore, to the best of the author’s knowledge, it is the first time that coinductive natural semantics is proposed and used to define computations that do not terminate in an abstract machine. In this way, we obtain a fully-based (coinductive) natural semantics technique for a functional language to an abstract machine compiler correctness verification in Coq.
Establishing correctness is even easier, intuitive and simple since natural semantics are also used in the machine. If a source language expression e is evaluated to a value v via source language natural semantics e v , then c is evaluated to a final machine state with v m at the top of the stack via machine natural semantics s c v m · s ; where c is the compilation of e via natural semantics e c , and  v m is the compilation of v via natural semantics v v m , and s is any machine stack. If e diverges via coinductive natural semantics e , then c also diverges via machine coinductive natural semantics s c . We can note here, how only (coinductive) natural semantics is sufficient to establish correctness; we do not need to use any other distinct formalism.
A potential use of this framework is to take it as basis to verify a conventional compiler to abstract machine implementation of (the core of) a realistic functional language such as OCaml. The official INRIA OCaml implementation comes with two compilers [22], the first one generates code of the ZAM machine, and the second one generates C-- code. We speculate that this framework can also be used as basis to verify the compiler that generates C-- since Dargaye [23] already uses big-step semantics (although not as unifying framework and only tackling terminating computations) to verify a compiler from Mini-ML to Cminor (an early intermediate language of the CompCert C compiler). The idea of generating Cminor (or some other Compcert C intermediate language) code instead of C-- is immediate since, in this way, we can connect the compiler’s back-end to CompCert C and obtain as final result verified assembly code. This use takes more relevance if we take into account that Coq itself is an OCaml program (even though some portions of Coq are verified in Coq [24,25,26], the extracted verified OCaml code will eventually run on an OCaml implementation).
Another line of work is dedicated to systematically derive an abstract machine from a lambda calculus [27,28,29,30,31,32,33]. The general idea in these works is from a lambda calculus to carry out a series of transformations until the desired abstract machine is obtained. One of the most exploited transformations in some of these works is refocusing [34], although a great variety of transformations are used. The compilation correctness is a direct consequence of the correctness of the transformations. Some of them, in addition, address Coq formalization [29,30,31,32,33]. The closest works to ours are those which starting from a natural semantics of a lambda calculus derive an abstract machine [27,30]. Specifically, the most similar work in nature to ours is [30]. In [30], the STG machine is derived from natural semantics of a lazy lambda calculus and the derivation is formalized in Coq. However, in  [30] only the case for terminating computations is tackled.
In all these works, the emphasis is on the corresponding machine derivation. In contrast, in a functional language implementation the target abstract machine is usually designed by hand and only then (if any) proved correct w.r.t source lambda calculus semantics (see, for example, [18]). Hence, (coinductive) natural semantics as framework as presented in this paper is best suited to verify functional languages implementations (which targets abstract machines), since it assumes that the target machine (and intermediate languages) are given (not to be derived).
Moreover, if for some reason (for example, semantic justification of the target abstract machine) it is considered relevant to systematically derive the target abstract machine from the source calculus, we conjecture that the corresponding derivation can also be carried out in our (coinductive) natural semantics framework. This is because each transformation which leads to the derived machine could be seen as an (intermediate) translation and be defined in natural semantics. Also, the input and output language of each transformation could be seen as an (intermediate) language and its corresponding semantics be defined in natural semantics. Certainly, the derived abstract machine would be a big-step machine.
Other works tackle the verification of a small functional language in Coq, but to the authors’ knowledge none of them use (coinductive) natural semantics as unifying framework; instead, they use ad-hoc verifications. For instance, Chlipala [35] offers a compiler from a small impure functional language to an idealized assembly language. He starts from de Bruijn notation and employs natural semantics for the source and target languages, but not to specify the compilation, his effort only cover terminating computations. Benton and Hur [36] deal with the compilation of a small typed functional language to the SECD machine, but they use denotational semantics for the source language and small-step semantics for the target machine. In addition, Benton and Hur employ a biorthogonality step-indexed logical relation to establish correctness. As mentioned before, Dargaye [23] develops a compiler from Mini-ML to C minor, but it is not designed to be a standalone general-purpose Mini-ML implementation. Instead, it was conceived to work only on the code generated by the Coq extraction mechanism. The Coq extraction mechanism generates code of a real-life functional language, by default OCaml, but it is also able to generate Scheme and Haskell code. This is why in Dargaye’s work, it only makes sense to cover terminating computations since the Coq’s calculus, the Calculus of Inductive Constructions, is strongly normalizing [37], meaning in Coq all computations must terminate. For this reason, all extracted code from Coq should be terminating, while in Coq this property is ensured by Coq’s type checker [26]; the code generation translation performed by the Coq extraction mechanism is not verified, although some efforts are conducted in this direction [6,24,25,38,39,40].
The CertiCoq project [6,40,41] aims to provide a verified extraction pipeline from the core language of Coq, Gallina, to machine language. Therefore, in CertiCoq it also only makes sense to cover terminating computations. This fact is explicitly stated in [6]: ‘… we can restrict our reasoning to terminating programs since Coq is strongly normalizing. This way we avoid backward simulations (forward simulations proofs are much simpler) and avoid proving preservation of divergence’. Similarly, Savary Bélanger [40] indicates: ‘In CertiCoq, we are only concerned with terminating programs: Gallina is strongly normalizing, and our proof of correctness ensures that programs do not acquire non-terminating behaviors along the way’.
Instead of producing machine code directly, CertiCoq generates C light (a CompCert C intermediate language) code. Hence, it uses CompCert C as verified compiler back-end to produce machine language. This way, CertiCoq compiler performs a series of phases from Galllina to Cligth. In CertiCoq, (intermediate) languages semantics and proofs of correctness are based on big-step semantics (for terminating computations). However, big-step semantics is refined with other notions such as step-indexed logical relations and context-based semantics [40,42] to account for additional properties, for instance, compositionality. In addition, the idea of adapting this technique to be useful for general-purpose programming languages is barely mentioned in [40]. Albeit, for this purpose, Savary Bélanger [40] suggests to employ small-step semantics. For their part, Paraskevopoulou and Appel [42], in order to prove closure conversion correctness, they already extend this technique to cover non-termination computations under certain conditions. Closure conversion is a phase performed by CertiCoq.
Our (coinductive) natural semantics framework is best suited to verify usual functional language to abstract machine implementations since it accounts for both terminating and non-terminating computations (total correctness). In addition, it can express terminating and non-terminating computations in an abstract machine. In contrast, by design [6] CertiCoq only covers terminating evaluations on one hand, and on the other it targets C light which is why no abstract machine is used. This situation reflects the fact that our (coinductive) natural semantics framework and CertiCoq pursuit different goals. Although our (coinductive) natural semantics framework is a framework to conduct total correctness compiler verification in Coq, CertiCoq is a verified compiler (from Coq’s core calculus to Clight). Hence, it is not an explicit CertiCoq main objective to offer an infrastructure to perform compiler verification [6], even although, the infrastructure and techniques developed to verify the CertiCoq compiler could be adapted to be used to verify other compilers as well.
Step-indexed logical relations as shown by Ahmed [43] serve to establish contextual equivalence between programs. We remark that step-indexed logical relations provide a way to deal with two compiler problems in particular; specifically, compositionality and secure compilation.
In [44], Ahmed and Blume show how to use step-indexed logical relations together with small-step semantics to deal with a notion of secure compilation. Ahmed and Blume demonstrate their method, applying it to a typed closure conversion transformation. Patrignani et al. [45] offer a recent survey of the formal approaches and techniques used in secure compilation. Certainly, this survey includes in particular works that employ step-indexed logical relations. Abate et al. [46] study generalizations of trace-based compiler correctness criteria including some which accounts for secure compilation.
In order to account for compositionality, Perconti and Ahmed [47] propose the use of a language in which all languages involved in a compilation pipeline can be embedded. Then, using a step-indexed logical relation and small-step semantics compositional compiler correctness is established in terms of the combined language. For their part, Neis et al. [48] introduce parametric inter-language simulations (PILS) as a technique particularly suited to compositional compiler verification for higher-order imperative languages. In particular, they demonstrate their technique with Pilsner, a verified compositional compiler from a ML-like language to an assembly-like language. Patterson and Ahmed [49] provide a framework for expressing different notions of compiler correctness, especially those which consider compiler compositionality.
Dreyer et al. [50], in order to avoid tedious, error-prone and obscuring step-indexed arithmetic, instead of using explicit indices, they propose to ‘hide’ indices, internalizing them into a logic. The idea is to replace indices with a modal operator, this way obtaining a modal logic which they name LSLR. In particular, this idea is reused in IRIS. IRIS [7,51,52,53] is a concurrent separation logic framework implemented and verified in Coq. In this regard, Krebbers et al. [53] comment: ‘We also show that the step-indexed “later” modality of Iris is an essential source of complexity, in that removing it leads to a logical inconsistency’. Recently, Linn Georges et al. [54] formalize a capability machine in IRIS. As Linn Georges et al. [54] point out, capability machines are promising targets for secure compilers. Hence, the idea to extend IRIS to be used as secure compiler framework is imminent; in particular, to verify secure compilers from high-level concurrent languages to capability machines. However, to the authors’ knowledge, IRIS has never been used in this manner. A very similar goal is pursued by Cuellar et al. [55] and Cuellar [56] but extending CompCert C. To this end, they introduce the Concurrent Permission Machine (CPM). Certainly, C (with concurrency) is the source language in these works.
In retrospective, on one hand step-indexed logical relations have proved to be useful, in particular in secure compilation, compiler compositionality and concurrency; on the other hand, natural semantics has proved to be easier and more convenient than other formalisms (for instance, small-step semantics) for compiler correctness proofs. Hence, we speculate that both natural semantics and step-indexed logical relations can be combined in a single formalism that has the best properties of each one of them. In other words, we envisage the ambitious goal of reaching a single formalism that features secure compilation, compositional compilation, concurrency and be simple, easy and intuitive as possible.
Currently, our (coinductive) natural semantics framework does not account for secure compilation, compositionality nor concurrency. However, we conjecture that step-indexed logical relations can be adopted in it to address some or even all these features. The price paid for this effort would be to deal with the known complexity of step-indexed logical relations (although it could be ameliorated, for instance, by internalizing the indices in a natural semantics modal logic). At present, our (coinductive) natural semantics framework is simple, easy and intuitive.
The following are related semantics: coinductive big-step operational semantics [14,15], trace-based coinductive operational semantics [57], pretty-big-step semantics [20] and flag-based big-step semantics [21].
The only one of these works that presents the verification of the correctness of a compiler is Leroy’s (an ad-hoc verification). This means that (coinductive) natural semantics is not used in any of them as a unifying framework for the verification of compiler correctness. Specifically, it is not used in the definition of the semantics of the machine (nor in that of its interpreter), it is not used to define the translations, and it is not used (both in the source language and in the target language) to establish, nor to prove the correctness of the translations. What it does, in each of them, is to present a natural semantics with coinduction of a high-level language (which would usually correspond to the source language in a compiler) and it is this aspect that we review next.
Leroy [14] first expresses finite computations with natural semantics ‘evaluation’ and infinite computations ‘divergence’ with coinductive natural semantics, separately; this solution is clear and clean. After, he offers an alternative solution in which one finite and infinite computations are expressed in a single coinductive natural semantics ‘coevaluation’; however, this semantics does not behave well in the sense that on one hand, there are infinite computations that it is not able to express, and on the other, there are infinite computations that are evaluated to any value v. Nakata and Uustalu [57] remark that this behavior appears accidental and undesired.
Nakata and Uustalu [57] define a coinductive natural semantics of the While language that expresses finite and infinite computations; the careful and ad-hoc design of semantics follows, and within it that of small-step semantics. Additionally, Nakata and Uustalu define an interpreter using the trace monad and they show that it is correct regarding such semantics. Nakata and Uustalu’s work [57] is the only one of the related works presented here in which an interpreter is presented.
Charguéraud [20] introduces pretty-big-step semantics, a semantics based on ‘coevaluation’ of Leroy. Unfortunately, pretty-big-step semantics inherits the not well behavior of ‘coevaluation’. In turn, Bach Poulsen and Mosses [21] define flag-based big-step semantics based on pretty-big-step semantics. Unfortunately, flag-based big-step semantics, through pretty-big-step semantics, also inherits the not well behavior of ‘coevaluation’.
In this work, we present (coinductive) natural semantics as a framework for the verification of total correctness of compilers in Coq. Once we have a simple, easy, clear, and intuitive solution for this task, we can seek to improve it in the future. In particular, we use a natural parameter in the interpreters to bound the recursion. Recently, Leroy [58] has defined an interpreter of While using the partiality monad in Coq; we plan to adopt the partiality monad in our Mini-ML compiler and in the framework in general to avoid the use of this parameter.
On the other hand, we can seek to reach a single coinductive natural semantics ‘ c o ’ able to express terminating computations, as well as non-terminating computations. Charguéraud [20] mentions that in principle, this semantics can be used directly to prove total correctness of the translations; however, he points out that the conclusion in the correctness theoremis usually of the form v . ( v v ) ( c c o v ) , and that the current support of coinduction in Coq only allows using coinductive predicates in the conclusion. In particular, it does not allow using the existential quantifier ‘∃’ or the connective ‘∧’ when a proof is done by coinduction. Bach Poulsen and Mosses [21] run a similar criticism to the current coinduction support in Coq. Fortunately, our (coinductive) natural semantics is ideal here since, when using (inductive) natural semantics ‘⇒’ to express finite computations and coinductive natural semantics ‘ ’ to express infinite computations (separately), the proof of the termination case where the conclusion requires an ∃ and an ∧ can be done by induction, whereas, in this way, in the case of non-termination, in the conclusion neither the ∃ nor the ∧ is required, only the coinductive predicate is used, so it can be proved by coinduction (with the current support of Coq).
Even then, it would be possible to aim at having a single semantics in order to have a more concise definition. If so, the framework could automate the translation from it to the two separated semantics (⇒ and ); also, the framework could establish and prove the equivalence between the first one and the union of the last two semantics. Having arrived at these two semantics, the current results of the framework can be used.
The central problem is that (to the authors’ knowledge) to date, there is not a single coinductive natural semantics in the literature that expresses finite and infinite computations, and that it does behave well. The first author, based on Leroy’s ‘coevaluation’, has succeeded in defining a single coinductive natural semantics (of the pure lambda calculus extended with constants) that expresses terminating and non-terminating computations, and that it does behave well in Coq. Also, he has proved the equivalence of this semantics with the union of the two semantics (⇒ and ) that express, respectively, finite and infinite computations separately. Apparently, this result is sound [59] and we plan to present it in future works.
To continue, it would be possible to deal with the problem of decreasing the number of rules necessary in a coinductive natural semantics definition. This is the main goal of pretty-big-step semantics and flag-based big-step semantics. To this end and going further, we envisage that the results in this work and those of pretty-big-step semantics and flag-based big-step semantics (future work and perhaps other works as well) can be integrated in a coinductive natural semantics framework having all the desired properties of each of them. In other words, it is our intention that the resulting coinductive natural semantics framework synthesizes all the major advances in natural semantics.

1.2. Contributions

Our main general and specific contributions are:
  • The (coinductive) natural semantics as a framework for the verification of total correctness of compilers in Coq. Such that a working standalone verified compiler, meaning, a compiler sound and complete regarding (coinductive) natural semantics specification and correct regarding semantic preservation of the specified translation can be obtained as a final product
  • A systematic method to obtain either a sound or complete interpreter (Section 2.1 and  Section 3.1) or compiler (Section 2.3.1), as applicable, from a (coinductive) natural semantics specification
  • The use of coinductive natural semantics to specify non-terminating computations in an abstract machine (Section 3.3)
  • A compiler from Mini-ML to a big-step version of the Modern SECD machine including its total correctness verification in Coq (Section 2.1Section 2.3Section 3.1 and Section 3.3)
  • An extended version of the original small-step semantics Modern SECD machine which includes native recursion support (Section 2.2 and Section 3.2)
  • A big-step version of the Modern SECD machine including its formalization in Coq (Section 2.3 and Section 3.3)
  • A coinductive natural semantics specification of non-terminating computations of Mini-ML (extended version of Leroy’s specification of the pure lambda calculus with constants, Section 3.1)
  • A coinductive natural semantics specification of non-terminating computations of the big-step Modern SECD machine (Section 3.3)
  • An algorithm to translate from (an abstract representation of) the (coinductive) natural semantics specification of a total correct compiler to its corresponding formalization in Coq (Section 4)
The strategy for the presentation is, first, to tackle the termination case using natural semantics (Section 2), and then the non-termination case using coinductive natural semantics (Section 3). During this work, the method that we use is to present each of the compiler’s components together with their corresponding Coq formalization; in this way, it is intended that when our compiler is finished, we will have the necessary intuition behind the algorithm to go from a total correct compiler in abstract to Coq (Section 4). Finally, (Section 5), we present our conclusions.

2. Natural Semantics

We will first tackle, in this section, the case in which the computations are finite (terminating) using natural semantics.

2.1. MiniML dB

To begin with, we introduce the source language, Mini-ML, in de Bruijn notation, which is essentially the pure lambda calculus extended with naturals, Booleans, arithmetic and comparison operators, local definitions, conditionals and native recursion by means of a fixed point operator. Its abstract syntax is the following:
d : : = n     Naturals
 ∣ b     Booleans
 ∣  d d   with {+,−,∗,=}     Primitive operators
 ∣  i ̲      Nameless variables (de Bruijn index)
 ∣ ifdthendelsed     Conditionals
 ∣ letdind     Local definition
 ∣  λ . d      Abstraction
 ∣  μ . λ . d      Fixed point
 ∣  d d      Application
Before carrying out the coding of our definitions in Coq, it is important to highlight some of its features. Coq is based on the Calculus of Inductive Constructions, i.e., a lambda calculus with a sophisticated and expressive type system. Since it is a lambda calculus, it can be used as a logic, but also as a programming language, i.e., we can prove propositions, but also write programs. This distinction is made explicit by using the types Prop and Set respectively. Roughly, it can be said that when a term in Coq has type Prop, it is used as logic, and if a term has type Set, then it is used as programming language. In fact, this explicit syntactic distinction between Prop and Set was introduced by the Coq extraction mechanism [60] to distinguish between those terms with computational content and those without it (Paulin-Mohring [60] calls ‘Spec’ what would later be called ‘Set’). In this way, if a term in Coq has a Set type, the extraction mechanism can generate a program written in a general-purpose programming language, such as OCaml, related to this term, in contrast to a term with a Prop type from which is not possible to extract any program at all.
The abstract syntax of MiniML dB can be coded in Coq as first order abstract syntax using an Inductive definition with type Set as follows:
  • Inductive MML_dB_exp: Set :=
  • | Const_dB : nat → MML_dB_exp
  • | …
  • | Letm_dB: MML_dB_exp → MML_dB_exp → MML_dB_exp
  • | …
  • | Lam_dB: MML_dB_exp → MML_dB_exp
  • | Mu_dB: MML_dB_exp → MML_dB_exp
  • | App_dB: MML_dB_exp → MML_dB_exp → MML_dB_exp.
For conciseness, throughout this article, we will show only the essentials parts of the formalization. The full formalization can be consulted in [61].
Hence, the Coq extraction mechanism can be used with the following command:
  • Extraction MML_dB_exp.
which gives as a result:
  • type mML_dB_exp =
  • | Const_dB of nat
  • | …
  • | Letm_dB of mML_dB_exp ∗ mML_dB_exp
  • | …
  • | Lam_dB of mML_dB_exp
  • | Mu_dB of mML_dB_exp
  • | App_dB of mML_dB_exp ∗ mML_dB_exp
This way, we can notice how an Inductive definition with type Set in Coq corresponds to an ADT in OCaml, in this case to the abstract syntax of MiniML dB written in OCaml.
To define the natural semantics of MiniML dB , we first need to define its values by means of environments and closures.
v : : = n   Numbers Ω : : = [   ]   Empty environment
 ∣ b   Booleans    ∣  v · Ω
 ∣  ( λ . d ) [ Ω ]    Closures
 ∣  ( μ . λ . d ) [ Ω ]    Recursive closures
The environments serve as (implicit) associations from variables (represented by de Bruijn indices) to values. In this manner, as expressed by the predicate Ω i ̲ v , the value of a variable represented by the index i ̲ is at the i t h position in the environment (a sequence of values).
v · Ω 0 ̲ v Ω i ̲ v w · Ω S i ̲ v
The natural semantics of MiniML dB is inductively defined by the predicate:
Ω d v
which can be read as follows: in the environment Ω , the expression d is evaluated to the value v.
The Ω environment is supposed to contain the value of the free variables in d. The natural semantics of MiniML dB is defined as follows:
Ω n n Ω b b Ω d 1 n 1 Ω d 2 n 2 Ω d 1 d 2 n 1 n 2
Ω i ̲ v Ω i ̲ v Ω d 1 v 1 v 1 · Ω d 2 v Ω let d 1 in d 2 v
Ω d 1 t r u e Ω d 2 v Ω if d 1 then d 2 else d 3 v Ω d 1 f a l s e Ω d 3 v Ω if d 1 then d 2 else d 3 v
Ω λ . d ( λ . d ) [ Ω ] Ω μ . λ . d ( μ . λ . d ) [ Ω ]
Ω d 1 ( λ . d ) [ Ω 1 ] Ω d 2 v 2 v 2 · Ω 1 d v Ω d 1 d 2 v
Ω d 1 ( μ . λ . d ) [ Ω 1 ] Ω d 2 v 2 v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d v Ω d 1 d 2 v
A natural semantics definition can be seen as an inductive logical proposition; hence, it can be encoded in Coq as an Inductive definition with type Prop. This way the MiniML dB semantics can be written as follows:
  • Inductive MML_dB_NS : MML_dB_env → MML_dB_exp → MML_dB_val → Prop :=
  • | MML_dB_NS_Const:  O:MML_dB_env,  n:nat,
  •     MML_dB_NS O (Const_dB n) (Num_dB n)
  • | …
  • | MML_dB_NS_Let:  O:MML_dB_env,  d1 d2:MML_dB_exp,  v1 v2: MML_dB_val,
  •     MML_dB_NS O d1 v1 →
  •     MML_dB_NS (v1::O) d2 v2 →
  •     MML_dB_NS O (Letm_dB d1 d2) v2
  • | …
  • | MML_dB_NS_Lam:  O:MML_dB_env,  d:MML_dB_exp,
  •     MML_dB_NS O (Lam_dB d) (Clos_dB d O)
  •  
  • | MML_dB_NS_Mu:  O:MML_dB_env,  d:MML_dB_exp,
  •     MML_dB_NS O (Mu_dB d) (Closr_dB d O)
  •  
  • | MML_dB_NS_App:  O O1: MML_dB_env,  d1 d2 d:MML_dB_exp,  v v2:MML_dB_val,
  •     MML_dB_NS O d1 (Clos_dB d O1) →
  •     MML_dB_NS O d2 v2 →
  •     MML_dB_NS (v2::O1) d v →
  •     MML_dB_NS O (App_dB d1 d2) v
  •  
  • | MML_dB_NS_Appr:  O O1:MML_dB_env,  d1 d2 d:MML_dB_exp,  v v2:MML_dB_val,
  •     MML_dB_NS O d1 (Closr_dB d O1) →
  •     MML_dB_NS O d2 v2 →
  •     MML_dB_NS (v2::(Closr_dB d O1)::O1) d v →
  •     MML_dB_NS O (App_dB d1 d2) v.
A natural semantics definition, in general, is a relation; therefore, no determinism is the general case. Then, in case a definition of this kind is deterministic, a lemma that expresses this property must be formally established in the same way we do it for the MiniML dB semantics:
  • Lemma MML_dB_NS_deterministic:
  •  O,  d,  v1, MML_dB_NS O d v1 →
  •              v2, MML_dB_NS O d v2 →
  •                        v1 = v2.
If a relation is deterministic, then it can be stated as a function. Consequently, it can be encoded as function in a programming language. In particular, in Coq, we can write a recursive function employing Fixpoint. For instance, the function corresponding to MiniML dB natural semantics is written as follows:
  • Fixpoint MML_dB_NS_interpreter (depthR:nat )(O:MML_dB_env) (d:MML_dB_exp)
  • : option MML_dB_val :=
  • match depthR with
  • | 0 ⇒ None
  • | S m ⇒ match d with
  •            | Const_dB n ⇒ Some (Num_dB n)
  •            | …
  •            | Letm_dB d1 d2 ⇒
  •              match (MML_dB_NS_interpreter m O d1) with
  •                | Some v1 ⇒ MML_dB_NS_interpreter m (v1::O) d2
  •                | _ ⇒ None
  •              end
  •            | …
  •            | Lam_dB d ⇒ Some (Clos_dB d O)
  •            | Mu_dB d ⇒ Some (Closr_dB d O)
  •            | App_dB d1 d2 ⇒
  •              match (MML_dB_NS_interpreter m O d1) with
  •                | Some (Clos_dB d O1) ⇒
  •                  match MML_dB_NS_interpreter m O d2 with
  •                    | Some v2 ⇒ MML_dB_NS_interpreter m (v2::O1) d
  •                    | _ ⇒ None
  •                  end
  •                | Some (Closr_dB d O1) ⇒
  •                  match MML_dB_NS_interpreter m O d2 with
  •                    | Some v2 ⇒ MML_dB_NS_interpreter m (v2::(Closr_dB d O1)::O1) d
  •                    | _ ⇒ None
  •                  end
  •                | _ ⇒ None
  •              end
  •          end
  • end.
Please note that this function is actually an interpreter. To guarantee termination, we added the natural parameter depthR which indicates the recursion depth (depthR is also called ‘fuel’ by some authors, see, for example [24,25,62,63]). This is because the CIC is strongly normalizing [37], which means, from a programming-language perspective, that all the calculations must terminate. In Coq, this means that all functions must be total and terminating.
From a verification perspective, a logical proposition serves as a formal specification that a program must comply. In this case, the logical proposition is the Inductive definition in Prop whereas the program is the interpreter in Set. Then, to verify that our interpreter is sound with respect to the MiniML dB natural semantics, we must prove the following lemma:
  • Lemma MML_dB_NS_interpreter_soundness:
  •  O,  d,  v, MML_dB_NS O d v →
  •              n, MML_dB_NS_interpreter n O d = Some v.
Conversely, i.e., to verify that our interpreter is complete with respect to MiniML dB natural semantics, we must prove this lemma:
  • Lemma MML_dB_NS_interpreter_completeness:  n,  O,  d,  v,
  • MML_dB_NS_interpreter n O d = Some v →
  • MML_dB_NS O d v.
Now we write factorial of 5 in MiniML dB as a program example:
  • Definition example :=
  • (App_dB (Mu_dB (If_dB (Eq_dB (Var_dB 0) (Const_dB 0))
  •            (Const_dB 1)
  •            (Times_dB (Var_dB 0)
  •                (App_dB (Var_dB 1)
  •                          (Minus_dB (Var_dB 0) (Const_dB 1)))))) (Const_dB 5)).
then, we can evaluate it in our MiniML dB interpreter, inside Coq, as follows:
  • Compute (MML_dB_NS_interpreter 19 nil example).
obtaining just the expected result:
  • = Some (Num_dB 120) : option MML_dB_val
Next, we can use the extraction mechanism as follows:
  • Extraction MML_dB_NS_interpreter.
so, in this way, we obtain a verified interpreter, sound and complete with respect to MiniML dB natural semantics in OCaml, ready to be used in real life.
  • let rec mML_dB_NS_interpreter depthR o d =
  •   match depthR with
  •   | O → None
  •   | S m →
  •     (match d with
  •      | Const_dB n → Some (Num_dB n)
  •      | …
  •      | Letm_dB (d1, d2) →
  •        (match mML_dB_NS_interpreter m o d1 with
  •         | Some v1 → mML_dB_NS_interpreter m (Cons (v1, o)) d2
  •         | None → None)
  •      | …
  •      | Lam_dB d0 → Some (Clos_dB (d0, o))
  •      | Mu_dB d0 → Some (Closr_dB (d0, o))
  •      | App_dB (d1, d2) →
  •        (match mML_dB_NS_interpreter m o d1 with
  •         | Some m0 →
  •           (match m0 with
  •            | Clos_dB (d0, o1) →
  •              (match mML_dB_NS_interpreter m o d2 with
  •               | Some v2 → mML_dB_NS_interpreter m (Cons (v2, o1)) d0
  •               | None → None)
  •            | Closr_dB (d0, o1) →
  •              (match mML_dB_NS_interpreter m o d2 with
  •               | Some v2 →
  •                 mML_dB_NS_interpreter m (Cons (v2, (Cons ((Closr_dB (d0, o1)),
  •                   o1)))) d0
  •               | None → None)
  •            | _ → None)
  •         | None → None))
The reader may question the ‘double’ task of maintaining both definitions, Prop and Set. On one hand, if we stay in the logical part, in Prop, a verified compiler cannot be obtained to be used in real life, while on the other hand, definitions using the Set type forces us to work with total terminating functions.
Let us recall that natural semantics is, in general, inherently relational and, non-deterministic; therefore, to write a natural semantics definition as a function we must ensure that it is total and deterministic. Although for some particular cases this is true, we think that if a natural semantics definition is written directly as a function, the essence of natural semantics vanishes.
Also, Coq automatically generates inductive principles from inductive definitions, which is not the case for functions. These induction principles are useful as they can be used through the induction tactic while doing a proof. In some scenarios, this is an advantage, especially, of course, when a proof is done by induction.
Regarding the remarks above, we give definitions in Prop to retain the essence of natural semantics and to take advantage of the inductive principles generated by Coq. Also, we give the corresponding definitions in Set, mainly to obtain verified implementations.

2.2. Modern SECD Machine

Leroy [8,14] introduces the Modern SECD, a machine based on Landin’s SECD [64] with two main differences: the first one is that it does not use a Dump; instead, it makes use of frames in the stack to support function calls; the second one is that it uses de Bruijn indices to access the environment.
The original Modern SECD only offers natural constants, local definitions, abstraction and application support. Due to this, we offer an extended version of the MSECD to support Booleans, arithmetic and comparison operators, conditionals, and native recursion by means of recursive closures. It is worth mentioning that we made the conditionals support based on Henderson’s SECD presentation [65].
The instructions of the extended MSECD are the following:
i : : = IConst n   Push the natural n
 ∣ IConstb b   Push the Boolean b
 ∣ IAdd   Perform an addition
 ∣ ISub   Perform a subtraction
 ∣ IMul   Perform a multiplication
 ∣ IEq   Perform an equality comparison
 ∣ IAcc i ̲    Push the value of the variable number (de Bruijn index) i ̲
 ∣ ISel c c   Select a conditional branch
 ∣ IJoin   Rejoin the main control (return from conditional)
 ∣ ILet   Add the value of a local defintion variable to the environment
 ∣ IEndLet   Remove the value of a local definition variable from the environment
 ∣ IClos c   Push a closure with code c
 ∣ IClos r e c c   Push a recursive closure with code c
 ∣ IApp   Perform a function application
 ∣ IRet   Return from function
Notice the distinction between ‘i’ and ‘ i ̲ ’, the former denotes a machine instruction, whereas the latter denotes a de Bruijn index.
The code is defined as an instruction sequence:
c : : = [   ]    Empty code
 ∣  i · c
The values of the machine and its environment are defined as follows:
v m : : = n   Naturals Δ : : = [   ]   Empty environment
 ∣ b   Booleans    ∣  v m · Δ
 ∣  c [ Δ ]    Closures
 ∣  c [ Δ ] r e c    Recursive closures
Besides these values, the frames should be able to be stored in the stack. Therefore, the stack values and the stack of the machine are defined as follows:
v s : : = v m   Machine values s : : = [   ]   Empty stack
 ∣  ( c , Δ )   Stack Frames    ∣  v s · Δ
A MSECD machine configuration is a triplet ( c , Δ , s ) where c is a code, Δ is a machine environment, and s is a stack.
The MSECD small-step semantics is a transition relation from a configuration ( c i , Δ i , s i ) to the next ( c i + 1 , Δ i + 1 , s i + 1 ) denoted by: ( c i , Δ i , s i ) ( c i + 1 , Δ i + 1 , s i + 1 ) .
Next, We present the MSECD small-step semantics, shown in Table 1:
To codify this semantics in Coq, we write:
  • Inductive MSECD_SS: conf → conf → Prop :=
  •  MSECD_SS_IConst:  n:nat,  c:code,  D:env,  s:stack,
  •     MSECD_SS (IConst n::c, D, s) (c, D, Val (MInt n)::s)
  • | …
  •  
  • | MSECD_SS_ILet:  c:code,  D:env,  v:val,  s:stack,
  •     MSECD_SS (ILet::c, D, Val v::s) (c, v::D, s)
  •  
  • | MSECD_SS_IEndLet:  c:code,  D:env,  v:val,  s:stack,
  •     MSECD_SS (IEndLet::c, v::D, s) (c, D, s)
  • | …
  •  
  • | MSECD_SS_IClos:  cc c:code,  D:env,  s:stack,
  •     MSECD_SS (IClos cc::c, D, s) (c, D, Val (MClos cc D)::s)
  •  
  • | MSECD_SS_IClosr:  cc c:code,  D:env,  s:stack,
  •     MSECD_SS (IClosr cc::c, D, s) (c, D, Val (MClosr cc D)::s)
  •  
  • | MSECD_SS_IApp:  c c1:code,  D D1:env,  s:stack,  v:val,
  •     MSECD_SS (IApp::c, D, Val v:: Val (MClos c1 D1)::s) (c1, v::D1, SFrame c D::s)
  •  
  • | MSECD_SS_IAppr: c c1:code,  D D1:env,  s:stack,  v:val,
  •     MSECD_SS (IApp::c, D,Val v::Val (MClosr c1 D1)::s) (c1, v::(MClosr c1 D1)::D1,SFrame c D::s)
  •  
  • | MSECD_SS_IReturn:  c c1:code,  D D1:env,  v:val,  s:stack,
  •     MSECD_SS (IRet::c, D, Val v:: SFrame c1 D1 ::s) (c1, D1, Val v::s).
Let m 1 , m 2 and m 3 be MSECD machine configurations, the transitive closure of the small-step semantics is defined inductively as follows:
m 1 m 2 m 1 + m 2 m 1 m 2 m 2 + m 3 m 1 + m 3
In Coq, this transitive closure is written as follows:
  • Inductive TC_MSECD_SS: conf → conf → Prop :=
  • | TC_MSECD_SS_SS:
  •       m1 m2, MSECD_SS m1 m2 →
  •                  TC_MSECD_SS m1~m2
  •  
  • | TC_MSECD_SS_Transitivity:
  •       m1 m2, MSECD_SS m1 m2 →
  •           m3, TC_MSECD_SS m2 m3 →
  •                  TC_MSECD_SS m1 m3.

2.2.1. Compilation

Leroy [14] defines the compilation from the pure lambda calculus extended with constants to MSECD machine code as a function. Here, we extend his work to all the MiniML dB language constructs:
n = IConst n b = IConstb b d 1 d 2 = d 1 · d 2 · IOp i ̲ = IAcc i ̲ let d 1 in d 2 = d 1 · ILet · d 2 · IEndLet if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) λ . d = IClos ( d · IRet ) μ . λ . d = IClos r e c ( d · IRet ) d 1 d 2 = d 1 · d 2 · IApp

2.2.2. Correctness

The correctness of this compilation can be established by semantic preservation for which it is necessary to extend the compilation to values and environments of the machine, as shown below:
n = n b = b ( λ . d ) [ Ω ] = ( d · IRet ) [ Ω ] ( μ . λ . d ) [ Ω ] = ( d · IRet ) [ Ω ] r e c v 1 v n = v 1 v n
In this way, if an expression d is evaluated to a value v in an Ω environment, it is expected that its compilation d is evaluated to v in the Ω environment. However, to prove this result, it is necessary to strengthen the hypothesis (we will see, in Section 2.3.2, that this is not necessary when natural semantics is used). Here, to strengthen the hypothesis is to concatenate any code c at the end of compilation d , so when the evaluation of d finishes, it is expected that v is at the top of the stack, and the code c remains to evaluate. This is formally expressed in the following theorem formulated by Leroy [14]:
Theorem 1.
If Ω d v , then ( d · c , Ω , s ) + ( c , Ω , v · s ) for all codes c and stacks s.
Proof outline.
The proof is conducted by induction on the derivation of Ω d v . The base cases where d is a natural, a Boolean, a nameless variable, an abstraction, or a fixed point (recursive abstraction) are straightforward since the corresponding d compilation is a single machine instruction whose evaluation is performed by a single machine step → that mimics the MiniML dB d evaluation.
For the inductive cases where d is an arithmetic or comparison expression, a conditional, a local definition, or an application the proof follows the structure of the derivation Ω d v . The key idea is to use the + transitivity together with the induction hypothesis, while evaluating the intermingled single instructions which appear in d by performing the corresponding → machine step. □
The complete proof can be consulted in Appendix A. This theorem is written in Coq as follows:
  • Theorem compile_eval:
  •  O,  d,  v, MML_dB_NS O d v →
  •      c,  s, TC_MSECD_SS ((compile d)++c, compile_env O,s)
  •                                   (c,compile_env O, (Val (compile_value v)::s)).

2.3. Big-Step MSECD Machine

This section introduces our big-step version of the Modern SECD machine. This machine is strongly based on our extended version of the original small-step semantics MSECD. Unlike the small-step MSECD, due to the high-level of abstraction of natural semantics, it is not necessary to use stack frames at all, and therefore the return instructions are also unnecessary (IRet which works for returning from a function call, nor IJoin that works for returning from a conditional). Having said this, we can affirm that the use of natural semantics directly impacts the machine design, specifically the machine’s components.
The instructions of the big-step MSECD machine, as well as its code, are the following:
i : : = IConst n  Naturals c : : = [   ]   Empty code
 ∣ IConstb b  Booleans ∣  i · c
 ∣ IAdd  Addition
 ∣ ISub  Subtraction
 ∣ IMul  Multiplication
 ∣ IEq  Equality comparison
 ∣ IAcc i ̲   Variable value access (de Bruijn index)
 ∣ ISel c c  Conditionals
 ∣ ILet  Local definitions
 ∣ IEndLet
 ∣ IClos c  Abstraction
 ∣ IClos r e c c  Recursion abstraction
 ∣ IApp  Application
The values and environments of the machine are defined as follows:
v m : : = n   Naturals Δ : : = [   ]    Empty environment
 ∣ b   Booleans ∣  v m · Δ
 ∣  c [ Δ ]    Closures
 ∣  c [ Δ ] r e c    Recursive closures
Given the fact that the frames disappear, it is not necessary to define stack values. Due to this, the stack directly becomes a sequence of machine values:
s : : = [   ]    Empty stack
 ∣  v m · s
The predicate Δ i ̲ v expresses that v is the value of the variable represented by the de Bruijn index i ̲ in the machine environment Δ .
v · Δ 0 ̲ v Δ i ̲ v w · Δ S i ̲ v
A state is a pair ( Δ , s ) where Δ is a machine environment and s a stack.
The machine natural semantics is defined by the following two mutually dependent predicates:
Δ , s c ( Δ f , s f ) Δ 1 , s 1 i ( Δ 2 , s 2 )
the first one for machine code, which can be read as follows: if the machine is in a state ( Δ , s ) , and a code c is given, evaluating c takes it to the state ( Δ f , s f ) . The second one for instructions, which can be read as follows: if the machine is in a state ( Δ 1 , s 1 ) and an instruction i is given, evaluating i takes it to the state ( Δ 2 , s 2 ) . However, the entry point for the semantics should be the predicate for code.
The environment Δ is supposed to contain the value of the free variables (represented by IAcc i ̲ instructions) in c, whereas the environment Δ 1 are supposed to contain the value of the free variable in i (if i is an instruction IAcc  i ̲ ). The natural semantics of the machine is the following:
Δ , s [ ] ( Δ , s ) Δ , s i ( Δ 1 , s 1 ) Δ 1 , s 1 c ( Δ 2 , s 2 ) Δ , s i · c ( Δ 2 , s 2 )
Δ , s IConst n ( Δ , n · s ) Δ , s IConstb b ( Δ , b · s )
Δ , n 2 · n 1 · s IOp ( Δ , n 1 n 2 · s ) IOp { IAdd , ISub , IMul , IEq } , { + , , , = } resp .
Δ i ̲ v Δ , s IAcc i ̲ ( Δ , v · s )
Δ , s c 1 ( Δ 1 , s 1 ) Δ , t r u e · s ISel c 1 c 2 ( Δ 1 , s 1 ) Δ , s c 2 ( Δ 1 , s 1 ) Δ , f a l s e · s ISel c 1 c 2 ( Δ 1 , s 1 )
Δ , v · s ILet ( v · Δ , s ) v · Δ , s IEndLet ( Δ , s )
Δ , s IClos c ( Δ , c [ Δ ] · s ) Δ , s IClos r e c c ( Δ , c [ Δ ] r e c · s )
v · Δ 1 , s c ( Δ 2 , v 1 · s 1 ) Δ , v · c [ Δ 1 ] · s IApp ( Δ , v 1 · s 1 ) v · c [ Δ 1 ] r e c · Δ 1 , s c ( Δ 2 , v 1 · s 1 ) Δ , v · c [ Δ 1 ] r e c · s IApp ( Δ , v 1 · s 1 )
The coding of the natural semantics of the machine is similar to that of the natural semantics of MiniML dB (only, it is necessary to use a mutually dependent definition in Coq, in correspondence with the mutually dependent predicates of the machine natural semantics). The same applies for the interpreter and its respective lemmas of soundness and completeness regarding the machine natural semantics. The formalization details can be consulted at [61].
We highlight that the machine natural semantics has the property enunciated in the following lemma:
Lemma 1.
Let Δ, Δ 1 , Δ 2 be machine environments; s, s 1 , s 2 stacks; c 1 , c 2 machine codes. If
Δ , s c 1 ( Δ 1 , s 1 ) , Δ 1 , s 1 c 2 ( Δ 2 , s 2 )
then
Δ , s c 1 · c 2 ( Δ 2 , s 2 )
Proof outline.
By induction on the derivation Δ , s c 1 ( Δ , s 1 ) . The base case is when c 1 is the empty code c 1 = [ ] which follows simply by hypothesis. The inductive case is when c 1 is not empty c 1 [ ] which is proved by applying the induction hypothesis and by ⇒ definition. □
This lemma is useful to prove compilation correctness (Section 2.3.2). A detailed proof can be seen in Appendix A.

2.3.1. Compilation

Using natural semantics, the compilation from MiniML dB to code of the big-step Modern SECD machine is defined by the following predicate:
d c
meaning, the  MiniML dB expression d is compiled into the machine code c.
- n IConst n - b IConstb b - d 1 d 2 c 1 · c 2 · IOp d 1 c 1 d 2 c 2 { + , , , = } , IOp { IAdd , ISub , IMul , IEq } resp .
- i ̲ IAcc i ̲ - let d 1 in d 2 c 1 · ILet · c 2 · IEndLet d 1 c 1 d 2 c 2 - if d 1 then d 2 else d 3 c 1 · ISel c 2 c 3 d 1 c 1 d 2 c 2 d 3 c 3
- λ . d IClos c d c - μ . λ . d IClos r e c c d c - d 1 d 2 c 1 · c 2 · IApp d 1 c 1 d 2 c 2
Regarding the Coq encoding of this compilation, it is analogous to the MiniML dB semantics, meaning, it is done with an Inductive definition with Prop type:
  • Inductive Compilation_NS: MML_dB_exp → code → Prop :=
  • | Compilation_NS_Const:  n:nat,
  •                     Compilation_NS (Const_dB n) (IConst n::nil)
  • | …
  •  
  • | Compilation_NS_Let:
  •        d1,  c1, Compilation_NS d1 c1 →
  •        d2,  c2, Compilation_NS d2 c2 →
  •                     Compilation_NS (Letm_dB d1 d2) (c1 ++ ILet::c2  ++ IEndLet::nil)
  • | …
  •  
  • | Compilation_NS_Lam:
  •           d,  c, Compilation_NS d c →
  •                      Compilation_NS (Lam_dB d) (IClos c::nil)
  •  
  • | Compilation_NS_Mu:
  •           d,  c, Compilation_NS d c →
  •                     Compilation_NS (Mu_dB d) (IClosr c::nil)
  •  
  • | Compilation_NS_App:
  •        d1,  c1, Compilation_NS d1 c1 →
  •        d2,  c2, Compilation_NS d2 c2 →
  •                     Compilation_NS (App_dB d1 d2) (c1 ++ c2 ++ IApp::nil).
and the corresponding function is written as follows:
  • Fixpoint Compilation_NS_compiler (d:MML_dB_exp) : code :=
  • match d with
  • | Const_dB n ⇒ IConst n::nil
  • | …
  • | Letm_dB d1 d2 ⇒ Compilation_NS_compiler d1 ++ ILet::Compilation_NS_compiler d2 ++ IEndLet::nil
  • | …
  • | Lam_dB d ⇒ IClos (Compilation_NS_compiler d)::nil
  • | Mu_dB d ⇒ IClosr (Compilation_NS_compiler d)::nil
  • | App_dB d1 d2 ⇒ Compilation_NS_compiler d1 ++ Compilation_NS_compiler d2 ++ IApp::nil
  • end.
It is noteworthy how this time, instead of the function being an interpreter, it is a compiler, since it translates an expression instead of evaluating it. Also, it is not necessary to add a natural parameter to bound the recursion, given that the translation is decidable. This fact is guaranteed in Coq by using structural recursion (based on syntax) on the expression d.
The following lemma expresses that the compiler is sound regarding the natural semantics definition of the compilation:
  • Lemma Compilation_NS_compiler_soundness:
  •  d:MML_dB_exp,  c:code,
  • Compilation_NS d c →
  • Compilation_NS_compiler d = c.
Conversely, the next lemma expresses that the compiler is complete regarding the natural semantics definition of the compilation:
  • Lemma Compilation_NS_compiler_completeness:
  •  d:MML_dB_exp,  c:code,
  • Compilation_NS_compiler d = c →
  • Compilation_NS d c.

2.3.2. Correctness

To establish the correctness, we extend the compilation to values and environments once more, so after that we can formulate semantic preservation.
Mathematics 08 01573 i003
To formulate correctness, we expect that if a nameless expression d is evaluated to a value v in an environment Ω , besides, if c is the code resulting of the d compilation, and  Δ is the resulting compilation of Ω ; then, it must exist a machine value v m that corresponds to the compilation of v and, when c is evaluated starting with the machine in a state ( Δ , s ) , for any stack s, the evaluation takes the machine to the state ( Δ , v m · s ) . Now, the correctness theorem is enunciated.
Theorem 2 (Correctness for termination).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code, v a nameless value. If
Mathematics 08 01573 i006
then, there exists a machine value v m such that v Mathematics 08 01573 i004 vm and for all stack s,
Δ , s c ( Δ , v m · s )
Proof outline.
We proceed by induction on the derivation of Ω d v . The base cases where d is a natural, a Boolean, a nameless variable, an abstraction, or a fixed point (recursive abstraction) are straightforward. In these cases, we exhibit a v m such that v Mathematics 08 01573 i004 vm, since c is the result of d compilation, c is a single machine instruction hence Δ , s c ( Δ , v m · s ) follows simply by definition.
For the inductive cases where d is an arithmetic or comparison expression, a conditional, a local definition, or an application, the  main idea is to use the induction hypothesis in tandem with Lemma 1. In such way the machine evaluation follows the structure of the Ω d v derivation and the proof is simple and intuitive. □
The complete proof can be consulted in Appendix A. This theorem is written as follows in Coq:
  • Theorem Compilation_NS_correctness:
  •  O,  d,  v, MML_dB_NS O d v →
  •               c, Compilation_NS d c →
  •               D, Compilation_NS_env O D →
  •              mv, Compilation_NS_val v mv  ∧
  •               s, BSMSECD_NSC (D,s) c  (D, mv::s).
We can immediately notice that due to the unifying use of natural semantics to define each of the compiler’s components: source language, compilation and machine; the source language is mapped down, in a transparent way, to the target language (in this case, machine code) by means of the compilation. In this manner, to establish the correctness turns out to be easier, clearer, simpler and more intuitive than using an ad-hoc solution. For instance, in this case, it was unnecessary to previously define a closure of a relation, and it was also unnecessary to strengthen the hypothesis to prove the correctness theorem compared to the use of a function to define the compilation and small-step semantics in the machine.

3. Coinductive Natural Semantics

In this section, we will address the case in which the computations do not terminate, for which we will use coinductive natural semantics.

3.1. MiniML dB

In general, coinduction allows us to reason on infinite structures. In this way, taking into account the natural semantics design, we can employ a coinductive definition to express infinite evaluations of a language, in this case of MiniML dB . Following Leroy [14], we define the coinductive natural semantics for divergence (infinite evaluations) by the following predicate:
Ω d
which can be read: in the Ω environment, the evaluation of the expression d diverges, is infinite, or, non-terminate.
That is, the infinite evaluations of MiniML dB are defined by the coinductive interpretation of the following rules:
Ω d 1 ¯ ¯ Ω d 1 d 2 Ω d 1 n 1 Ω d 2 ¯ ¯ Ω d 1 d 2
= Ω let d 1 in d 2 Ω d 1 Ω d 1 v 1 v 1 · Ω d 2 ¯ ¯ Ω let d 1 in d 2
= Ω if d 1 then d 2 else d 3 Ω d 1 Ω d 1 t r u e Ω d 2 ¯ ¯ Ω if d 1 then d 2 else d 3 Ω d 1 f a l s e Ω d 3 ¯ ¯ Ω if d 1 then d 2 else d 3
Ω d 1 ¯ ¯ Ω d 1 d 2 Ω d 1 ( λ . d ) [ Ω 1 ] Ω d 2 ¯ ¯ Ω d 1 d 2 Ω d 1 ( μ . λ . d ) [ Ω 1 ] Ω d 2 ¯ ¯ Ω d 1 d 2
Ω d 1 ( λ . d ) [ Ω 1 ] Ω d 2 v 2 v 2 · Ω 1 d ¯ ¯ Ω d 1 d 2
Ω d 1 ( μ . λ . d ) [ Ω 1 ] Ω d 2 v 2 v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d ¯ ¯ Ω d 1 d 2
Adopting the Leroy [14] convention, double horizontal lines denote coinductive interpretation, whereas single horizontal lines denote inductive interpretation.
The coinduction support in Coq is based on the work of Giménez [66]. In particular, Coq has native support of coinductive definitions. Likewise, a natural semantics definition can be encoded in Coq as an Inductive definition with type Prop, a coinductive natural semantics definition can be encoded in Coq as a CoInductive definition with type Prop. Hence, the  MiniML dB semantics for divergence can be written in Coq as follows:
  • CoInductive MML_dB_CNS: MML_dB_env → MML_dB_exp → Prop :=
  • | …
  •  
  • | MML_dB_CNS_LetL:
  •          O,  d1, MML_dB_CNS O d1 →
  •                d2, MML_dB_CNS O (Letm_dB d1 d2)
  •  
  • | MML_dB_CNS_LetR:
  •  O,  d1,  v1, MML_dB_NS O d1 v1 →
  •                d2, MML_dB_CNS (v1::O) d2 →
  •                      MML_dB_CNS O (Letm_dB d1 d2)
  • | …
  •  
  • | MML_dB_CNS_AppL:
  •           O,  d1, MML_dB_CNS O d1 →
  •                 d2, MML_dB_CNS O (App_dB d1 d2)
  •  
  • | MML_dB_CNS_AppR:
  •   O O1,  d1 d, MML_dB_NS O d1 (Clos_dB d O1) →
  •                d2, MML_dB_CNS O d2 →
  •                      MML_dB_CNS O (App_dB d1 d2)
  •  
  • | MML_dB_CNS_AppRr:
  •   O O1,  d1 d, MML_dB_NS O d1 (Closr_dB d O1) →
  •                d2, MML_dB_CNS O d2 →
  •                      MML_dB_CNS O (App_dB d1 d2)
  •  
  • | MML_dB_CNS_AppF:
  •   O O1,  d1 d, MML_dB_NS O d1 (Clos_dB d O1) →
  •         d2,  v2, MML_dB_NS O d2 v2 →
  •                      MML_dB_CNS (v2::O1) d →
  •                      MML_dB_CNS O (App_dB d1 d2)
  •  
  • | MML_dB_CNS_AppFr:
  •   O O1,  d1 d, MML_dB_NS O d1 (Closr_dB d O1) →
  •         d2,  v2, MML_dB_NS O d2 v2 →
  •                      MML_dB_CNS (v2:: (Closr_dB d O1)::O1) d →
  •                      MML_dB_CNS O (App_dB d1 d2).
In the same manner as shown earlier in Section 2.1, where we verified that our interpreter MML_dB_NS_interpreter is sound regarding MiniML dB natural semantics; here, we must verify that it is sound regarding MiniML dB coinductive natural semantics for non-termination, meaning, we must prove the next lemma:
  • Lemma MML_NS_interpreter_soundness_non_termination:
  •  O,  d, MML_dB_CNS O d →
  •        n, MML_dB_NS_interpreter n O d = None.
This lemma states that, if the evaluation of d does not terminate, whatever the n value of the fuel is, the interpreter will necessarily, eventually, run out of fuel (None means that the interpreter runs out of fuel).
Conversely, to verify that our interpreter is complete regarding MiniML dB coinductive natural semantics, we must prove this lemma:
  • Lemma MML_NS_interpreter_completeness_non_termination:  n,  O,  d,
  • MML_dB_NS_interpreter n O d = None →
  • not ( v, MML_dB_NS O d v) ∨
  • ( m, m > n ∧  v, MML_dB_NS_interpreter m O d = Some v).
This lemma says that if the interpreter runs out of fuel, then, there is not a finite evaluation of or d or, in fact, it exists a finite evaluation of d, but more fuel is needed for the interpreter to be able to compute it. The proof of this lemma in Coq requires classic reasoning.

3.2. Modern SECD Machine

Let us now see how to express non-terminating computations in a machine. Leroy [14] uses small-step semantics to express infinitely many transitions in the MSECD. He defines the transition relation ‘ ’ coinductively as follows:
m 1 m 2 m 2 ¯ ¯ m 1
This relation can be written in Coq in the following manner:
  • CoInductive transinf: conf → Prop :=
  • | transinf_intro:  m1 m2,
  •      MSECD_SS m1 m2 →
  •      transinf m2 →
  •      transinf m1.
However, by using this definition directly, it is not possible to prove the correctness of the compilation in the case of non-termination. The reason is that the Coq coinduction mechanism imposes the guard condition. The guard condition requires (at least) one rule (a constructor) of a coinductive definition to be used before the coinduction hypothesis is employed during a proof by coinduction. The solution offered by Leroy [14] is to define an auxiliary relation with which the proof can be carried out, and which is equivalent to the previous definition.
= m n + 1 m n ( n - sleep ) = m 1 n m 1 + m 2 m 2 n ( n - perform )
The most important property of the n relation, for our purposes, is that it allows the machine to remain in the same configuration, at most, a finite number n times ( n -sleep rule). This rule is crucial, as it is used for being able to comply with the guard condition when carrying out the correctness proof. At some point before n reaches 0, or necessarily when n arrives at 0, at least one transition ( n -perform rule) must be performed, in exchange for making a transition, the value of n is reset to any natural n , i.e., the possibility is given (again) to remain in the same configuration (this time, n times at most). The relation and the relation n are equivalent as stated in the following lemma:
Lemma 2.
Let m be a machine configuration, n any natural number,
m i f   a n d   o n l y   i f m n
Proof outline.
The if part is by coinduction. By  definition, necessarily m m 1 and m 1 , the result is obtained by applying the induction hypothesis on m 1 and then by using the n -perform rule. The only if part is also by coinduction. Assuming that if m n then m m 1 and m 1 n 1 , we apply the coinduction hypothesis on m 1 n 1 and then the result follows by definition. □
A more detailed proof can be consulted in Appendix A.

Compilation Correctness

To carry out the correctness proof, it is necessary to define a measure that indicates how many times the machine can remain in the same configuration based on the constructs of a language. The measure offered by Leroy (extended to cover all MiniML dB ) is the following:
n = b = x = λ . d = μ . λ . d = 0 d 1 d 2 = d 1 + 1 let d 1 in d 2 = d 1 + 1 if d 1 then d 2 else d 3 = d 1 + 1 d 1 d 2 = d 1 + 1
This is because it is possible that an evaluation step of a MiniML dB expression d does not correspond, one to one in the same order, to a transition while evaluating d in the machine, causing the machine to stay at the same configuration, d times, before performing a transition.
In this way, we are ready to state the correctness for the non-termination case, using the auxiliary relation n and strengthening the hypothesis, by the following lemma:
Lemma 3.
If Ω d , then ( d · c , Ω , s ) d for all codes c and stacks s.
Proof outline.
By coinduction. The main idea of the proof is to use Theorem 1 to evaluate the finite parts of d, to apply the coinduction hypothesis on the infinite parts of d, and to employ n -sleep and n -perform rules as convenient. □
A complete proof of this lemma can be consulted in Appendix A. This gives the possibility for formulating the correctness theorem directly with the m relation, as Leroy [14] does, as follows:
Theorem 3.
If Ω d , then ( d · c , Ω , s ) for all codes c and stacks s.
Proof outline.
The result is an immediate deduction from Lemma 3 followed by an application of Lemma 2. □
A step-by-step proof can be seen in Appendix A. This theorem is written in Coq as follows:
  • Theorem compile_evalinf:
  •  O,  d, MML_dB_CNS O d →
  •  c,  s, transinf ((compile d)++c, (compile_env O), s).

3.3. Big-Step MSECD Machine

This section introduces coinductive natural semantics to express non-terminating computations (infinite evaluations) in a machine. We illustrate its use with our big-step Modern SECD machine.

3.3.1. Rules of Non-terminating Computations

As with natural semantics (for finite evaluations, Section 2.3), coinductive natural semantics for divergence (infinite evaluations) is defined by the following two mutually dependent predicates:
Δ , s i Δ , s c
The first one reads: in the state ( Δ , s ) the instruction i diverges, whereas the second one reads: in the state ( Δ , s ) the code c diverges.
Thus, the infinite evaluations of the machine are defined by the coinductive interpretation of the following rules:
1 ) = Δ , s i · c Δ , s i 2 ) = Δ , s i · c Δ , s i ( Δ 1 , s 1 ) Δ 1 , s 1 c
3 ) = Δ , t r u e · s ISel c 1 c 2 Δ , s c 1 4 ) = Δ , f a l s e · s ISel c 1 c 2 Δ , s c 2
5 ) = Δ , v · c [ Δ 1 ] · s IApp v · Δ 1 , s c 6 ) = Δ , v · c [ Δ 1 ] r e c · s IApp v · c [ Δ 1 ] r e c · Δ 1 , s c
The coinductive natural semantics of the machine is encoded in Coq in an analogous manner to the coinductive natural semantics of MiniML dB (it is just necessary to use a coinductive mutually dependent definition in Coq that parallels the mutually dependent predicates of the machine coinductive natural semantics). Likewise, the respective lemmas that express that the machine interpreter is sound and complete regarding the machine coinductive natural semantics are analogous to those of the MiniML dB interpreter. These formalizations can be seen in detail in [61].
We will give a brief explanation of the rules. When evaluating a code, it must begin by evaluating the first instruction i. The evaluation of i can be finite (rule 2) or infinite (rule 1). In the rule 1 case, if the first instruction diverges, then the complete code diverges. How can an instruction diverge? Let us recall (Section 2.3) that due to the high level of abstraction of the big-step MSECD, in the case of termination, the ISel and IApp instructions are fully evaluated in a single big step, which includes the evaluation of their sub-codes and is why for these instructions it is necessary to define rules that allow expressing the possibility that their corresponding sub-codes diverge (rules 3–6). In the case of rule 2, if the evaluation of the first instruction terminates but the remaining code diverges, then, the complete code (including the first instruction) diverges.
We can note here that in principle only rule 2 is necessary to express divergence in the machine since, intuitively, an instruction performs only a single basic operation and this rule is the analogous of the small-step semantics transition relation . However, as already mentioned, our big-step machine has two instructions, namely ISel and IApp, which are high-level (and therefore they evaluate different from their small-step semantics counterparts, performing not only single basic operations but a big-step sub-code evaluation). This is why these instructions require specific rules, while the remaining instructions, perform in fact only a single basic operation; for instance, IConst n push n on the stack. This is why these remaining instructions do not need specific rules.
In this way, the machine computations that do not terminate are completely defined. However, as in the case of the MSECD small-step semantics, we are facing, once more, the problem with Coq’s guard condition. This means that similarly, we cannot prove correctness directly by using this relation. To solve this problem, we will present a variant of Leroy’s solution adapted to coinductive natural semantics. This means that we must define an auxiliary relation equivalent to the previous relation, and which allows proving correctness. Below, we present the auxiliary relation:
1 ) = Δ , s i · c n Δ , s i
3 ) = Δ , t r u e · s ISel c 1 c 2 Δ , s c 1 n 4 ) = Δ , f a l s e · s ISel c 1 c 2 Δ , s c 2 n
5 ) = Δ , v · c [ Δ 1 ] · s IApp v · Δ 1 , s c n 6 ) = Δ , v · c [ Δ 1 ] r e c · s IApp v · c [ Δ 1 ] r e c · Δ 1 , s c n
= Δ , s c 1 · c 2 n + 1 Δ , s c 1 n ( n - sleep ) = c 1 [ ] Δ , s c 1 ( Δ 1 , s 1 ) Δ 1 , s 1 c 2 n Δ , s c 1 · c 2 n ( n - perform )
The rule ( n -sleep) is the improved analogous version of Leroy’s rule ( n -sleep), since, in addition, it expresses that if in a code, the initial code c 1 diverges, then, no matter what the remaining code c 2 is, the code will diverge. The importance of this improvement is that it allows proving correctness without the need to strengthen the hypothesis. The rule ( n -perform) is analogous to the rule ( n -perform) of Leroy. We can note that rule 2 disappears (is no longer necessary) because it is subsumed by the ( n -perform) rule. For its part, the remaining rules (1 and 3–6) remain unchanged, i.e., they are analogous, but instead of the relation for code they use the relation n with any natural n.
It is worth remarking that the relation defines the machine computations that do not terminate in the expected way and it would be ideal working directly with it in Coq; however, because of the Coq guard condition it is not possible. This is why we have defined the relation just to beat the Coq guard condition. Since we have defined the relation (more precisely n relation for code and relation for instructions) in a very similar way to the relation, we have used a very similar notation; nonetheless, we should be careful and notice the distinction between and .
The following lemma states that the two original mutually dependent relations are equivalent to the two auxiliary mutually dependent relations.
Lemma 4.
Let Δ be a machine environment, s a stack, i a machine instruction,
Δ , s i if and only if Δ , s i
and, let c be a machine code, n any natural,
Δ , s c if and only if Δ , s c n
Proof outline.
The if part consist of: if Δ , s i then Δ , s i , and  if Δ , s c then Δ , s c n , i.e., of the following two cases:
  • If Δ , s i then Δ , s i . Assuming 2, since the instructions’ definition of and are analogous, the proof proceeds simply by case analysis which are proved directly by definition using 2 to obtain the required Δ , s c n code premises.
  • If Δ , s c then Δ , s c n . By coinduction. The main idea is to use the coinduction hypothesis together with the n -perform rule, and to apply 1 to obtain Δ , s i premises when necessary.
The only if part consists of: If Δ , s i then Δ , s i , and if Δ , s c n then Δ , s c . That is, of the following two cases:
3.
If Δ , s i then Δ , s i . Assuming 4, the proof is analogue to that of 1 going in the opposite direction (and using 4 instead of 2).
4.
If Δ , s c n then Δ , s c . Assuming that, if  Δ , s i · c n then Δ , s i or there exists n 1 , Δ 1 , s 1 , such that Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c n 1 ; The proof proceeds by coinduction. The key idea is to use the coinduction hypothesis together with n definition, in particular with the n -perform rule, employing the assumption in the step which is required, and  applying 3 to obtain Δ , s i premises when necessary.
 □
The details of this proof can be consulted in Appendix A.

3.3.2. Compilation Correctness

To prove correctness, we must use the auxiliary relation n along with a measure. Following an analogous argument to the case of the small-step MSECD, the measure d also works here. In this way, the correctness for the non-termination case can be formulated by the following lemma:
Lemma 5 (Correctness for non-termination (auxiliary)).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code. If
Mathematics 08 01573 i007
then, for all stack s,
Δ , s c d
Proof outline.
We proceed by coinduction. The main idea is to mimic the MiniML dB d evaluation in the machine while evaluating c. To carry out this idea, for the finite parts of d (if any), we employ Theorem 2, whereas for the infinite parts of d, we apply the coinduction hypothesis. In addition, we use the n definition, including the n -sleep and n -perform rules, as necessary. □
A complete proof of this lemma appears in Appendix A. Finally, we enunciate the correctness theorem for the non-termination case of the machine, using the relation directly in the following manner:
Theorem 4 (Correctness for non-termination).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code. If
Mathematics 08 01573 i007
then, for all stack s,
Δ , s c
Proof outline.
The result is a direct consequence of Lemma 5 followed by Lemma 4. □
A detailed step-by-step proof can be found in Appendix A. This theorem is written in Coq as follows:
  • Theorem Compilation_CNS_correctness:
  •  O,  d, MML_dB_CNS O d →
  •         c, Compilation_NS d c →
  •         D, Compilation_NS_env O D →
  •         s, BSMSECD_CNSC (D,s) c.

4. Abstract to Coq Translation Algorithm

At this point, by means of our Mini-ML compiler, we have shown how from the (coinductive) natural semantics definition of each compiler component the corresponding formalization in Coq can be realized. It is our intention here to generalize this method and write it formally as an algorithm.
Algorithm 1 expresses how to translate a (coinductive) natural semantics definition of a compiler to its corresponding formalization in Coq.
We observe that the steps of the algorithm possess a high-level of abstraction. This is favorable in the sense that it provides freedom on how to actually implement them. We can even take advantage of this freedom by applying previous work. For instance, applying the results in [67], step 14 could be performed by generating a function from the Inductive definition I N , corresponding to the natural semantics N.
Analyzing the algorithm, as we can note in step 35, the case in which the target language R of a translation T is a postfix representation requires a special treatment that merits explanation. Let V be the source language of T, d a construct of V, if c is the translation of d into R, then if R is a prefix representation when reasoning about the evaluation of c in Coq, necessarily a constructor s associated with the construct, must be used (at front) when starting the evaluation; in this way, the guard condition is fulfilled. Instead, if R is a postfix representation, then necessarily a constructor s associated with the construct, must be used but (behind), at the end of the evaluation; in this way, the Coq’s guard condition is not fulfilled since it requires that it must be used at the start (at front). For instance, let Plus e1 e2 be a construct in MiniML and let Plus_dB d1 d2 be its translation in MiniML dB , then the evaluation of Plus_dB d1 d2 will start using a Plus_dB constructor associated with the addition, at the start, and the Coq’s guard condition will be satisfied. Instead, let Plus_dB d1 d2 be a construct in MiniML dB and c1++c2++IAdd its translation into code of the big-step MSECD, then the evaluation of c1++c2++IAdd will not start using an IAdd constructor associated with the addition, even when potentially, eventually, it will be used at the end in fact. Therefore, in this latter case, we must find a way to express and convince Coq’s guard condition that the constructor will be in fact used, but at the end of the evaluation of c. This is exactly what the solution presented in Section 3.3 does, if the auxiliary relation is used, then initially the sleep rule constructor can be used, which allows the starting of the evaluation of c without using a constructor s associated with the construct, ensuring that potentially, eventually, such a s constructor will be in fact used (what is expressed in the constructor corresponding to the perform rule); the measure function d indicates the number of constructors that will be used at the end of the evaluation of c. This is certainly a weakness of Coq’s guard condition that turns out to be too inflexible in this case, and that is why we have had to resort to an indirect solution.
In fact, in our compiler, in the MiniML to MiniML dB translation it was not necessary to use this indirect solution at all because MiniML dB is a prefix representation. Instead, it was in fact necessary to use it in the MiniML dB to big-step MSECD machine code generation because machine code is a postfix representation.
Algorithm 1: Translation of a Compiler Definition to Coq (first part)
Mathematics 08 01573 i001
Algorithm 1: Translation of a Compiler Definition to Coq (second part)
Mathematics 08 01573 i002

5. Conclusions

Natural semantics is a simple, easy, and intuitive formalism widely known and used in the literature to define the semantics of programming languages.
In this work, we extended (coinductive) natural semantics to present it as a unifying framework for the verification of total correctness of compilers in Coq. This way, we present a solution to the problem of having a simple, easy, clear, and intuitive framework to perform this task in this proof assistant. By means of this framework, one can obtain standalone executable verified compiler.
Although we have not illustrated it here, natural semantics can also be used to express and verify the static semantics of a language. For instance, in [68] the Mini-ML static semantics is verified (although it is not possible to obtain a verified semantic analyzer). In future work, we plan to extend this use of natural semantics to make it possible to obtain a verified semantic analyzer.
To have a full compiler framework, we must address lexing and parsing too. So, we envisioned that natural ‘semantics’ can also be used to perform these tasks. This inspiration comes from the observation that, as stated by Kahn [11], natural deduction is at the heart of natural semantics, so we are looking for a natural deduction-based parsing strategy, fortunately, it already exists a parsing technique with these features since long time ago. In the logic programming community, parsing as deduction [69,70] is a well-known and established natural deduction-based parsing framework. Therefore, since both: natural semantics and parsing as deduction are based on natural deduction, we believe that we can abstract both in a single formalism able to express both: syntax and semantics. In this way, it would achieve natural ‘semantics’ as full compiler verification framework in Coq.

Author Contributions

Conceptualization, A.Z.; methodology, A.Z.; software, A.Z.; validation, A.Z.; formal analysis, A.Z.; investigation, A.Z.; resources, G.B.-E.; writing—original draft preparation, A.Z.; writing—review and editing, A.Z. and G.B.-E.; visualization, A.Z.; supervision, G.B.-E.; project administration, G.B.-E.; funding acquisition, G.B.-E. Both authors have read and agreed to the published version of the manuscript.

Funding

This research was funded by CONACYT, grant number A1-S-27780, and DGAPA UNAM, grant number PAPIIT-A401219.

Acknowledgments

The first author sincerely thanks Xavier Leroy for inspiring him to work with coinductive natural semantics in Coq. In particular, for revising his preliminary results regarding the equivalence of c o with the union of ⇒ and . Finally, for encouraging him to write his results and extend his work. The first author is grateful to David de Frutos-Escrig for providing advice during this work. Special thanks to Veronica Dahl who offered guidance, and useful insight into Prolog parsing techniques. Our deepest gratitude goes to our anonymous reviewers whose accurate, appropriate and constructive comments have led to a valuable improvement of this work.

Conflicts of Interest

The authors declare no conflict of interest.

Appendix A. Proofs

Theorem A1.
If Ω d v , then ( d · c , Ω , s ) + ( c , Ω , v · s ) for all codes c and stacks s.
Proof. 
By induction on Ω d v .
  • Base cases:
    (i)
    d = n . By hypothesis Ω n n . Since by definition n = IConst n and n = n we must prove ( IConst n · c , Ω , s ) + ( c , Ω , n · s ) , which follows simply by definition of the machine small-step semantics transition → corresponding to the IConst n instruction.
    (ii)
    d = b . Analogous to case i. Hypothesis Ω b b ; b = IConstb b and b = b .
    (iii)
    d = i ̲ . The proof follows from the fact that if Ω i ̲ v then Ω ( i ) = v which is proved by straightforward induction on Ω.
    (iv)
    d = λ . d . Analogous to case i. Hypothesis Ω λ . d ( λ . d ) [ Ω ] ; λ . d = IClos ( d · IRet ) and ( λ . d ) [ Ω ] = ( d · IRet ) [ Ω ] .
    (v)
    d = μ . λ . d . Analogous to case i. Hypothesis Ω μ . λ . d ( μ . λ . d ) [ Ω ] ; μ . λ . d = IClos r e c ( d · IRet ) and ( μ . λ . d ) [ Ω ] = ( d · IRet ) [ Ω ] r e c .
  • Inductive cases:
    (vi)
    d = d 1 d 2 .
    By hypothesis Ω d 1 n 1 , Ω d 2 n 2 , Ω d 1 d 2 n 1 n 2 . We must prove ( d 1 d 2 · c , Ω , s ) + ( c , Ω , n 1 n 2 · s ) .
    (a)
    ( d 1 · d 2 · IOp · c , Ω , s ) + ( c , Ω , n 1 n 2 · s ) by definition d 1 d 2 = d 1 · d 2 · IOp and n 1 n 2 = n 1 n 2 .
    (b)
    ( d 1 · d 2 · IOp · c , Ω , s ) + ( d 2 · IOp · c , Ω , n 1 · s ) by + transitivity, applying induction hypothesis, and by definition n 1 = n 1 .
    (c)
    ( d 2 · IOp · c , Ω , n 1 · s ) + ( IOp · c , Ω , n 2 · n 1 · s ) by + transitivity, applying induction hypothesis, and by definition n 2 = n 2 .
    (d)
    ( IOp · c , Ω , n 2 · n 1 · s ) + ( c , Ω , n 1 n 2 · s ) by → definition of IOp.
    (vii)
    d = if d 1 then d 2 else d 3 .
    By hypothesis Ω d 1 t r u e , Ω d 2 v . We must prove
    ( if d 1 then d 2 else d 3 · c , Ω , s ) + ( c , Ω , v · s ) .
    (a)
    ( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) + ( c , Ω , v · s )
    by definition if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) .
    (b)
    ( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) + ( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , t r u e · s ) by + transitivity, and applying induction hypothesis
    (c)
    ( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , t r u e · s ) + ( d 2 · IJoin , Ω , ( c , [ ] ) · s ) by → definition of ISel.
    (d)
    ( d 2 · IJoin , Ω , ( c , [ ] ) · s ) + ( IJoin , Ω , v · ( c , [ ] ) · s ) by + transitivity, and applying induction hypothesis.
    (e)
    ( IJoin , Ω , v · ( c , [ ] ) · s ) + ( c , Ω , v · s ) by → definition of IJoin.
    (viii)
    d = if d 1 then d 2 else d 3 .
    By hypothesis Ω d 1 f a l s e , Ω d 3 v . We must prove
    ( if d 1 then d 2 else d 3 · c , Ω , s ) + ( c , Ω , v · s ) .
    (a)
    ( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) + ( c , Ω , v · s )
    by definition if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) .
    (b)
    ( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) + ( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , f a l s e · s ) by + transitivity, and applying induction hypothesis
    (c)
    ( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , f a l s e · s ) + ( d 3 · IJoin , Ω , ( c , [ ] ) · s ) by → definition of ISel.
    (d)
    ( d 3 · IJoin , Ω , ( c , [ ] ) · s ) + ( IJoin , Ω , v · ( c , [ ] ) · s ) by + transitivity, and applying induction hypothesis.
    (e)
    ( IJoin , Ω , v · ( c , [ ] ) · s ) + ( c , Ω , v · s ) by → definition of IJoin.
    (ix)
    d = let d 1 in d 2 .
    By hypothesis Ω d 1 v 1 , v 1 · Ω d 2 v , Ω let d 1 in d 2 v . We must prove
    ( let d 1 in d 2 · c , Ω , s ) + ( c , Ω , v · s ) .
    (a)
    ( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) + ( c , Ω , v · s )
    by definition let d 1 in d 2 = d 1 · ILet · d 2 · IEndLet .
    (b)
    ( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) + ( ILet · d 2 · IEndLet · c , Ω , v 1 · s ) by + transitivity, and applying induction hypothesis.
    (c)
    ( ILet · d 2 · IEndLet · c , Ω , v 1 · s ) + ( d 2 · IEndLet · c , v 1 · Ω , s ) by → definition of ILet.
    (d)
    ( d 2 · IEndLet · c , v 1 · Ω , s ) + ( IEndLet · c , v 1 · Ω , v · s ) by + transitivity, and applying induction hypothesis.
    (e)
    ( IEndLet · c , v 1 · Ω , v · s ) + ( c , Ω , v · s ) by → definition of IEndLet.
    (x)
    d = d 1 d 2 .
    By hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · Ω 1 d v , Ω d 1 d 2 v . We must prove ( d 1 d 2 · c , Ω , s ) + ( c , Ω , v · s ) .
    (a)
    ( d 1 · d 2 · IApp · c , Ω , s ) + ( c , Ω , v · s ) by definition d 1 d 2 = d 1 · d 2 · IApp
    (b)
    ( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · , Ω , ( λ . d ) [ Ω 1 ] · s ) by + transitivity, and applying induction hypothesis.
    (c)
    ( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( λ . d ) [ Ω 1 ] · s ) by + transitivity, and applying induction hypothesis.
    (d)
    ( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] · s ) by definition ( λ . d ) [ Ω 1 ] = ( d · IRet ) [ Ω 1 ] .
    (e)
    ( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] · s ) + ( d · IRet , v 2 · Ω 1 , ( c , Ω ) · s ) by → definition of IApp.
    (f)
    ( d · IRet , v 2 · Ω 1 , ( c , Ω ) · s ) + ( IRet , v 2 · Ω 1 , v · ( c , Ω ) · s ) by + transitivity and applying induction hypothesis.
    (g)
    ( IRet , v 2 · Ω 1 , v · ( c , Ω ) · s ) + ( c , Ω , v · s ) by → definition of IRet.
    (xi)
    d = d 1 d 2 .
    By hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d v ,
    Ω d 1 d 2 v . We must prove ( d 1 d 2 · c , Ω , s ) + ( c , Ω , v · s ) .
    (a)
    ( d 1 · d 2 · IApp · c , Ω , s ) + ( c , Ω , v · s ) by definition d 1 d 2 = d 1 · d 2 · IApp
    (b)
    ( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) by + transitivity, and applying induction hypothesis.
    (c)
    ( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( μ . λ . d ) [ Ω 1 ] · s ) by + transitivity, and applying induction hypothesis.
    (d)
    ( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] r e c · s ) by definition ( μ . λ . d ) [ Ω 1 ] = ( d · IRet ) [ Ω 1 ] r e c .
    (e)
    ( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] r e c · s ) + ( d · IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , ( c , Ω ) · s ) by → definition of IApp.
    (f)
    ( d · IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , ( c , Ω ) · s ) + ( IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , v · ( c , Ω ) · s ) by + transitivity and applying induction hypothesis.
    (g)
    ( IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , v · ( c , Ω ) · s ) + ( c , Ω , v · s ) by → definition of IRet. □
Lemma A1.
Let Δ, Δ 1 , Δ 2 be machine environments; s, s 1 , s 2 stacks; c 1 , c 2 machine codes. If
Δ , s c 1 ( Δ 1 , s 1 ) Δ 1 , s 1 c 2 ( Δ 2 , s 2 )
then
Δ , s c 1 · c 2 ( Δ 2 , s 2 )
Proof. 
By induction on Δ , s c 1 ( Δ 1 , s 1 ) .
  • Base case:
    (i)
    c 1 = [ ] .
    Hypothesis Δ , s [ ] ( Δ , s ) , Δ , s c 2 ( Δ 2 , s 2 ) . We must prove Δ , s [ ] · c 2 ( Δ 2 , s 2 ) , since [ ] · c 2 = c 2 our goal reduces to Δ , s c 2 ( Δ 2 , s 2 ) which follows by hypothesis.
  • Inductive case:
    (ii)
    c 1 [ ] that is c 1 = i · c .
    Hypothesis Δ , s i ( Δ 1 , s 1 ) , Δ 1 , s 1 c ( Δ 2 , s 2 ) , Δ 2 , s 2 c 2 ( Δ 3 , s 3 ) . We must prove Δ , s i · c · c 2 ( Δ 3 , s 3 ) .
    (a)
    Applying induction hypothesis on Δ 1 , s 1 c ( Δ 2 , s 2 ) and Δ 2 , s 2 c 2 ( Δ 3 , s 3 ) we have Δ 1 , s 1 c · c 2 ( Δ 3 , s 3 ) .
    (b)
    Using ( Δ , s ) i ( Δ 1 , s 1 ) and Δ 1 , s 1 c · c 2 ( Δ 3 , s 3 ) by ⇒ definition we conclude Δ , s i · c · c 2 ( Δ 3 , s 3 ) . □
Theorem A2 (Correctness for termination).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code, v a nameless value. If
Mathematics 08 01573 i006
then, there exists a machine value v m such that v Mathematics 08 01573 i004 vm and for all stack s,
Δ , s c ( Δ , v m · s )
Proof. 
By induction on Ω d v .
  • Base cases:
    (i)
    d = n .
    Hypothesis Ω n n , n c , Ω Mathematics 08 01573 i005 Δ. We claim that there exists v m = n , the proof of n Mathematics 08 01573 i004 n follows by definition. Using the n c hypothesis, by ⇓ definition necessarily c = IConst n . We are now in a position to prove the main goal Δ , s IConst n ( Δ , n · s ) which follows by ⇒ definition of IConst.
    (ii)
    d = b . Analogous to case i.
    Hypothesis Ω b b , b c , Ω Mathematics 08 01573 i005 Δ. We claim that there exists v m = b , the proof of b Mathematics 08 01573 i004 b follows by definition. Using the b c hypothesis, by ⇓ definition necessarily c = IConstb b . We are now in a position to prove the main goal Δ , s IConstb b ( Δ , b · s ) which follows by ⇒ definition of IConstb.
    (iii)
    d = i ̲ .
    The proof relies on the fact that if Ω i ̲ v , Ω Mathematics 08 01573 i005 Δ, v Mathematics 08 01573 i004 vm then Δ i ̲ v m which is proved by straightforward induction on Ω i ̲ v . (Also, it can by proved by induction on Ω.)
    (iv)
    d = λ . d . Analogous to case i.
    Hypothesis Ω λ . d ( λ . d ) [ Ω ] , λ . d c , Ω Mathematics 08 01573 i005 Δ. Using the λ . d c hypothesis, by ⇓ definition necessarily d c 1 , c = IClos c 1 . We claim that there exists v m = c 1 [ Δ ] , the proof of ( λ . d ) [ Ω ] Mathematics 08 01573 i004 c1[Δ] follows by definition, d c 1 and Ω Mathematics 08 01573 i005 Δ. We are now in a position to prove the main goal Δ , s IClos c 1 ( Δ , c 1 [ Δ ] · s ) which follows by ⇒ definition of IClos.
    (v)
    d = μ . λ . d . Analogous to case i.
    Hypothesis Ω μ . λ . d ( μ . λ . d ) [ Ω ] , μ . λ . d c , Ω Mathematics 08 01573 i005 Δ. Using the μ . λ . d c hypothesis, by ⇓ definition necessarily d c 1 , c = IClos r e c c 1 . We claim that there exists v m = c 1 [ Δ ] r e c , the proof of ( μ . λ . d ) [ Ω ] Mathematics 08 01573 i004 c1[Δ]rec follows by definition, d c 1 and Ω Mathematics 08 01573 i005 Δ. We are now in a position to prove the main goal Δ , s IClos r e c c 1 ( Δ , c 1 [ Δ ] r e c · s ) which follows by ⇒ definition of IClos r e c .
  • Inductive cases:
    (vi)
    d = d 1 d 2 .
    Hypothesis Ω d 1 n 1 , Ω d 2 n 2 , Ω d 1 d 2 n 1 n 2 , d 1 d 2 c , Ω Mathematics 08 01573 i005 Δ.
    We claim that there exists v m = n 1 n 2 , the proof of n 1 n 2 Mathematics 08 01573 i004 n 1 n 2 follows by definition. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IOp . We are now in position to prove the main goal Δ , s c 1 · c 2 · IOp ( Δ , n 1 n 2 · s ) .
    (a)
    Δ , s c 1 ( Δ , n 1 · s ) by induction hypothesis.
    (b)
    Δ , n 1 · s c 2 ( Δ , n 2 · n 1 · s ) by induction hypothesis.
    (c)
    Δ , s c 1 · c 2 ( Δ , n 2 · n 1 · s ) by Lemma A1 on vi.a and vi.b.
    (d)
    Δ , n 2 · n 1 · s IOp ( Δ , n 1 n 2 · s ) by definition.
    (e)
    Δ , s c 1 · c 2 · IOp ( Δ , n 1 n 2 · s ) by Lemma A1 on vi.c and vi.d.
    (vii)
    d = if d 1 then d 2 else d 3 .
    Hypothesis Ω d 1 t r u e , Ω d 2 v , if d 1 then d 2 else d 3 c , Ω Mathematics 08 01573 i005 Δ. Using the if d 1 then d 2 else d 3 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , d 3 c 3 , c = c 1 · ISel c 2 c 3 . We are now in position to prove the main goal Δ , s c 1 · ISel c 2 c 3 ( Δ , v m · s ) .
    (a)
    Δ , s c 1 ( Δ , t r u e · s ) by induction hypothesis.
    (b)
    Δ , s c 2 ( Δ , v m · s ) by induction hypothesis (such that v Mathematics 08 01573 i004 vm).
    (c)
    Δ , t r u e · s ISel c 2 c 3 ( Δ , v m · s ) by definition using viii.b.
    (d)
    Δ , s c 1 · ISel c 2 c 3 ( Δ , v m · s ) by Lemma A1 on viii.a and viii.c.
    (viii)
    d = if d 1 then d 2 else d 3 .
    Hypothesis Ω d 1 f a l s e , Ω d 3 v , if d 1 then d 2 else d 3 c , Ω Mathematics 08 01573 i005 Δ. Using the if d 1 then d 2 else d 3 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , d 3 c 3 , c = c 1 · ISel c 2 c 3 . We are now in position to prove the main goal Δ , s c 1 · ISel c 2 c 3 ( Δ , v m · s ) .
    (a)
    Δ , s c 1 ( Δ , f a l s e · s ) by induction hypothesis.
    (b)
    Δ , s c 3 ( Δ , v m · s ) by induction hypothesis (such that v Mathematics 08 01573 i004 vm).
    (c)
    Δ , f a l s e · s ISel c 2 c 3 ( Δ , v m · s ) by definition using viii.b.
    (d)
    Δ , s c 1 · ISel c 2 c 3 ( Δ , v m · s ) by Lemma A1 on viii.a and viii.c.
    (ix)
    d = let d 1 in d 2 .
    Hypothesis Ω d 1 v 1 , v 1 · Ω d 2 v , Ω let d 1 in d 2 v , let d 1 in d 2 c , Ω Mathematics 08 01573 i005 Δ. Using the let d 1 in d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · ILet · c 2 · IEndLet . We are now in position to prove the main goal
    Δ , s c 1 · ILet · c 2 · IEndLet ( Δ , v m · s )
    (a)
    Δ , s c 1 ( Δ , v m 1 · s ) by induction hypothesis (such that v1 Mathematics 08 01573 i004 vm1).
    (b)
    Δ , v m 1 · s ILet ( v m 1 · Δ , s ) by definition.
    (c)
    Δ , s c 1 · ILet ( v m 1 · Δ , s ) by Lemma A1 on ix.a and ix.b.
    (d)
    v m 1 · Δ , s c 2 ( v m 1 · Δ , v m · s ) by induction hypothesis (such that v Mathematics 08 01573 i004 vm).
    (e)
    Δ , s c 1 · ILet · c 2 ( v m 1 · Δ , v m · s ) by Lemma A1 on ix.c and ix.d.
    (f)
    v m 1 · Δ , v m · s IEndLet ( Δ , v m · s ) by definition.
    (g)
    Δ , s c 1 · ILet · c 2 · IEndLet ( Δ , v m · s ) by Lemma A1 on ix.e and ix.f.
    (x)
    d = d 1 d 2 .
    Hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · Ω 1 d v , Ω d 1 d 2 v , d 1 d 2 c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp .
    We are now in position to prove the main goal Δ , s c 1 · c 2 · IApp ( Δ , m v · s ) .
    (a)
    d c , Ω1 Mathematics 08 01573 i005 Δ1, Δ , s c 1 ( Δ , c [ Δ 1 ] · s ) by induction hypothesis
    (such that ( λ . d ) [ Ω 1 ] Mathematics 08 01573 i004 c1]).
    (b)
    Δ , c [ Δ 1 ] · s c 2 ( Δ , v m 2 · c [ Δ 1 ] · s ) by induction hypothesis (such that v2 Mathematics 08 01573 i004 vm2).
    (c)
    Δ , s c 1 · c 2 ( Δ , v m 2 · c [ Δ 1 ] · s ) by Lemma A1 on x.a and x.b.
    (d)
    v m 2 · Δ 1 , s c ( v m 2 · Δ 1 , v m · s ) by induction hypothesis (such that v Mathematics 08 01573 i004 vm).
    (e)
    Δ , v m 2 · c [ Δ 1 ] · s IApp ( Δ , v m · s ) by definition using x.d.
    (f)
    Δ , s c 1 · c 2 · IApp ( Δ , v m · s ) by Lemma A1 on x.c and x.e.
    (xi)
    d = d 1 d 2 .
    Hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d v , Ω d 1 d 2 v , d 1 d 2 c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp .
    We are now in position to prove the main goal Δ , s c 1 · c 2 · IApp ( Δ , m v · s ) .
    (a)
    d c , Ω1 Mathematics 08 01573 i005 Δ1, Δ , s c 1 ( Δ , c [ Δ 1 ] r e c · s ) by induction hypothesis
    (such that ( μ . λ . d ) [ Ω 1 ] Mathematics 08 01573 i004 c1]rec).
    (b)
    Δ , c [ Δ 1 ] r e c · s c 2 ( Δ , v m 2 · c [ Δ 1 ] r e c · s ) by induction hypothesis (such that v2 Mathematics 08 01573 i004 vm2).
    (c)
    Δ , s c 1 · c 2 ( Δ , v m 2 · c [ Δ 1 ] r e c · s ) by Lemma A1 on xi.a and xi.b.
    (d)
    v m 2 · c [ Δ 1 ] r e c · Δ 1 , s c ( v m 2 · c [ Δ 1 ] r e c · Δ 1 , v m · s ) by induction hypothesis (such that v Mathematics 08 01573 i004 vm).
    (e)
    Δ , v m 2 · c [ Δ 1 ] r e c · s IApp ( Δ , v m · s ) by definition using xi.d.
    (f)
    Δ , s c 1 · c 2 · IApp ( Δ , v m · s ) by Lemma A1 on xi.c and xi.e. □
Lemma A2.
Let m be a machine configuration, n any natural number,
m if   and   only   if m n
Proof. 
(i)
If m then m n . By coinduction.
Hypothesis m . Using the m hypothesis by definition necessarily m m 1 , m 1 . We are now in position to prove m n .
(a)
m 1 n by coinduction hypothesis on m 1 .
(b)
m n by the n -perform rule on m m 1 and m 1 n .
(ii)
If m n then m . By coinduction.
Hypothesis m n . We have to prove m .
(a)
The proof uses the fact that if m n then there exists m 1 such that m m 1 and m 1 n 1 which is proved by induction on the natural n.
(b)
m m 1 , m 1 n 1 by ii.a on m n .
(c)
m 1 by coinduction hypothesis on m 1 n 1 .
(d)
m by definition on m m 1 and m 1 . □
Lemma A3.
If Ω d , then for all codes c, for all stacks s, ( d · c , Ω , s ) d .
Proof. 
By coinduction.
(i)
d = d 1 d 2 .
Hypothesis Ω d 1 . We have to prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
for all c h , s h , ( d 1 · c h , Ω , s h ) d 1 by coinduction hypothesis on Ω d 1 .
(b)
( d 1 · d 2 · IOp · c , Ω , s ) d 1 by i.a with c h = d 2 · IOp · c and s h = s .
(c)
( d 1 · d 2 · IOp · c , Ω , s ) d 1 + 1 by n -sleep rule on i.b.
(d)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IOp and d 1 d 2 = d 1 + 1 .
(ii)
d = d 1 d 2 .
Hypothesis Ω d 1 n 1 , Ω d 2 . We have to prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
( d 1 · d 2 · IOp · c , Ω , s ) + ( d 2 · IOp · c , Ω , n 1 · s ) by Theorem A1 on Ω d 1 n 1 .
(b)
for all c h , s h , ( d 2 · c h , Ω , s h ) d 2 by induction hypothesis on Ω d 2 .
(c)
( d 2 · IOp · c , Ω , n 1 · s ) d 2 by ii.b with c h = IOp · c and s h = n 1 · s .
(d)
( d 1 · d 2 · IOp · c , Ω , s ) d 1 d 2 by n -perform rule on ii.a and ii.c.
(e)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IOp .
(iii)
d = let d 1 in d 2 .
Hypothesis Ω d 1 . We have to prove ( let d 1 in d 2 · c , Ω , s ) let d 1 in d 2 .
(a)
for all c h , s h , ( d 1 · c h , Ω , s h ) d 1 by coinduction hypothesis on Ω d 1 .
(b)
( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) d 1 by iii.a with c h = ILet · d 2 · IEndLet · c and s h = s .
(c)
( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) d 1 + 1 by n -sleep rule on iii.b.
(d)
( let d 1 in d 2 · c , Ω , s ) let d 1 in d 2
by definition let d 1 in d 2 = d 1 · ILet · d 2 · IEndLet and let d 1 in d 2 = d 1 + 1 .
(iv)
d = let d 1 in d 2 .
Hypothesis Ω d 1 v 1 , v 1 · Ω d 2 .
We must prove ( let d 1 in d 2 · c , Ω , s ) let d 1 in d 2 .
(a)
( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) + ( ILet · d 2 · IEndLet · c , Ω , v 1 · s ) by Theorem A1 on Ω d 1 v 1 .
(b)
( ILet · d 2 · IEndLet · c , Ω , v 1 · s ) ( d 2 · IEndLet · c , v 1 · Ω , s ) by → definition of ILet.
(c)
for all c h , s h , ( d 2 · c h , v 1 · Ω , s h ) d 2 by coinduction hypothesis on v 1 · Ω d 2 .
(d)
( d 2 · IEndLet · c , v 1 · Ω , s ) d 2 by iv.c with c h = IEndLet · c and s h = s .
(e)
( ILet · d 2 · IEndLet · c , Ω , v 1 · s ) d 1 by n -perform rule on iv.b and iv.d.
(f)
( d 1 · ILet · d 2 · IEndLet · c , Ω , s ) d 1 + 1 by n -perform rule on iv.a and iv.e.
(g)
( let d 1 in d 2 · c , Ω , s ) let d 1 in d 2
by definition let d 1 in d 2 = d 1 · ILet · d 2 · IEndLet and let d 1 in d 2 = d 1 + 1 .
(v)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 . We must prove ( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 .
(a)
for all c h , s h , ( d 1 · c h , Ω , s h ) d 1 by coinduction hypothesis on Ω d 1 .
(b)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) d 1 by v.a with
c h = ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c and s h = s .
(c)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) d 1 + 1 by n -sleep rule on v.b.
(d)
( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 by definition
if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) and
if d 1 then d 2 else d 3 = d 1 + 1 .
(vi)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 t r u e , Ω d 2 .
We must prove ( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 .
(a)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) +
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , t r u e · s ) by Theorem A1 on Ω d 1 t r u e .
(b)
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , t r u e · s ) ( d 2 · IJoin , Ω , ( c , [ ] ) · s ) by → definition of ISel.
(c)
for all c h , s h , ( d 2 · c h , Ω , s h ) d 2 by coinduction hypothesis on Ω d 2 .
(d)
( d 2 · IJoin , Ω , ( c , [ ] ) · s ) d 2 by vi.c with c h = IJoin and s h = ( c , [ ] ) · s .
(e)
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , t r u e · s ) d 1 by n -perform rule on vi.b and vi.d.
(f)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) d 1 + 1 by n -perform rule on vi.a and vi.e.
(g)
( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 by definition
if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) and
if d 1 then d 2 else d 3 = d 1 + 1 .
(vii)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 f a l s e , Ω d 3 .
We must prove ( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 .
(a)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) +
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , f a l s e · s ) by Theorem A1 on Ω d 1 f a l s e .
(b)
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , f a l s e · s ) ( d 3 · IJoin , Ω , ( c , [ ] ) · s ) by → definition of ISel.
(c)
for all c h , s h , ( d 3 · c h , Ω , s h ) d 3 by coinduction hypothesis on Ω d 3 .
(d)
( d 3 · IJoin , Ω , ( c , [ ] ) · s ) d 3 by vii.c with c h = IJoin and s h = ( c , [ ] ) · s .
(e)
( ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , f a l s e · s ) d 1 by n -perform rule on vii.b and vii.d.
(f)
( d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) · c , Ω , s ) d 1 + 1 by n -perform rule on vii.a and vii.e.
(g)
( if d 1 then d 2 else d 3 · c , Ω , s ) if d 1 then d 2 else d 3 by definition
if d 1 then d 2 else d 3 = d 1 · ISel ( d 2 · IJoin ) ( d 3 · IJoin ) and
if d 1 then d 2 else d 3 = d 1 + 1 .
(viii)
d = d 1 d 2 .
Hypothesis Ω d 1 . We must prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
for all c h , s h , ( d 1 · c h , Ω , s h ) d 1 by coinduction hypothesis on Ω d 1 .
(b)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 by viii.a with c h = d 2 · IApp · c and s h = s .
(c)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 + 1 by n -sleep rule on viii.b.
(d)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IApp and d 1 d 2 = d 1 + 1 .
(ix)
d = d 1 d 2 .
Hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 . We must prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) by Theorem A1 on
Ω d 1 ( λ . d ) [ Ω 1 ] .
(b)
for all c h , s h , ( d 2 · c h , Ω , s h ) d 2 by coinduction hypothesis on Ω d 2 .
(c)
( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) d 2 by ix.b with c h = IApp · c and s h = ( λ . d ) [ Ω 1 ] · s .
(d)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 + 1 by n -perform rule on ix.a and ix.c.
(e)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IApp and d 1 d 2 = d 1 + 1 .
(x)
d = d 1 d 2 .
Hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 . We must prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) by Theorem A1 on
Ω d 1 ( μ . λ . d ) [ Ω 1 ] .
(b)
for all c h , s h , ( d 2 · c h , Ω , s h ) d 2 by coinduction hypothesis on Ω d 2 .
(c)
( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) d 2 by x.b with c h = IApp · c and s h = ( μ . λ . d ) [ Ω 1 ] · s .
(d)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 + 1 by n -perform rule on x.a and x.c.
(e)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IApp and d 1 d 2 = d 1 + 1 .
(xi)
d = d 1 d 2 .
Hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · Ω 1 d .
We must prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) by Theorem A1 on
Ω d 1 ( λ . d ) [ Ω 1 ] .
(b)
( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( λ . d ) [ Ω 1 ] · s ) by Theorem A1 on Ω d 2 v 2 .
(c)
( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] · s ) ( d · IRet , v 2 · Ω 1 , ( c , Ω ) · s ) by → of IApp.
(d)
for all c h , s h , ( d · c h , v 2 · Ω 1 , s h ) d by coinduction hypothesis on v 2 · Ω 1 d .
(e)
( d · IRet , v 2 · Ω 1 , ( c , Ω ) · s ) d by xi.d with c h = IRet and s h = ( c , Ω ) · s .
(f)
( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] · s ) d 2 by n -perform rule on xi.c and xi.e.
(g)
( d 2 · IApp · c , Ω , ( λ . d ) [ Ω 1 ] · s ) d 1 by n -perform rule on xi.b and xi.f, and by definition ( λ . d ) [ Ω 1 ] = ( d · IRet ) [ Ω 1 ] .
(h)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 + 1 by n -perform rule on xi.a and xi.g.
(i)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IApp and d 1 d 2 = d 1 + 1 .
(xii)
d = d 1 d 2 .
Hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d .
We must prove ( d 1 d 2 · c , Ω , s ) d 1 d 2 .
(a)
( d 1 · d 2 · IApp · c , Ω , s ) + ( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) by Theorem A1 on
Ω d 1 ( μ . λ . d ) [ Ω 1 ] .
(b)
( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) + ( IApp · c , Ω , v 2 · ( μ . λ . d ) [ Ω 1 ] · s ) by Theorem A1 on Ω d 2 v 2 .
(c)
( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] r e c · s )
( d · IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , ( c , Ω ) · s ) by → of IApp.
(d)
for all c h , s h , ( d · c h , v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 , s h ) d by coinduction hypothesis on
v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d .
(e)
( d · IRet , v 2 · ( d · IRet ) [ Ω 1 ] r e c · Ω 1 , ( c , Ω ) · s ) d by xii.d with c h = IRet and
s h = ( c , Ω ) · s , and by definition ( μ . λ . d ) [ Ω 1 ] = ( d · IRet ) [ Ω 1 ] r e c .
(f)
( IApp · c , Ω , v 2 · ( d · IRet ) [ Ω 1 ] r e c · s ) d 2 by n -perform rule on xii.c and xii.e.
(g)
( d 2 · IApp · c , Ω , ( μ . λ . d ) [ Ω 1 ] · s ) d 1 by n -perform rule on xii.b and xii.f, and by definition ( μ . λ . d ) [ Ω 1 ] = ( d · IRet ) [ Ω 1 ] r e c .
(h)
( d 1 · d 2 · IApp · c , Ω , s ) d 1 + 1 by n -perform rule on xii.a and xii.g.
(i)
( d 1 d 2 · c , Ω , s ) d 1 d 2 by definition d 1 d 2 = d 1 · d 2 · IApp and d 1 d 2 = d 1 + 1 . □
Theorem A3.
If Ω d , then ( d · c , Ω , s ) for all codes c and stacks s.
Proof. 
Hypothesis Ω d . We have to prove ( d · c , Ω , s ) .
(i)
( d · c , Ω , s ) d by Lemma A3 on Ω d .
(ii)
( d · c , Ω , s ) by Lemma A2 on i. □
Lemma A4.
Let Δ be a machine environment, s a stack, i a machine instruction,
Δ , s i if and only if Δ , s i
and, let c be a machine code, n any natural,
Δ , s c if and only if Δ , s c n
Proof. 
  • If Δ , s i then Δ , s i and if Δ , s c then Δ , s c n .
    (a)
    If Δ , s i then Δ , s i . Assuming 1b, the proof is by case analysis.
    • i = ISel c 1 c 2 .
      Hypothesis Δ , s c 1 , Δ , t r u e · s ISel c 1 c 2 .
      We have to prove Δ , t r u e · s ISel c 1 c 2 .
      • Δ , s c 1 n by 1b on Δ , s c 1 .
      • Δ , t r u e · s ISel c 1 c 2 by definition using 1(a)iA.
    • i = ISel c 1 c 2 .
      Hypothesis Δ , s c 1 , Δ , f a l s e · s ISel c 1 c 2 .
      We have to prove Δ , f a l s e · s ISel c 1 c 2 .
      • Δ , s c 1 n by 1b on Δ , s c 1 .
      • Δ , f a l s e · s ISel c 1 c 2 by definition using 1(a)iiA.
    • i = IApp .
      Hypothesis v · Δ 1 , s c , Δ , v · c [ Δ 1 ] · s IApp .
      We have to prove Δ , v · c [ Δ 1 ] · s IApp .
      • v · Δ 1 , s c n by 1b on v · Δ 1 , s c .
      • Δ , v · c [ Δ 1 ] · s IApp by definition using 1(a)iiiA.
    • i = IApp .
      Hypothesis v · c [ Δ 1 ] r e c · Δ 1 , s c , Δ , v · c [ Δ 1 ] r e c · s IApp .
      We have to prove Δ , v · c [ Δ 1 ] r e c · s IApp .
      • v · c [ Δ 1 ] r e c · Δ 1 , s c n by 1b on v · c [ Δ 1 ] r e c · Δ 1 , s c .
      • Δ , v · c [ Δ 1 ] r e c · s IApp by definition using 1(a)ivA.
    (b)
    If Δ , s c then Δ , s c n . By coinduction.
    • c = i · c .
      Hypothesis Δ , s i , Δ , s i · c . We have to prove Δ , s i · c n .
      • Δ , s i by 1a on Δ , s i .
      • Δ , s i · c n by definition using 1(b)iA.
    • c = i · c .
      Hypothesis Δ , s i ( Δ 1 , s 1 ) , Δ 1 , s 1 c , Δ , s i · c .
      We have to prove Δ , s i · c n .
      • Δ 1 , s 1 c n by coinduction hypothesis on Δ 1 , s 1 c .
      • Δ , s i · c n by n -perform rule on Δ , s i ( Δ 1 , s 1 ) and 1(b)iiA.
  • If Δ , s i then Δ , s i and if Δ , s c n then Δ , s c .
    (a)
    If Δ , s i then Δ , s i . Assuming 2b, the proof is by case analysis.
    • i = ISel c 1 c 2 .
      Hypothesis Δ , s c 1 n , Δ , t r u e · s ISel c 1 c 2 .
      We have to prove Δ , t r u e · s ISel c 1 c 2 .
      • Δ , s c 1 by 2b on Δ , s c 1 n .
      • Δ , t r u e · s ISel c 1 c 2 by definition using 2(a)iA.
    • i = ISel c 1 c 2 .
      Hypothesis Δ , s c 1 n , Δ , f a l s e · s ISel c 1 c 2 .
      We have to prove Δ , f a l s e · s ISel c 1 c 2 .
      • Δ , s c 1 by 2b on Δ , s c 1 n .
      • Δ , f a l s e · s ISel c 1 c 2 by definition using 2(a)iiA.
    • i = IApp .
      Hypothesis v · Δ 1 , s c n , Δ , v · c [ Δ 1 ] · s IApp .
      We have to prove Δ , v · c [ Δ 1 ] · s IApp .
      • v · Δ 1 , s c by 2b on v · Δ 1 , s c n .
      • Δ , v · c [ Δ 1 ] · s IApp by definition using 2(a)iiiA.
    • i = IApp .
      Hypothesis v · c [ Δ 1 ] r e c · Δ 1 , s c n , Δ , v · c [ Δ 1 ] r e c · s IApp .
      We have to prove Δ , v · c [ Δ 1 ] r e c · s IApp .
      • v · c [ Δ 1 ] r e c · Δ 1 , s c by 2b on v · c [ Δ 1 ] r e c · Δ 1 , s c n .
      • Δ , v · c [ Δ 1 ] r e c · s IApp by definition using 2(a)ivA.
    (b)
    If Δ , s c n then Δ , s c . By coinduction.
    • c = i · c .
      Hypothesis Δ , s i , Δ , s i · c n . We have to prove Δ , s i · c .
      • Δ , s i by 2a on Δ , s i .
      • Δ , s i · c by definition using 2(b)iA.
    • c = c 1 · c 2 .
      Hypothesis Δ , s c 1 n , Δ , s c 1 · c 2 n + 1 . We have to prove Δ , s c 1 · c 2 .
      • The proof uses the fact that if Δ , s i · c n then Δ , s i or there exists n 1 , Δ 1 , s 1 , such that Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c n 1 , which is proved by induction on the natural n.
      • c 1 [ ] that is c 1 = i · c 1 by n definition and Δ , s c 1 n .
      • Δ , s i , or Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c 1 · c 2 n 1 by 2(b)iiA on
        Δ , s i · c 1 · c 2 n + 1 .
        • Δ , s i .
          -
          Δ , s i by 2a on Δ , s i .
          -
          Δ , s i · c 1 · c 2 by definition using Δ , s i .
        • Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c 1 · c 2 n 1 .
          -
          Δ 1 , s 1 c 1 · c 2 by coinduction hypothesis on Δ 1 , s 1 c 1 · c 2 n 1 .
          -
          Δ , s i · c 1 · c 2 by definition using Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c 1 · c 2 .
    • c = c 1 · c 2 .
      Hypothesis c 1 [ ] , Δ , s c 1 ( Δ 1 , s 1 ) , Δ 1 , s 1 c 2 n , Δ , s c 1 · c 2 n .
      We must prove Δ , s c 1 · c 2 .
      • c 1 [ ] that is c 1 = i · c 1 by hypothesis.
      • Δ , s i ( Δ t , s t ) and Δ t , s t c 1 ( Δ 1 , s 1 ) by Δ , s c 1 ( Δ 1 , s 1 ) hypothesis.
        • c 1 = [ ] .
          -
          Δ t = Δ 1 and s t = s 1 by Δ t , s t c 1 ( Δ 1 , s 1 ) and c 1 = [ ] .
          -
          Δ 1 , s 1 c 2 by coinduction hypothesis on Δ 1 , s 1 c 2 n .
          -
          Δ , s i · c 2 by definition using Δ , s i ( Δ 1 , s 1 ) and Δ 1 , s 1 c 2 .
          -
          Δ , s i · c 1 · c 2 by c 1 = [ ] .
        • c 1 [ ]
          -
          Δ t , s t c 1 · c 2 n by n -perform rule on Δ t , s t c 1 ( Δ 1 , s 1 ) and
          Δ 1 , s 1 c 2 n .
          -
          Δ t , s t c 1 · c 2 by coinduction hypothesis on Δ t , s t c 1 · c 2 n .
          -
          Δ , s i · c 1 · c 2 by definition using Δ , s i ( Δ t , s t ) and Δ t , s t c 1 · c 2 . □
Lemma A5 (Correctness for non-termination (auxiliary)).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code. If
Mathematics 08 01573 i007
then, for all stack s,
Δ , s c d
Proof. 
By coinduction.
(i)
d = d 1 d 2 .
Hypothesis Ω d 1 , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis,
>by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IOp .
We must prove Δ , s c 1 · c 2 · IOp d 1 d 2 .
(a)
Δ , s c 1 d 1 by coinduction hypothesis on Ω d 1 .
(b)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -sleep rule on i.a.
(c)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(ii)
d = d 1 d 2 .
Hypothesis Ω d 1 n 1 , Ω d 2 , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IOp . We must prove Δ , s c 1 · c 2 · IOp d 1 d 2 .
(a)
Δ , s c 1 ( Δ , n 1 · s ) by Theorem A2 on Ω d 1 n 1 .
(b)
Δ , n 1 · s c 2 d 2 by coinduction hypothesis on Ω d 2 .
(c)
Δ , n 1 · s c 2 · IOp d 2 + 1 by n -sleep rule on ii.b.
(d)
Δ , s c 1 · c 2 · IOp d 1 + 1 by n -perform rule on ii.a and ii.c.
(e)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(iii)
d = let d 1 in d 2 .
Hypothesis Ω d 1 , Ω let d 1 in d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the let d 1 in d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · ILet · c 2 · IEndLet . We must prove Ω c 1 · ILet · c 2 · IEndLet let d 1 in d 2 .
(a)
Δ , s c 1 d 1 by coinduction hypothesis on Ω d 1 .
(b)
Δ , s c 1 · ILet · c 2 · IEndLet d 1 + 1 by n -sleep on iii.a.
(c)
Δ , s c 1 · ILet · c 2 · IEndLet let d 1 in d 2 by definition let d 1 in d 2 = d 1 + 1 .
(iv)
d = let d 1 in d 2 .
Hypothesis Ω d 1 v 1 , v 1 · Ω d 2 , Ω let d 1 in d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the let d 1 in d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · ILet · c 2 · IEndLet . We must prove Ω c 1 · ILet · c 2 · IEndLet let d 1 in d 2 .
(a)
Δ , s c 1 ( Δ , v m 1 · s ) by Theorem A2 on Ω d 1 v 1 (such that v1 Mathematics 08 01573 i004 vm1).
(b)
Δ , v m 1 · s ILet ( v m 1 · Δ , s ) by definition.
(c)
v m 1 · Δ , s c 2 d 2 by coinduction hypothesis on v 1 · Ω d 2 .
(d)
v m 1 · Δ , s c 2 · IEndLet d 2 + 1 by n -sleep rule on iv.c.
(e)
Δ , v m 1 · s ILet · c 2 · IEndLet d 2 + 1 by n -perform rule on iv.b and iv.d.
(f)
Δ , s c 1 · ILet · c 2 · IEndLet d 1 + 1 by n -perform rule on iv.a and iv.e.
(g)
Δ , s c 1 · ILet · c 2 · IEndLet let d 1 in d 2 by definition let d 1 in d 2 = d 1 + 1 .
(v)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 , Ω if d 1 then d 2 else d 3 , d c , Ω Mathematics 08 01573 i005 Δ. Using the if d 1 then d 2 else d 3 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , d 3 c 3 , c = c 1 · ISel c 2 c 3 . We must prove Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 .
(a)
Δ , s c 1 d 1 by coinduction hypothesis on Ω d 1 .
(b)
Δ , s c 1 · ISel c 2 c 3 d 1 + 1 by n -sleep rule on v.a.
(c)
Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 by definition if d 1 then d 2 else d 3 = d 1 + 1 .
(vi)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 t r u e , Ω d 2 , Ω if d 1 then d 2 else d 3 , d c , Ω Mathematics 08 01573 i005 Δ. Using the if d 1 then d 2 else d 3 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , d 3 c 3 , c = c 1 · ISel c 2 c 3 . We must prove Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 .
(a)
Δ , s c 1 ( Δ , t r u e · s ) by Theorem A2 on Ω d 1 t r u e .
(b)
Δ , s c 2 d 2 by coinduction hypothesis on Ω d 2 .
(c)
Δ , t r u e · s ISel c 2 c 3 by definition using vi.b.
(d)
Δ , t r u e · s ISel c 2 c 3 d 2 by definition using vi.c.
(e)
Δ , s c 1 · ISel c 2 c 3 d 1 + 1 by n -perform rule on vi.a and vi.d.
(f)
Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 by definition if d 1 then d 2 else d 3 = d 1 + 1 .
(vii)
d = if d 1 then d 2 else d 3 .
Hypothesis Ω d 1 f a l s e , Ω d 3 , Ω if d 1 then d 2 else d 3 , d c , Ω Mathematics 08 01573 i005 Δ. Using the if d 1 then d 2 else d 3 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , d 3 c 3 , c = c 1 · ISel c 2 c 3 . We must prove Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 .
(a)
Δ , s c 1 ( Δ , f a l s e · s ) by Theorem A2 on Ω d 1 f a l s e .
(b)
Δ , s c 3 d 3 by coinduction hypothesis on Ω d 3 .
(c)
Δ , f a l s e · s ISel c 2 c 3 by definition using vii.b.
(d)
Δ , f a l s e · s ISel c 2 c 3 d 3 by definition using vii.c.
(e)
Δ , s c 1 · ISel c 2 c 3 d 1 + 1 by n -perform rule on vii.a and vii.d.
(f)
Δ , s c 1 · ISel c 2 c 3 if d 1 then d 2 else d 3 by definition if d 1 then d 2 else d 3 = d 1 + 1 .
(viii)
d = d 1 d 2 .
Hypothesis Ω d 1 , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp .
We must prove Δ , s c 1 · c 2 · IApp d 1 d 2 .
(a)
Δ , s c 1 d 1 by coinduction hypothesis on Ω d 1 .
(b)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -sleep rule on viii.a.
(c)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(ix)
d = d 1 d 2 .
Hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp .
We must prove Δ , s c 1 · c 2 · IApp d 1 d 2 .
(a)
Δ , s c 1 ( Δ , v m · s ) by Theorem A2 on Ω d 1 ( λ . d ) [ Ω 1 ] (such that ( λ . d ) [ Ω 1 ] Mathematics 08 01573 i004 vm).
(b)
Δ , v m · s c 2 d 2 by coinduction hypothesis on Ω d 2 .
(c)
Δ , v m · s c 2 · IApp d 2 + 1 by n -sleep rule on ix.b.
(d)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -perform rule on ix.a and ix.c.
(e)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(x)
d = d 1 d 2 .
Hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp .
We must prove Δ , s c 1 · c 2 · IApp d 1 d 2 .
(a)
Δ , s c 1 ( Δ , v m · s ) by Theorem A2 on Ω d 1 ( μ . λ . d ) [ Ω 1 ] (such that ( μ . λ . d ) [ Ω 1 ] Mathematics 08 01573 i004 vm).
(b)
Δ , v m · s c 2 d 2 by coinduction hypothesis on Ω d 2 .
(c)
Δ , v m · s c 2 · IApp d 2 + 1 by n -sleep rule on x.b.
(d)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -perform rule on x.a and x.c.
(e)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(xi)
d = d 1 d 2 .
Hypothesis Ω d 1 ( λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · Ω 1 d , Ω d 1 d 2 , d c ,
Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp . We must prove Δ , s c 1 · c 2 · IApp d 1 d 2 .
(a)
Ω1 Mathematics 08 01573 i005 Δ1, d c , Δ , s c 1 ( Δ , c [ Δ 1 ] · s ) by Theorem A2 on Ω d 1 ( λ . d ) [ Ω 1 ]
(such that ( λ . d ) [ Ω 1 ] Mathematics 08 01573 i004 c′[Δ1].
(b)
Δ , c [ Δ 1 ] · s c 2 ( Δ , v m 2 · c [ Δ 1 ] · s ) by Theorem A2 on Ω d 2 v 2 (such that v2 Mathematics 08 01573 i004 vm2).
(c)
v m 2 · Δ 1 , s c d by coinduction hypothesis on v 2 · Ω 1 d .
(d)
Δ , v m 2 · c [ Δ 1 ] · s IApp by definition using xi.c.
(e)
Δ , v m 2 · c [ Δ 1 ] · s IApp d by definition using xi.d.
(f)
Δ , c [ Δ 1 ] · s c 2 · IApp d 2 by n -perform rule on xi.b and xi.e.
(g)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -perform rule on xi.a and xi.f.
(h)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 .
(xii)
d = d 1 d 2 .
Hypothesis Ω d 1 ( μ . λ . d ) [ Ω 1 ] , Ω d 2 v 2 , v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d , Ω d 1 d 2 , d c , Ω Mathematics 08 01573 i005 Δ. Using the d 1 d 2 c hypothesis, by ⇓ definition necessarily d 1 c 1 , d 2 c 2 , c = c 1 · c 2 · IApp . We must prove Δ , s c 1 · c 2 · IApp d 1 d 2 .
(a)
Ω1 Mathematics 08 01573 i005 Δ1, d c , Δ , s c 1 ( Δ , c [ Δ 1 ] r e c · s ) by Theorem A2 on Ω d 1 ( μ . λ . d ) [ Ω 1 ]
(such that ( μ . λ . d ) [ Ω 1 ] c [ Δ 1 ] Mathematics 08 01573 i004 c′[Δ1]rec.
(b)
Δ , c [ Δ 1 ] r e c · s c 2 ( Δ , v m 2 · c [ Δ 1 ] r e c · s ) by Theorem A2 on Ω d 2 v 2 (such that v2 Mathematics 08 01573 i004 vm2).
(c)
v m 2 · c [ Δ 1 ] r e c · Δ 1 , s c d by coinduction hypothesis on v 2 · ( μ . λ . d ) [ Ω 1 ] · Ω 1 d .
(d)
Δ , v m 2 · c [ Δ 1 ] r e c · s IApp by definition using xii.c.
(e)
Δ , v m 2 · c [ Δ 1 ] r e c · s IApp d by definition using xii.d.
(f)
Δ , c [ Δ 1 ] r e c · s c 2 · IApp d 2 by n -perform rule on xii.b and xii.e.
(g)
Δ , s c 1 · c 2 · IApp d 1 + 1 by n -perform rule on xii.a and xii.f.
(h)
Δ , s c 1 · c 2 · IApp d 1 d 2 by definition d 1 d 2 = d 1 + 1 . □
Theorem A4 (Correctness for non-termination).
Let Ω be a nameless environment, Δ a machine environment, d a nameless expression, c a machine code. If
Mathematics 08 01573 i007
then, for all stack s,
Δ , s c
Proof. 
Hypothesis Ω d , d c , Ω Mathematics 08 01573 i005 Δ. We must prove Δ , s c .
(i)
Δ , s c d by Lemma A5 on the hypothesis.
(ii)
Δ , s c by Lemma A4 on i. □

References

  1. Leroy, X. Formal Verification of a Realistic Compiler. Commun. ACM 2009, 52, 107–115. [Google Scholar] [CrossRef] [Green Version]
  2. Leroy, X. A formally verified compiler back-end. J. Autom. Reason. 2009, 43, 363–446. [Google Scholar] [CrossRef] [Green Version]
  3. Leroy, X. Formal Certification of a Compiler Back-End or: Programming a Compiler with a Proof Assistant. In Proceedings of the Conference Record of the 33rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, SC, USA, 11–13 January 2006; Association for Computing Machinery: New York, NY, USA, 2006; pp. 42–54. [Google Scholar] [CrossRef] [Green Version]
  4. Blazy, S.; Leroy, X. Mechanized semantics for the Clight subset of the C language. J. Autom. Reason. 2009, 43, 263–288. [Google Scholar] [CrossRef] [Green Version]
  5. Blazy, S.; Dargaye, Z.; Leroy, X. Formal Verification of a C Compiler Front-End. In International Symposium on Formal Methods; Misra, J., Nipkow, T., Sekerinski, E., Eds.; Springer: Berlin/Heidelberg, Germany, 2006; Volume 4085, pp. 460–475. [Google Scholar] [CrossRef] [Green Version]
  6. Anand, A.; Appel, A.W.; Morrisett, G.; Paraskevopoulou, Z.; Pollack, R.; Savary Bélanger, O.; Sozeau, M.; Weaver, M. CertiCoq: A verified compiler for Coq. In Proceedings of the The Third International Workshop on Coq for Programming Languages, CoqPL 2017, Paris, France, 15–21 January 2017. [Google Scholar]
  7. Jung, R.; Krebbers, R.; Jourdan, J.H.; Bizjak, A.; Birkedal, L.; Dreyer, D. Iris from the ground up: A modular foundation for higher-order concurrent separation logic. J. Funct. Program. 2018, 28, e20. [Google Scholar] [CrossRef] [Green Version]
  8. Leroy, X. Functional Programming Languages Part II: Abstract Machines. MPRI 2-4, INRIA. Available online: https://xavierleroy.org/mpri/2-4/machines.pdf (accessed on 4 March 2020).
  9. Grégoire, B.; Leroy, X. A Compiled Implementation of Strong Reduction. In Proceedings of the seventh ACM SIGPLAN International Conference on Functional Programming, ICFP ’02, Pittsburgh, PA, USA, 4–6 October 2002; Association for Computing Machinery: New York, NY, USA, 2002; pp. 235–246. [Google Scholar] [CrossRef] [Green Version]
  10. Zúñiga, A.; Bel-Enguix, G. A Correct Compiler from Mini-ML to a Big-Step Machine Verified Using Natural Semantics in Coq. In Proceedings of the XVIII Jornadas de PROgramación y LEnguajes (PROLE 2018), Seville, Spain, 17–19 September 2018. [Google Scholar]
  11. Kahn, G. Natural semantics. In Annual Symposium on Theoretical Aspects of Computer Science; Brandenburg, F.J., Vidal-Naquet, G., Wirsing, M., Eds.; Springer: Berlin/Heidelberg, Germany, 1987; Volume 247, pp. 22–39. [Google Scholar] [CrossRef]
  12. Despeyroux, J. Proof of Translation in Natural Semantics. Research Report RR-0514; INRIA. 1986. Available online: https://hal.inria.fr/inria-00076040/file/RR-0514.pdf (accessed on 4 March 2020).
  13. Boutin, S. Proving Correctness of the Translation from Mini-ML to the CAM with the Coq Proof Development System. Research Report RR-2536; INRIA. Available online: https://hal.inria.fr/inria-00074142/file/RR-2536.pdf (accessed on 4 March 2020).
  14. Leroy, X. Coinductive Big-Step Operational Semantics. In Proceedings of the ESOP 2006: Programming Languages and Systems, Vienna, Austria, 27–28 March 2006; Sestoft, P., Ed.; Springer: Berlin/Heidelberg, Germany, 2006; Volume 3924, pp. 54–68. [Google Scholar] [CrossRef] [Green Version]
  15. Leroy, X.; Grall, H. Coinductive big-step operational semantics. Inf. Comput. 2009, 207, 284–304. [Google Scholar] [CrossRef] [Green Version]
  16. Hardin, T.; Maranget, L.; Pagano, B. Functional runtime systems within the lambda-sigma calculus. J. Funct. Program. 1998, 8, 131–176. [Google Scholar] [CrossRef]
  17. Grégoire, B. Compilation des Termes de Preuves: Un (nouveau) Mariage Entre Coq et OCaml. Ph.D. Thesis, Spécialité Informatique, Université Paris 7—Denis Diderot, École Polytechnique, France, 2003. [Google Scholar]
  18. Leroy, X. The ZINC Experiment: An Economical Implementation of the ML Language. Technical Report RT-0117; INRIA. Available online: https://hal.inria.fr/inria-00070049/file/RT-0117.pdf (accessed on 4 March 2020).
  19. Kunze, F.; Smolka, G.; Forster, Y. Formal Small-Step Verification of a Call-by-Value Lambda Calculus Machine. In Proceedings of the Asian Symposium on Programming Languages and Systems, APLAS 2018, Wellington, New Zealand, 2–6 December 2018; Ryu, S., Ed.; Springer International Publishing: Cham, Switzerland, 2018; Volume 11275, pp. 264–283. [Google Scholar] [CrossRef] [Green Version]
  20. Charguéraud, A. Pretty-Big-Step Semantics. In Proceedings of the ESOP 2013: Programming Languages and Systems, Rome, Italy, 16–24 March 2013; Felleisen, M., Gardner, P., Eds.; Springer: Berlin/Heidelberg, Germany, 2013; Volume 7792, pp. 41–60. [Google Scholar] [CrossRef] [Green Version]
  21. Bach Poulsen, C.; Mosses, P.D. Flag-based big-step semantics. J. Log. Algebr. Methods Program. 2017, 88, 174–190. [Google Scholar] [CrossRef] [Green Version]
  22. Leroy, X. Le Système Caml Special Light: Modules et Compilation Efficace en Caml. Research Report RR-2721; INRIA. Available online: https://hal.inria.fr/inria-00073972/file/RR-2721.pdf (accessed on 4 March 2020).
  23. Dargaye, Z. Vérification Formelle d’un Compilateur Optimisant Pour Langages Fonctionnels. Ph.D. Thesis, Université Paris 7—Denis Diderot, Paris, France, 2009. [Google Scholar]
  24. Sozeau, M.; Anand, A.; Boulier, S.; Cohen, C.; Forster, Y.; Kunze, F.; Malecha, G.; Tabareau, N.; Winterhalter, T. The MetaCoq Project. J. Autom. Reason. 2020, 64, 947–999. [Google Scholar] [CrossRef]
  25. Sozeau, M.; Boulier, S.; Forster, Y.; Tabareau, N.; Winterhalter, T. Coq Coq Correct! Verification of Type Checking and Erasure for Coq, in Coq. Proc. ACM Program. Lang. 2019, 4, 1–28. [Google Scholar] [CrossRef] [Green Version]
  26. Barras, B. Auto-Validation d’un Système de Preuves Avec Familles Inductives. Ph.D. Thesis, Université Paris 7—Denis Diderot, Paris, France, 1999. [Google Scholar]
  27. Ager, M.S. From Natural Semantics to Abstract Machines. In Proceedings of the LOPSTR 2004: Logic Based Program Synthesis and Transformation, London, UK, 7–9 September 2005; Etalle, S., Ed.; Springer: Berlin/Heidelberg, Germany, 2005; Volume 3573, pp. 245–261. [Google Scholar] [CrossRef]
  28. Biernacka, M.; Danvy, O. A Concrete Framework for Environment Machines. ACM Trans. Comput. Log. 2007, 9, 6-es. [Google Scholar] [CrossRef]
  29. Biernacka, M.; Biernacki, D. Formalizing Constructions of Abstract Machines for Functional Languages in Coq. In Proceedings of the 7th International Workshop on Reduction Strategies in Rewriting and Programming, Paris, France, 25 June 2007; Giesl, J., Ed.; Preeliminary Proceedings: Paris, France, 2007; pp. 84–99. [Google Scholar]
  30. Pirog, M.; Biernacki, D. A Systematic Derivation of the STG Machine Verified in Coq. In Proceedings of the Haskell ’10, Third ACM Haskell Symposium on Haskell, Baltimore, MA, USA, 30 September 2010; Association for Computing Machinery: New York, NY, USA, 2010; pp. 25–36. [Google Scholar] [CrossRef]
  31. Sieczkowski, F.; Biernacka, M.; Biernacki, D. Automating Derivations of Abstract Machines from Reduction Semantics. In Proceedings of the IFL 2010: Implementation and Application of Functional Languages, Alphen aan den Rijn, The Netherlands, 1–3 September 2010; Hage, J., Morazán, M.T., Eds.; Springer: Berlin/Heidelberg, Germany, 2011; Volume 6647, LNCS. pp. 72–88. [Google Scholar] [CrossRef]
  32. Biernacka, M.; Charatonik, W.; Zielinska, K. Generalized Refocusing: From Hybrid Strategies to Abstract Machines. In Proceedings of the 2nd International Conference on Formal Structures for Computation and Deduction (FSCD 2017), Oxford, UK, 3–9 September 2017; Miller, D., Ed.; Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik: Dagstuhl, Germany, 2017; Volume 84, pp. 10:1–10:17. [Google Scholar] [CrossRef]
  33. Biernacka, M.; Charatonik, W. Deriving an Abstract Machine for Strong Call by Need. In Proceedings of the 4th International Conference on Formal Structures for Computation and Deduction (FSCD 2019), Dortmund, Germany, 24–30 June 2019; Geuvers, H., Ed.; Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik: Dagstuhl, Germany, 2019; Volume 131, pp. 8:1–8:20. [Google Scholar] [CrossRef]
  34. Danvy, O.; Nielsen, L.R. Refocusing in Reduction Semantics; Technical Report RS-04-26, BRICS; Department of Computer Science, University of Aarhus: Aarhus, Denmark, 2004. [Google Scholar]
  35. Chlipala, A. A Verified Compiler for an Impure Functional Language. In Proceedings of the 37th annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Madrid, Spain, 20–22 January 2010; Association for Computing Machinery: New York, NY, USA, 2010; pp. 93–106. [Google Scholar] [CrossRef]
  36. Benton, N.; Hur, C.K. Biorthogonality, Step-Indexing and Compiler Correctness. In Proceedings of the 14th ACM SIGPLAN International Conference on Functional Programming, Edinburgh, Scotland, 31 August–2 September 2009; Association for Computing Machinery: New York, NY, USA, 2009; pp. 97–108. [Google Scholar] [CrossRef]
  37. Werner, B. Une Théorie des Constructions Inductives. Ph.D. Thesis, Université Paris-Diderot—Paris VII, Paris, France, 1994. [Google Scholar]
  38. Glondu, S. Towards Certification of the Extraction of Coq. Ph.D. Thesis, Université Paris 7—Denis Diderot, Paris, France, 2012. [Google Scholar]
  39. Mullen, E.; Pernsteiner, S.; Wilcox, J.R.; Tatlock, Z.; Grossman, D. CEuf: Minimizing the Coq Extraction TCB. In Proceedings of the 7th ACM SIGPLAN International Conference on Certified Programs and Proofs, Los Angeles, CA, USA, 8–9 January 2018; Association for Computing Machinery: New York, NY, USA, 2018; pp. 172–185. [Google Scholar] [CrossRef]
  40. Savary Bélanger, O. Verified Extraction for Coq. Ph.D. Thesis, Princeton University, Princeton, NJ, USA, 2019. [Google Scholar]
  41. Bélanger, O.S.; Appel, A.W. Shrink Fast Correctly! In Proceedings of the 19th International Symposium on Principles and Practice of Declarative Programming, Namur, Belgium, 9–10 October 2017; Association for Computing Machinery: New York, NY, USA, 2017; pp. 49–60. [Google Scholar] [CrossRef]
  42. Paraskevopoulou, Z.; Appel, A.W. Closure Conversion is Safe for Space. Proc. ACM Program. Lang. 2019, 3, 1–29. [Google Scholar] [CrossRef] [Green Version]
  43. Ahmed, A. Step-Indexed Syntactic Logical Relations for Recursive and Quantified Types. In Proceedings of the ESOP 2006: Programming Languages and Systems, Vienna, Austria, 27–28 March 2006; Sestoft, P., Ed.; Springer: Berlin/Heidelberg, Germany, 2006; Volume 3924, pp. 69–83. [Google Scholar] [CrossRef] [Green Version]
  44. Ahmed, A.; Blume, M. Typed Closure Conversion Preserves Observational Equivalence. In Proceedings of the 13th ACM SIGPLAN International Conference on Functional Programming, Victoria, BC, Canada, 22–24 September 2008; Association for Computing Machinery: New York, NY, USA, 2008; pp. 157–168. [Google Scholar] [CrossRef] [Green Version]
  45. Patrignani, M.; Ahmed, A.; Clarke, D. Formal Approaches to Secure Compilation: A Survey of Fully Abstract Compilation and Related Work. ACM Comput. Surv. 2019, 51, 1–36. [Google Scholar] [CrossRef]
  46. Abate, C.; Blanco, R.; Ciobâcă, S.; Durier, A.; Garg, D.; Hritcu, C.; Patrignani, M.; Tanter, É.; Thibault, J. Trace-Relating Compiler Correctness and Secure Compilation. In Proceedings of the ESOP 2020: Programming Languages and Systems, Dublin, Ireland, 27–30 April 2020; Müller, P., Ed.; Springer International Publishing: Cham, Switzerland, 2020; Volume 12075, pp. 1–28. [Google Scholar] [CrossRef] [Green Version]
  47. Perconti, J.T.; Ahmed, A. Verifying an Open Compiler Using Multi-language Semantics. In Proceedings of the ESOP 2014: Programming Languages and Systems, Grenoble, France, 5–13 April 2014; Shao, Z., Ed.; Springer: Berlin/Heidelberg, Germany, 2014; Volume 8410, pp. 128–148. [Google Scholar] [CrossRef] [Green Version]
  48. Neis, G.; Hur, C.K.; Kaiser, J.O.; McLaughlin, C.; Dreyer, D.; Vafeiadis, V. Pilsner: A Compositionally Verified Compiler for a Higher-Order Imperative Language. In Proceedings of the The 20th ACM SIGPLAN International Conference on Functional Programming, Vancouver, BC, Canada, 31 August–2 September 2015; Association for Computing Machinery: New York, NY, USA, 2015; pp. 166–178. [Google Scholar] [CrossRef] [Green Version]
  49. Patterson, D.; Ahmed, A. The next 700 Compiler Correctness Theorems (Functional Pearl). Proc. ACM Program. Lang. 2019, 3, 1–29. [Google Scholar] [CrossRef] [Green Version]
  50. Dreyer, D.; Ahmed, A.; Birkedal, L. Logical Step-Indexed Logical Relations. Log. Methods Comput. Sci. 2011, 7. [Google Scholar] [CrossRef] [Green Version]
  51. Jung, R.; Swasey, D.; Sieczkowski, F.; Svendsen, K.; Turon, A.; Birkedal, L.; Dreyer, D. Iris: Monoids and Invariants as an Orthogonal Basis for Concurrent Reasoning. In Proceedings of the 42nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Mumbai, India, 15–17 January 2015; Association for Computing Machinery: New York, NY, USA, 2015; pp. 637–650. [Google Scholar] [CrossRef]
  52. Jung, R.; Krebbers, R.; Birkedal, L.; Dreyer, D. Higher-Order Ghost State. In Proceedings of the 21st ACM SIGPLAN International Conference on Functional Programming, Nara, Japan, 18 September 2016; Association for Computing Machinery: New York, NY, USA, 2016. ICFP 2016. pp. 256–269. [Google Scholar] [CrossRef]
  53. Krebbers, R.; Jung, R.; Bizjak, A.; Jourdan, J.H.; Dreyer, D.; Birkedal, L. The Essence of Higher-Order Concurrent Separation Logic. In Proceedings of the ESOP 2017: Programming Languages and Systems, Uppsala, Sweden, 25–28 April 2017; Yang, H., Ed.; Springer: Berlin/Heidelberg, Germany, 2017; Volume 10201, pp. 696–723. [Google Scholar] [CrossRef] [Green Version]
  54. Linn Georges, A.; Trieu, A.; Birkedal, L. Mechanized Reasoning about a Capability Machine. Available online: https://iris-project.org/pdfs/2020-iris-capabilities-prisc-conf.pdf (accessed on 4 March 2020).
  55. Cuellar, S.; Giannarakis, N.; Madiot, J.M.; Mansky, W.; Beringer, L.; Cao, Q.; Appel, A.W. Compiler Correctness for Concurrency: From Concurrent Separation Logic to Shared-Memory Assembly Language; Technical Report TR-014-19; Department of Computer Science, Princeton University: Princeton, NJ, USA, 2020. [Google Scholar]
  56. Cuellar, S. Concurrent Permission Machine for Modular Proofs of Optimizing Compilers with Shared Memory Concurrency. Ph.D. Thesis, Princeton University, Princeton, NJ, USA, 2020. [Google Scholar]
  57. Nakata, K.; Uustalu, T. Trace-Based Coinductive Operational Semantics for While. In Proceedings of the International Conference on Theorem Proving in Higher Order Logics 2009, Munich, Germany, 17–20 August 2009; Berghofer, S., Nipkow, T., Urban, C., Wenzel, M., Eds.; Springer: Berlin/Heidelberg, Germany, 2009; Volume 5674, pp. 375–390. [Google Scholar] [CrossRef]
  58. Leroy, X. L’éternité c’est Long … Sémantiques de la Divergence: Théorie des Domaines et Approches Coinductives. Sémantiques Mécanisées, Sixième Cours, Collège de France. 2020. Available online: https://www.college-de-france.fr/media/xavier-leroy/UPL2331162062302586657_leroy_cours_6.pdf (accessed on 4 March 2020).
  59. Leroy, X. Personal communication, 2020.
  60. Paulin-Mohring, C. Extraction de Programmes dans le Calcul des Constructions. Ph.D. Thesis, Université Paris-Diderot—Paris VII, Paris, France, 1989. [Google Scholar]
  61. Zúñiga, A. (Coinductive) Natural Semantics for Compiler Verification in Coq: The Coq Development. Available online: https://sites.google.com/a/ciencias.unam.mx/zuniga/repository/cnsvcompiler.tgz (accessed on 24 August 2020).
  62. Jourdan, J.H.; Laporte, V.; Blazy, S.; Leroy, X.; Pichardie, D. A Formally-Verified C Static Analyzer. ACM SIGPLAN Not. 2015, 50, 247–259. [Google Scholar] [CrossRef]
  63. Jourdan, J.H.; Pottier, F.; Leroy, X. Validating LR(1) Parsers. In Proceedings of the European Symposium on Programming, ESOP 2012, Tallinn, Estonia, 24 March–1 April 2012; Seidl, H., Ed.; Springer: Berlin/Heidelberg, Germany, 2012; Volume 7211, pp. 397–416. [Google Scholar] [CrossRef] [Green Version]
  64. Landin, P.J. The Mechanical Evaluation of Expressions. Comput. J. 1964, 6, 308–320. [Google Scholar] [CrossRef] [Green Version]
  65. Henderson, P. Functional Programming Application and Implementation; Computer Science, Prentice-Hall International: Upper Saddle River, NJ, USA, 1980. [Google Scholar]
  66. Giménez, E. Un Calcul de Constructions Infinies et Son Application a la Vérification de Systemes Communicants. Ph.D. Thesis, École Normale Supérieure de Lyon, Lyon, France, 1996. [Google Scholar]
  67. Tollitte, P.N.; Delahaye, D.; Dubois, C. Producing Certified Functional Code from Inductive Specifications. In Proceedings of the International Conference on Certified Programs and Proofs, Kyoto, Japan, 13–15 December 2012; Hawblitzel, C., Miller, D., Eds.; Springer: Berlin/Heidelberg, Germany, 2012; Volume 7679, pp. 76–91, CPP 2012. [Google Scholar] [CrossRef]
  68. Dubois, C.; Ménissier-Morain, V. Certification of a Type Inference Tool for ML: Damas–Milner within Coq. J. Autom. Reason. 1999, 23, 319–346. [Google Scholar] [CrossRef]
  69. Pereira, F.C.N.; Warren, D.H.D. Parsing as Deduction. In Proceedings of the 21st Annual Meeting of the Association for Computational Linguistics, ACL ’83, Cambridge, MA, USA, 15–17 June 1983; Association for Computational Linguistics: Cambridge, MA, USA, 1983; pp. 137–144. [Google Scholar] [CrossRef] [Green Version]
  70. Shieber, S.M.; Schabes, Y.; Pereira, F.C.N. Principles and implementation of deductive parsing. J. Log. Program. 1995, 24, 3–36. [Google Scholar] [CrossRef] [Green Version]
Figure 1. Compiler architecture. (a) Compilation; (b) Execution.
Figure 1. Compiler architecture. (a) Compilation; (b) Execution.
Mathematics 08 01573 g001
Table 1. MSECD small-step semantics.
Table 1. MSECD small-step semantics.
CurrentNext
CodeEnvironmentStackCodeEnvironmentStack
( IConst n ) · c Δ sc Δ n · s
( IConstb b ) · c Δ sc Δ b · s
IAdd · c Δ n 2 · n 1 · s c Δ n 1 + n 2 · s
ISub · c Δ n 2 · n 1 · s c Δ n 1 n 2 · s
IMul · c Δ n 2 · n 1 · s c Δ n 1 n 2 · s
IEq · c Δ n 2 · n 1 · s c Δ n 1 = n 2 · s
( IAcc i ̲ ) · c [ v 0 , , v i , , v n ] = Δ sc Δ v i · s
ILet · c Δ v · s c v · Δ s
IEndLet · c v · Δ sc Δ s
( ISel c 1 c 2 ) · c Δ t r u e · s c 1 Δ ( c , [ ] ) · s
( ISel c 1 c 2 ) · c Δ f a l s e · s c 2 Δ ( c , [ ] ) · s
IJoin · c Δ v · ( c b , [ ] ) · s c b Δ v · s
( IClos c 1 ) · c Δ sc Δ c 1 [ Δ ] · s
( IClos r e c c 1 ) · c Δ sc Δ c 1 [ Δ ] r e c · s
IApp · c Δ v · c 1 [ Δ 1 ] · s c 1 v · Δ 1 ( c , Δ ) · s
IApp · c Δ v · c 1 [ Δ 1 ] r e c · s c 1 v · c 1 [ Δ 1 ] r e c · Δ 1 ( c , Δ ) · s
IRet · c Δ v · ( c 1 , Δ 1 ) · s c 1 Δ 1 v · s

Share and Cite

MDPI and ACS Style

Zúñiga, A.; Bel-Enguix, G. Coinductive Natural Semantics for Compiler Verification in Coq. Mathematics 2020, 8, 1573. https://doi.org/10.3390/math8091573

AMA Style

Zúñiga A, Bel-Enguix G. Coinductive Natural Semantics for Compiler Verification in Coq. Mathematics. 2020; 8(9):1573. https://doi.org/10.3390/math8091573

Chicago/Turabian Style

Zúñiga, Angel, and Gemma Bel-Enguix. 2020. "Coinductive Natural Semantics for Compiler Verification in Coq" Mathematics 8, no. 9: 1573. https://doi.org/10.3390/math8091573

Note that from the first issue of 2016, this journal uses article numbers instead of page numbers. See further details here.

Article Metrics

Back to TopTop