Éric Jaeger

Catherine Dubois

Why Would You Trust B ?

Keywords: Confidence, Formal Methods, Prover, Deep embedding

The use of formal methods provides confidence in the correctness of developments. Yet one may argue about the actual level of confidence obtained when the method itself -or its implementation -is not formally checked. We address this question for the B, a widely used formal method that allows for the derivation of correct programs from specifications. Through a deep embedding of the B logic in Coq, we check the B theory but also implement B tools. Both aspects are illustrated by the description of a proved prover for the B logic.

A clear benefit of formal methods is to increase the confidence in the correctness of developments. However, one may argue about the actual level of confidence obtained, when the method or its implementation are not themselves formally checked. This question is legitimate for safety, as one may accidentally derive invalid results. It is even more relevant when security is a concern, as any flaw can be deliberately exploited by a malicious developer to obfuscate undesirable behaviours of a system while still getting a certification.

B [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF] is a popular formal method that allows for the derivation of correct programs from specifications. Several industrial implementations are available (e.g. AtelierB, B Toolkit ), and it is widely used in the industry for projects where safety or security is mandatory. So the B is a good candidate for addressing our concern: when the prover says that a development is right, who says that the prover is right? To answer this question, one has to check the theory as well as the prover w.r.t. this theory (or, alternatively, to provide a proof checker). Those are the objectives of BiCoq, a deep embedding of the B logic in Coq [START_REF]The Coq development team: The Coq proof assistant reference manual[END_REF].

BiCoq benefits from the support of Coq to study the theory of B, and to check the validity of standard definitions and results. BiCoq also allows us, through an implementation strategy, to develop formally checked B tools. This strategy is illustrated in this paper by the development of a prover engine for the B logic, that can be extracted and used independently of Coq. Coq is therefore our notary public, witnessing the validity of the results associated to the B theory, as well as the correctness of tools implementing those results -ultimately increasing confidence in B developments. The approach, combining a deep embedding and an implementation technique, can be extended to address further elements of the B, beyond its logic, or to safely enrich it, as illustrated in this paper.

This paper is divided into 9 sections. Sections 1, 2 and 3 briefly introduce B, Coq and the notion of embedding. The B logic and its formalisation in Coq are presented in Sec. [START_REF] Boulton | Experience with embedding hardware description languages in hol[END_REF]. Section 5 describes various results proved using BiCoq. Section 6 focuses on the implementation strategy, and presents its application to the development of a set of extractible proof tactics for a B prover. Section 7 discusses further uses of BiCoq, and mentions some existing extensions. Finally, Sect. 8 concludes and identifies further activities.

A Short Introduction to B

In a nutshell, the B method defines a first-order predicate logic completed with elements of set theory, a Generalised Substitution Language (GSL) and a methodology of development. An abstract B machine is a module combining a state, properties and operations (described as substitutions) to read or alter the state.

The logic is used to express preconditions, invariants, etc. and to conduct proofs. The GSL allows for definitions of substitutions that can be abstract, declarative and non-deterministic (that is, specifications) as well as concrete, imperative and deterministic (that is, programs). The following example uses the non-deterministic substitution ANY (a "magic" operator finding a value which satisfies a property) to specify the square root of a natural number n:

Example 1. ANY x WHERE x * x ≤ n < (x+1) * (x+1) THEN p (n) := x END
Regarding the methodology, a machine M C refines an abstract machine M A if one cannot distinguish M C from M A by valid operation calls -this notion being independent of the internal representations, as illustrated by the following example of a system returning the maximum of a set of stored values:

Example 2. The state of MA is a (non implementable) set of natural numbers; the state of MC is a natural number. Yet MC , having the expected behaviour, refines MA.

MACHINE MA VARIABLES S INVARIANT S ⊆ N INITIALISATION S := ∅ OPERATIONS store(n) PRE n ∈ N THEN S := S ∪{n} END m ← get PRE S = ∅ THEN m := max(S) END END REFINEMENT MC VARIABLES s INVARIANT s = max(S ∪{0}) INITIALISATION s := 0 OPERATIONS store(n) IF s < n THEN s := n END m ← get BEGIN m := s END END
Refinement being transitive, it is possible to go progressively from the specification to the implementation. By discharging at each step the proof obligations defined by the B methodology, a program can be proved to be a correct and complete implementation of a specification. This methodology, combined with the numerous native notions provided by the set theory and the existence of toolkits, make the B a popular formal method, widely used in the industry.

Note that the B logic is not genuinely typed and allows for manipulation of free variables. A special mechanism, called type-checking (but thereafter referred to as wf-checking), filters ill-formed (potentially paradoxal) terms; it is only mentioned in this paper, deserving a dedicated analysis.

The rest of the paper only deals with the B logic (its inference rules).

A Short Introduction to Coq

Coq is a proof assistant based on a type theory. It offers a higher-order logical framework that allows for the construction and verification of proofs, as well as the development and analysis of functional programs in an ML-like language with pattern-matching. For the intent of this paper, it is sufficient to see Coq as allowing for the manipulation of inductive sets of terms. For example, let's consider the standard representation of natural numbers:

Example 3. Inductive N : Set := 0 : N | S : N → N
It defines a type N which is the smallest set of terms stable by application of the constructors 0 and S. N is exactly made of the terms 0 and S n (0) for any finite n; being well-founded, structural induction on N is possible.

Coq also allows for the declaration of inductive logical properties, e.g.: It defines a family of logical types: ev 0 is a type inhabited by the term (ev 0 ), ev 2 is another type inhabited by (ev 2 0 ev 0 ), and ev 1 is an empty type. The standard interpretation is that ev 0 is a proof of the proposition ev 0 and that there is no proof of ev 1, that is we have ¬(ev 1). An intuitive interpretation of our two examples is that N is a set of terms, and ev a predicate marking some of them, defining a subset of N.

Deep Embedding and Related Works

Embedding in a proof assistant consists in mechanizing a guest logic by encoding its syntax and semantic into a host logic ( [START_REF] Gordon | Mechanizing programming logics in higher-order logic[END_REF][START_REF] Boulton | Experience with embedding hardware description languages in hol[END_REF][START_REF] Azurat | A survey on embedding programming logics in a theorem prover[END_REF]). In a shallow embedding, the encoding is partially based on a direct translation of the guest logic into constructs of the host logic. In a deep embedding the syntax and the semantic are formalised as datatypes. At a fundamental level, taking the view presented in Sec. 2, the deep embedding of a logic is simply a definition of the set of all sequents (the terms) and a predicate marking those that are provable (the inference rules of the guest logic being encoded as constructors of this predicate). Shallow embeddings of B in higher-order logics have been proposed in several papers (cf. [START_REF] Bodeveix | A formalization of the B-method in Coq and PVS[END_REF][START_REF] Chartier | Formalisation of B in Isabelle/HOL[END_REF]) formalising the GSL in PVS, Coq or Isabelle/HOL. Such embeddings are not dealing with the B logic, and by using directly the host logic to express B notions, they introduce a form of interpretation. If the objective is to have an accurate formalisation of the guest system, the definition of a valid interpretation is difficult -e.g. B functions are relations, possibly partial or undecidable, and translating accurately this concept in Coq is a tricky exercise.

BiCoq aims at such an accurate formalisation, to pinpoint any problem of the theory with the objective to increase confidence in the developments when safety or security is a concern; in addition, we also have an implementation objective. In such cases, a deep embedding is fully justified -see for example the development of a sound and complete theorem prover for first-order logic verified in Isabelle proposed in [START_REF] Ridge | A mechanically verified, sound and complete theorem prover for first order logic[END_REF].

A deep embedding of the B logic in Coq is described in [START_REF] Berkani | Validation des règles de base de l'Atelier B[END_REF] (using notations with names), to validate the base rules used by the prover of Atelier-B -yet not checking standard B results, and without implementation goal. As far as the implementation of a trusted B prover is concerned, we can also mention the encoding of the B logic as a rewriting system proposed in [START_REF] Cirstea | Using rewriting and strategies for describing the B predicate prover[END_REF].

Deep embeddings have also the advantage to clearly separate the host and the guest logics: in Bicoq, excluded middle, provable in B, is not promoted to Coq. This improves readibility, and allows one to study meta-theoretical questions such as consistency. Furthermore, the host logic consistency is not endangered.

Formalising the B Logic in Coq

In this section, we present our embedding of the B logic in the Coq system; the embedding uses a De Bruijn representation that avoids ambiguities and constitutes an efficient solution w.r.t. the implementation objective (see [START_REF] De Bruijn | Lambda calculus notation with nameless dummies, a tool for automatic formula manipulation, with application to the church-rosser theorem[END_REF][START_REF] Liang | Tradeoffs in the intensional representation of lambda terms[END_REF]). Deviations between B and its formalisation are described and justified.

Notation. B definitions use upper case letters with standard notations. BiCoq uses lower case letters, and mixes B and Coq notations; standard notations are used for Coq (e.g. ∀ is the universal quantification) while dotted notations are used for the embedded B (e.g. ∀ is the universal quantification constructor).

Notation.

[T ] denotes the type of the lists whose elements have type T .

Syntax

Given a set of identifiers (I), the B logic syntax defines predicates (P ), expressions (E), sets (S) and variables (V ) as follows: The first design choice of BiCoq is to use a pure nameless De Bruijn notation (see [START_REF] De Bruijn | Lambda calculus notation with nameless dummies, a tool for automatic formula manipulation, with application to the church-rosser theorem[END_REF][START_REF] Aydemir | Engineering aspects of formal metatheory[END_REF]), where variables are represented by indexes giving the position of their binder -here the universal quantifier and the comprehension set. When an index exceeds the number of parent binders, it is said to be dangling and represents a free variable, whose name is provided by a scope (left implicit in this paper), so that any syntactically correct term is semantically valid, and there is no need for well-formedness condition 4 . In this representation, proofs of side conditions related to name clashing are replaced by computations on indexes, but the index representing a variable is not constant in a term.

P := P ∧P | P⇒P | ¬P | ∀ V • P | E = E | E ∈ E | [V :=E]P E := V | S | E → E | ↓ S | [V :=E]E S := BIG | ↑ S | S ×S | {V |P } V := I | V, V In this syntax, [V := E]T represents the (elementary) substitution, V 1 , V 2 a list of variables, E 1 → E 2 a
The B syntax is formalised in Coq by two mutually inductive types with the following constructors, I being the set of indexes (that is, N\{0}) and J an infinite set of names with a decidable equality:

P := P ∧P | P ⇒P | ¬P | ∀ P | E =E | E ∈E E := χI | E ˙ →E | ↓E | Ω | ↑E | E ×E | {E ˙|P} | ωJ
P represents B predicates, while E merges B expressions, sets and variables. Using a De Bruijn representation, binders ∀ and { ˙|} have no attached names and only bind (implicitly) a single variable. Binding over list of variables can be eliminated without loss of expressivity, as illustrated by the following example:

Example 5. {V | V ∈ S1×S2∧ ∃V1 • (V1 ∈ S1∧ ∃V2 • (V2 ∈ S2∧V1 → V2 = V ∧P ))} represents {V1, V2 | V1, V2 ∈ S1 ×S2 ∧P } 5
The constructor { ˙|} is further modified to be parameterised by an expression, to keep in the syntax definition only wf-checkable terms. Indeed, only comprehension sets of the form {V | V ∈ E ∧ P }, with V not free in E, are valid. The BiCoq representation of this set is {e ˙|p}; to reflect the non-freeness condition, {e ˙|p} only binds variables in its predicate parameter p. By these design choices, we bridge the gap between syntactically correct terms and wf-checkable ones, while being conservative.

Ω represents the constant set BIG, χ unary (De Bruijn) variables. The constructor ω is without B equivalent, and provides elements of Ω (cf. Par. 4.3).

Notation. χi denotes the application of constructor χ to i : I and ωj of constructor ω to j : J. By abuse of notation the variable χi is also denoted simply by i.

Finally, the elementary substitution is not considered in BiCoq as a syntactical construct but is replaced by functions on terms -substitution being introduced earlier in B only to be used in the description of inference rules. Note however that the full GSL of B can still be formalised by additional terms constructors (the explicit substitution approach, see [START_REF] Abadi | Explicit substitutions[END_REF][START_REF] Curien | Confluence properties of weak and strong calculi of explicit substitutions[END_REF]).

Notation. p1 ⇔p2 is defined as p1 ⇒p2 ∧p2 ⇒p1, p1 ∨p2 as ¬p1 ⇒p2, and ∃p as ¬ ∀ ¬p.

Notation. T denotes the type of terms, that is the union of P and E.

Dealing with the De Bruijn Notation

De Bruijn notation is an elegant solution to avoid complex name management, and it has numerous merits. But it also has a big drawback, being an unusual representation for human readers: Example 6. If x ∈ y is the interpretation of the term 1 ∈2, the interpretation of the term ∀(1 ∈2) is ∀t•t ∈ x; because of the binder, the scope has shifted (so 2 now represents x), and (likely) the semantic has been distorted.

In this paragraph, we illustrate some of the consequences of using a De Bruijn notation, as well as how to mask such consequences from the users.

Induction When defining type T, Coq automatically generates the associated structural induction principle. As illustrated in Ex. 6, it is however not semantically adequate, because it does not reflect De Bruijn indexes scoping. A more interesting principle is derived in BiCoq by using the syntactical depth function D of a term as a well-founded measure: ∀ (P : T → P rop), (∀ (t : T), (∀ (t ′ : T), D(t ′ ) < D(t) → P t ′ ) → P t) → ∀ (t : T), P t With this principle, for the term ∀(1 ∈3) (that is, ∀t•t ∈ y) we can choose to use an induction hypothesis on 1 ∈2 (that is, x ∈ y) instead of 1 ∈3 (that is, x ∈ z).

Non-Freeness The B notation V \T means that the variable V does not appear free in T . Non-freeness is defined in BiCoq as a type ˙ : I → T → P rop (a relation between I, representing the variables, and T), with the following rules6 :

i ˙ Ω i ˙ ωk i1 = i2 i1 ˙ i2 (i+1) ˙ p i ˙ ∀ p i ˙ e (i+1) ˙ p i ˙ {e ˙|p}
The two first rules are axioms, the associated constructors are atomic and do not interact with variables. The rules for ∀ and { ˙|} reflect the fact that the associated constructors are binders and therefore shift the scope.

Binding, Instantiation and Substitution It is possible to define functions to simulate B binding (that is the use of ∀ or {}, representing λ-abstraction). These functions constitute a built-in user interface to produce De Bruijn terms while using the usual representation, making De Bruijn indexes and their management invisible to the user (see also [START_REF] Gordon | A mechanisation of name-carrying syntax up to alpha-conversion[END_REF] for a similar approach):

Usual rep. ∀ V1 •V1 ∈ {V2 | V2 ∈ E ∧V1 = V2} v v S S Pretty-printing Functional rep. ↑ ∀ (i1 •i1 ∈ ↑ {} (i2 : e•i1 =i2)) Computation + + Internal rep. ∀ (1 ∈{e ˙|2 =1})
The binding functions are defined by:

↑ ∀ (i•p) := ∀ Bind i 1 p ↑ {} (i : e•p) := {e ˙|Bind i 1 p} ↑ ∃ (i•p) := ∃Bind i 1 p Bind(i1 i2 : I)(t : T) : T := match t with | Ω | ωj ′ ⇒ t | χi ′ ⇒ t if i ′ < i2, or else χi 2 if i ′ = i1, or else χi ′ +1 | ∀ p ′ ⇒ ∀ (Bind (i1 +1) (i2 +1) p ′ ) | {e ′| p ′ } ⇒ {Bind i1 i2 e ′ ˙| Bind (i1 +1) (i2 +1) p ′ } | . . . ⇒ . . . (straightforward extension)
On the same principles, the definition of instantiation functions (for elimination of ∀ or {}, representing β-reduction and denoted by ↓ ∀ (p ← e) : P → E → P and ↓ {} (e 1 ← e 2 ) : E → E → P) is straightforward -being partial, these functions just require in Coq an additional proof parameter (omitted in this paper) that the term is of the expected form. Finally, it is also possible to define a substitution function 7 :

i := e t : I → E → T → T := match t with | Ω | ωj ′ ⇒ t | χi ′ ⇒ if i ′ = i then e else t | ∀ p ′ ⇒ ∀ i+1 := Lift(e) p ′ | {e ′| p ′ } ⇒ { i := e e ′| i+1 := Lift(e) p ′ } | . . . ⇒ . . . (straightforward extension)
where Lift, not detailed in this paper, increments dangling De Bruijn indexes. Remember that substitution is introduced early in B as a syntactical construct, but only to be used in inference rules. We consider that such rules are better represented using the resulting term (that is, the reduction of the application of the substitution). Once these functions are defined, numerous lemmas are proved, such as the (in)famous ones describing all possible interactions between lifting, binding, instantiation and substitution. The following results are then derived, proving the irrelevance of α-renaming or describing relationships between instantiation, binding and substitution (with = the Coq term structural equality):

i2 ˙ p → ↑ ∀ (i1 •p) =↑ ∀ (i2 • i1 := i2 p) i2 ˙ p → ↑ {} (i1 : e•p) =↑ {} (i2 : e• i1 := i2 p) ↓ ∀ (↑ ∀ (i•p) ← i) = p ↓ {} (↑ {} (i : e•p) ← i) = i ∈e ∧ p ↓ ∀ (↑ ∀ (i•p) ← e) = i := e p

Inference Rules

Having formalised the B syntax and defined some functions and properties on terms, the next step is to encode the B inference rules. Thanks to the use of the functional representation described in the previous paragraph, BiCoq rules look very much like the standard B rules. The translation is therefore straightforward, merely a syntactical one, and the risk of error is very limited.

In our formalisation sets of hypothesis are represented by lists, with membership (∈) and inclusion (⊆) as well as the pointwise extension of non-freeness ( ˙ ). The B inference rules are formalised as constructors of an inductive type ⊢ : [P] → P → P rop, that is g ⊢ p is the Coq type of all B proofs of p under the assumptions g. Such a type may be inhabited (i.e. p is provable assuming g) or empty (i.e. there is no proof of p under the assumptions of g).

The B rules and their encoding as constructors are detailed in Tab. 1, universal quantifications being omitted (the types are g, g 1 , g 2 : [P]; p, p 1 , p 2 : P; e, e 1 , e 2 , e 3 , e 4 : E, i, i 1 , i 2 : I and j, j 1 , j 2 : J). For most of them, translation is straightforward, only taking care to use functional substitution and binding where appropriate. On the other hand, the use of the functional representation imposes to keep the syntactical side conditions, except for the comprehension set rule, where such condition is embedded in the syntax; new rules have to be derived to benefit of the internal De Bruijn representation.

Only the last two B inference rules deserve discussion. The first one of these indicates that the constant set BIG is infinite, using the infinite B predicate defined by a fixpoint; unfolding this definition to produce a translation is possible, but not practical. Therefore, this rule is replaced in BiCoq by two different rules allowing to exhibit an infinity of elements of BIG, J being itself infinite.

The last rule, defining the semantics of pairs and products, is more interesting. A straightforward translation of this rule indeed leads to the impossibility to prove, in BiCoq, the following theorems from [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF]:

⊢ (E → F ) = (E ′ → F ′ ) ⇒ E = E ′ ∧ F = F ′ ⊢ S ∈↑ U ∧ T ∈↑ V ⇒ (S × T ) ∈↑ (U × V )
The proof of the first result provided in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF] is flawed, due to a confusion between pairs of expressions and lists of variables (as pointed out in [START_REF] Mussat | Private Communication[END_REF]), both using the same notation -and cannot be corrected in the absence of a form of destructor for pairs. On the other hand, the proof of the monotonicity of cartesian product w.r.t. inclusion is not detailed in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF], being considered trivial. However, using the listed rules, one may derive predicates of the form V ∈ S ×T but without being able to constraint V to be a pair to apply the last rule (a classical problem of the untyped λ-calculus). Basically, injectivity and surjectivity rules are lacking; Table 1. Encoding of the B inference rules

V \S ⊢ E ∈ {V |V ∈S ∧P } ⇔ E∈S ∧[V :=E]P ⊢ e1 ∈ ↑ {} (i : e2 •p) ⇔e1 ∈e2 ∧ i := e1 p Γ ⊢ E = F Γ ⊢ [V :=E]P Γ ⊢ [V :=F ]P g ⊢ e1 =e2 → g ⊢ i := e1 p → g ⊢ i := e2 p V \S ⊢ ∃ V • (V ∈ S) ⇒↓ S ∈ S i ˙ e → g ⊢ ↑ ∃ (i•i ∈e) ⇒ ↓e ∈e V \S,T ⊢ S ∈↑ T ⇔ ∀ V • (V ∈ S ⇒ V ∈ T ) i ˙ e1 → i ˙ e2 → g ⊢ e1 ∈ ↑e2 ⇔ ↑ ∀ (i•i ∈e1 ⇒i ∈e2) V \S,T ⊢ " ∀ V •(V ∈ S ⇒ V ∈ T ) ∧∀ V •(V ∈ T ⇒ V ∈ S) « ⇔ S = T g ⊢ e1 ∈ ↑e2 → g ⊢ e2 ∈ ↑e1 → g ⊢ e1 =e2 ⊢ infinite(BIG) g ⊢ ωj ∈ Ω j1 = j2 → g ⊢ ¬( ωj 1 = ωj 2 ) ⊢ (E →F ) ∈ (S×T ) ⇔ (E∈S)∧(F∈T ) g ⊢ e1 ˙ →e2 =e3 ˙ →e4 → g ⊢ e1 =e3 g ⊢ e1 ˙ →e2 =e3 ˙ →e4 → g ⊢ e2 =e4 i1 ˙ e ∈(e1 ×e2) → i2 ˙ e ∈(e1 ×e2) → i1 = i2 → g ⊢↑ ∃ (i1 •i1 ∈e1 ∧↑ ∃ (i2 •i2 ∈e2 ∧e =i1 ˙ →i2)) ⇔e ∈(e1 ×e2)
these observations, probably well known of the B gurus but not documented to our knowledge, have led us to replace this B rule by three new rules in order to be able to prove the expected theorems. Again, this process illustrates our conservative approach.

5 Proofs in BiCoq

Standard B Proofs

Using the definition of ⊢ , we formally prove in BiCoq all propositional calculus and predicate calculus results of [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF], using the functional representation and following the proposed proof structure, e.g.:

i1 ˙ g → i1 ˙ p → g ⊢ i2 := i1 p → g ⊢ ↑ ∀ (i2 •p), that is Γ ⊢ [V2 := V1]P V1\Γ,P Γ ⊢ ∀ V2 •P
To assist the proof construction BiCoq provides Coq tactics written in the Coq tactic language [START_REF] Delahaye | A tactic language for the system Coq[END_REF]. For example, the propositional calculus procedure described in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF], proposing a strategy based on propositional calculus theorems, is provided as a Coq tactic. More technical Coq tactics are also available in BiCoq, e.g. to obtain proved fresh variables.

An alternative form of theorems is also derived, using the internal De Bruijn representation; e.g. the ∀-introduction rule (to be compared with [∀i]) is:

i ˙ g → i ˙ ∀ p → g ⊢ Inst i 1 p → g ⊢ ∀ p
These last results are of course rather technical, not benefiting from the functional representation. Yet they have some interest, for technical lemmas or as derived rules in which only semantical side conditions remain (computations over De Bruijn indexes dealing with the syntactical ones).

Mixing BiCoq and Coq Logics

As it is standard in such a deep embedding (e.g. see [START_REF] Berkani | Validation des règles de base de l'Atelier B[END_REF]), BiCoq provides also results expressing relations between host and guest logics:

(g ⊢ p ∨ g ⊢ q) → g ⊢ p ∨q g ⊢ p ⇒g → (g ⊢ p → g ⊢ p) (g ⊢ p ∧ g ⊢ q) ↔ g ⊢ p ∧q (∀ (y : I), g ⊢ x := y p) ↔ g ⊢ ↑ ∀ (x•p)
Asymmetrical results mark the differences between the classical B logic and the constructive Coq logic -e.g. a reciprocal of the first rule, combined with the excluded middle, would prove that for any predicate p either ⊢ p or ⊢ ¬p, which of course is not the case. This emphasises the fact that both logics are well separated, the B logic being embedded has an external theory. By providing the best of both worlds, these results constitute efficient proof tactics. For example, the last theorem does not reflect non-freeness side conditions from B to the Coq logic (Coq taking care of such conditions automatically).

In this section, we detail how BiCoq is used as a framework for the development of formally checked B toolkits. Coq offers mechanisms to extract programs from constructive proofs (i.e. software from logical definitions and theorems), but a different approach is chosen here. Indeed, BiCoq includes code (in the form of functions using the ML-like internal language of Coq) which is proved correct. This code is extractible by a pure syntactical process, e.g. in Objective Caml, using the extraction mechanism of Coq. By doing so, we obtain proved B tools whose code is small, readable and efficient -and independent of Coq.

Notation. B represents the booleans, ⊤ being true and ⊥ being f alse.

Notation. Hat notations are used for boolean functions (e.g. b ∧ is the boolean and).

Implementing Decidable Properties

For P and f respectively a predicate and a boolean function over a type S, we note (P f ) when f decides P , i.e. when the following property is proved:

∀(s : S), (f (s) = ⊤ → P (s)) ∧ (f (s) = ⊥ → ¬P (s))
By defining folding as the extension of predicates and functions to lists, we prove that if f decides P , then the folding of f decides the folding of P :

Foldp(P ) := f un(L : [S]) ⇒ ∀(s : S), s ∈ L → P (s) Fold f (f ) := f un(L : [S]) ⇒ if empty(L) then ⊤ else f (head(L)) b ∧Fold f (f )(tail(L)) (P f ) → (Foldp(P ) Fold f (f ))
Example 7 (Non-freeness). Non-freeness is defined in B as a logical proposition and represented by the inductive type ˙ in BiCoq. Our implementation strategy consists in developing a program b : I → T → B and to prove that ( ˙ b ). Hence b and its extension (checking that a variable does not occur free in a list of hypotheses) are proved correct and can be extracted.

In BiCoq this approach is systematic; all typed equalities are implemented and proved correct (e.g. term equality), as well as non-freeness, list membership, inclusion, etc. to constitute our formally checked B toolkit.

A Proved Prover for the B Logic

In this paragraph we focus on the definition of an extractible prover to conduct first-order B proofs for standard B developments.

BiCoq includes programs, named B tactics in the following, to simulate the application of B inference rules or theorems. By providing such a dedicated piece of code for each of the inference rules listed in Tab. 1, and by proving them correct, we got a correct and complete prover (that is, any standard B result can be derived using this prover).

To this end, a type for sequents is defined as the product [P]×P; for g : [P] and p : P we denote g p the associated pair. While g ⊢ p is the type of B proofs of p under the assumptions g, that can be inhabited or not, g p is a syntactical construct extending T. To interpret a sequent, we use the translation Trans ⊢ that for a pair g p returns the type g ⊢ p (and its extension derived by Fold p ).

A B tactic is a function T B : → [ ] that, provided a goal g p, returns a list of subgoals [g 1 p 1 , . . . , g n p n ] which together are sufficient to prove g p; if a B tactic concludes (proves the goal) this list is empty. Example 9. T∧ i (s) := let (g p := s) in match p with p1 ∧p2 ⇒ [g p1, g p2] | ⇒ [s] The implementation strategy described in Par. 6.1 is now particularly relevant, as T ∈ uses the boolean function ∈ instead of the logical proposition ∈.

Following the same principles, numerous (much more complex) B tactics are provided in BiCoq, implementing theorems or strategies, such as the decision procedure for propositional calculus described in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF]. For each B tactic T B , the correctness is ensured by a proof of the following property:

∀ (s : ), Trans ⊢ (TB(s)) → Trans ⊢ (s), that is g1 ⊢ p1 . . . gn ⊢ pn g ⊢ p
Thanks to the functions defined in Par. 4.2, management of the De Bruijn indexes can be hidden from the users of the B tactics. With the programs already provided in BiCoq (such as non-freeness, binding, etc.), these B tactics constitute the core of a proved prover. This prover still lacks automation and HMI, and should be coupled with other tools, for example a B parser using the platform BRILLANT [START_REF] Colin | BRIL-LANT : An open source and XML-based platform for rigourous software development[END_REF].

Higher-Order Considerations and Extensions

While the B logic is first-order, various definitions and proofs in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF] are conducted in a higher-order meta-logic: results in propositional calculus are proved by induction over terms, and refinement is defined by quantification over predicates before being transformed into an equivalent first-order definition. Using the higher-order framework provided by Coq, BiCoq can clearly be extended to integrate and to formally check such concepts.

New results can also be derived; for example, using the proof depth function D ⊢ : ⊢→ I, we obtain a depth induction principle on B proof trees e.g. for results about proof rewriting. Other results, proved in higher-order logic, are applicable in first-order B logic, and implemented as B tactics for standard B proofs. This is the case for the following congruence results.

Predicate Substitution. We extend the B logic syntax with a new predicate variable constructor πK : P (K being an infinite set of names with a decidable equality), without adding any inference rules in order not to enrich the BiCoq logic8 . Only limited modifications of BiCoq are required to deal with this new constructor, e.g. non-freeness with the additional rule ∀ (i : I)(k : K), i ˙ πk .

Predicate variables play a role similar to the one of the variables -they are placeholders that can be replaced by a predicate using the substitution function k :≡ p 1 p 2 : K → P → P → P, not detailed in this paper, that mimicks the expression substitution function (see Par. 4.2). Thanks to this extension, we can prove the following congruence rules for ⇔ and implement associated B tactics that can be used e.g. to unfold a definition in a term, even under binders: g ⊢ p1 ⇔p2 → g ⊢ j :≡ p1 p ⇔ j :≡ p2 p g ⊢ p1 ⇔p2 → g ⊢ j :≡ p1 e = j :≡ p2 e Example 10. x =0, y ∈N ⊢ y ≤ x ⇔y =0, therefore we immediately derive (in one step)

x =0, y ∈N ⊢ ↑ ∀ (v•v ∈ ↑ {} (t : N•t ≤ y ∧y ≤ x)) ⇔ ↑ ∀ (v•v ∈ ↑ {} (t : N•t ≤ y ∧y =0))
Note that predicate substitution and expression substitution mechanically forbid the capture of variables in the substituted subterm, by lifting dangling De Bruijn indexes when crossing a binder. That is, in Ex. 10, if v or t appear free in the substituted subterm, they escape capture during substitution.

Predicate Grafting. Other congruence results can be derived for grafting of predicates, a modified substitution (not lifting the substituted subterm) allowing for the capture of variables:

k⊳p t : K → P → T → T := match t with | Ω | ωj ′ | χi ′ ⇒ t | πk ′ ⇒ if k ′ = k then p else t | ∀ p ′ ⇒ ∀ k⊳p p ′ | {e ′| p ′ } ⇒ { k⊳p e ′| k⊳p p ′ } | . . . ⇒ . .

. (straightforward extension)

The associated congruence results and proofs are technical, and not detailed in this paper. We just provide for illustration a simplified version of these results:

⊢ p1 ⇔p2 → g ⊢ j ⊳p1 p ⇔ j ⊳p2 p ⊢ p1 ⇔p2 → g ⊢ j ⊳p1 e = j ⊳p2 e
Example 11. g ⊢ k⊳ ¬ ¬p q ⇔ j⊳p q, that is the elimination of double negations in a subterm (even if dangling De Bruijn indexes of p are bound in q)

Remark. Results such as the ones in Exs. 10 or 11 are provable in B, on a caseby-case basis, with a first-order proof depending on the structure of the term in which substitution or grafting is done. It is therefore conceivable to develop a specific (and likely complex) B tactic automatically building for such goals a proof using the B inference rules. On the contrary, the proposed extensions provide a new approach through results derived from a higher-order proof; the associated B tactics are therefore simpler, and produce generic (and shorter) proofs by using not only the B inference rules but also induction on T.

Through an accurate deep embedding of the B logic in Coq, we identify shortfalls or confusions in [START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF] and propose amendments in order to be able to validate standard results -improving the confidence in the method and in the developments conducted with it. We describe a strategy to further benefit from this deep embedding by implementing verified B tools, extractible to be used independently of Coq. The approach is illustrated by the development of B tactics that constitute a complete and correct prover -usable to conduct proofs (provided further automation), or to check proofs produced by other tools. The objective, again, is to have better confidence in the developments conducted in B.

We also explain how, benefiting from the higher-order features of Coq, new results for B can be derived, and present an extension to derive congruence theorems related to equivalence, implemented in our prover.

All the results presented in this paper are mechanically checked; BiCoq currently represents about 550 definitions (i.e. types, properties, functions), 750 theorems and proofs in Coq -and about 6 man.months of development. It has now to be extended with the following definitions and results:

-Generation by the prover of B proof terms checkable by Coq.

-Use of a locally nameless De Bruijn representation with named free variables to derive unified congruence results (merging substitution and grafting). -Fixpoint constructs, with application to the definition of natural numbers in the B style; on the innovative side, we expect to derive inductive B tactics, not available in current B implementations. -GSL definition -either through a shallow embedding (an approach similar to the one presented in [START_REF] Bodeveix | A formalization of the B-method in Coq and PVS[END_REF], but in BiCoq) or through a deep embedding (with higher-order and first-order refinement definitions, and proof of equivalence).

We would like to emphasise the simplicity and the efficiency of the deep embedding approach, when having both validation and implementation objectives. In a relatively short amount of time, it was possible to describe the B logic, to check its standard results, and to implement a proved prover for this logic.

Example 4 .

 4 Inductive ev : N → Prop := ev0 : ev 0 | ev2 : ∀(n : N), ev n → ev (S(S n))

  The following (elementary) examples give the definition of the B tactics associated respectively to the inference rules [∈] and [∧i]: Example 8. T∈(s) := let (g p := s) in if p b ∈g then [] else [s]

An alternative approach to avoid well-formedness conditions is described in[START_REF] Bird | De Bruijn notation as a nested datatype[END_REF].

This second representation, while standard in B, appears to be an illegal binding over the expression x → y rather than over the variable x, y, but the same notations are used for both in[START_REF] Abrial | The B-Book -Assigning Programs to Meanings[END_REF] and such confusions are frequent.

The rules for the other constructors are trivial and can be obtained by straightforward extension, e.g. here i ˙ p and i ˙ q allow to derive i ˙ p ⇒q.

Substitution and instantiation may seem similar in usual notation, but their differences are emphasised when using De Bruijn notation.

B inference rulesBiCoq formalisationP ⊢ P None, derived from [∈] P appears in Γ Γ ⊢ P p ∈ g → g ⊢ p [∈] Γ ′ includes Γ Γ ⊢ P Γ ′ ⊢ P g1 ⊢ p → g1 ⊆ g2 → g2 ⊢ p [⊆] Γ ⊢ P Γ, P ⊢ Q Γ ⊢ Q None, derived from [¬n] [¬p] [⊆] [∈] Γ ⊢ P ⇒ Q Γ, P ⊢ Q Γ, P ⊢ Q Γ ⊢ P ⇒ Q g ⊢ p1 ⇒p2 → g, p1 ⊢ p2 g, p1 ⊢ p2 → g ⊢ p1 ⇒p2 Γ ⊢ P Γ ⊢ Q Γ ⊢ P ∧ Q g ⊢ p1 → g ⊢ p2 → g ⊢ p1 ∧p2 [∧ i ] Γ ⊢ P ∧ Q Γ ⊢ P Γ ⊢ P ∧ Q Γ ⊢ Q g ⊢ p1 ∧p2 → g ⊢ p1 g ⊢ p1 ∧p2 → g ⊢ p2 Γ, Q ⊢ P Γ, Q ⊢ ¬P Γ ⊢ ¬Q g, p2 ⊢ p1 → g, p2 ⊢ ¬p1 → g ⊢ ¬p2 [¬p] Γ, ¬Q ⊢ P Γ, ¬Q ⊢ ¬P Γ ⊢ Q g, ¬p2 ⊢ p1 → g, ¬p2 ⊢ ¬p1 → g ⊢ p2 [¬n] Γ ⊢ E = E g ⊢ e =e Γ ⊢ P V \Γ Γ ⊢ ∀ V • P i ˙ g → g ⊢ p → g ⊢ ↑ ∀ (i•p) [∀ i ] Γ ⊢ ∀ V • P Γ ⊢ [V := E]P g ⊢ ↑ ∀ (i•p) → g ⊢ i := e p

However, some new (propositional) sequents became provable, such as πk ⊢ πk .

Acknowledgements. We thank Pr. Hardin for reviewing earlier versions of this paper.