source: Deliverables/D3.1/C-semantics/Errors.ma @ 485

Last change on this file since 485 was 485, checked in by campbell, 9 years ago

Fix treatment of pointers in initialisation data, a little like later versions
of CompCert?. Remove obsolete Init_pointer.

File size: 7.5 KB
Line 
1(* *********************************************************************)
2(*                                                                     *)
3(*              The Compcert verified compiler                         *)
4(*                                                                     *)
5(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
6(*                                                                     *)
7(*  Copyright Institut National de Recherche en Informatique et en     *)
8(*  Automatique.  All rights reserved.  This file is distributed       *)
9(*  under the terms of the GNU General Public License as published by  *)
10(*  the Free Software Foundation, either version 2 of the License, or  *)
11(*  (at your option) any later version.  This file is also distributed *)
12(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
13(*                                                                     *)
14(* *********************************************************************)
15
16include "datatypes/pairs.ma".
17include "Plogic/equality.ma".
18include "Plogic/connectives.ma".
19include "datatypes/sums.ma".
20
21(* * Error reporting and the error monad. *)
22(*
23(** * Representation of error messages. *)
24
25(** Compile-time errors produce an error message, represented in Coq
26  as a list of either substrings or positive numbers encoding
27  a source-level identifier (see module AST). *)
28
29Inductive errcode: Type :=
30  | MSG: string -> errcode
31  | CTX: positive -> errcode.
32
33Definition errmsg: Type := list errcode.
34
35Definition msg (s: string) : errmsg := MSG s :: nil.
36*)
37(* * * The error monad *)
38
39(* * Compilation functions that can fail have return type [res A].
40  The return value is either [OK res] to indicate success,
41  or [Error msg] to indicate failure. *)
42
43ninductive res (A: Type) : Type ≝
44| OK: A → res A
45| Error: (* FIXME errmsg →*) res A.
46
47(*Implicit Arguments Error [A].*)
48
49(* * To automate the propagation of errors, we use a monadic style
50  with the following [bind] operation. *)
51
52ndefinition bind ≝ λA,B:Type. λf: res A. λg: A → res B.
53  match f with
54  [ OK x ⇒ g x
55  | Error (*msg*) ⇒ Error ? (*msg*)
56  ].
57
58ndefinition bind2 ≝ λA,B,C: Type. λf: res (A × B). λg: A → B → res C.
59  match f with
60  [ OK v ⇒ match v with [ mk_pair x y ⇒ g x y ]
61  | Error (*msg*) => Error ? (*msg*)
62  ].
63
64(* Not sure what level to use *)
65notation > "vbox('do' ident v ← e; break e')" with precedence 40 for @{'bind ${e} (λ${ident v}.${e'})}.
66notation > "vbox('do' ident v : ty ← e; break e')" with precedence 40 for @{'bind ${e} (λ${ident v} : ${ty}.${e'})}.
67notation < "vbox('do' \nbsp ident v ← e; break e')" with precedence 40 for @{'bind ${e} (λ${ident v}.${e'})}.
68notation < "vbox('do' \nbsp ident v : ty ← e; break e')" with precedence 40 for @{'bind ${e} (λ${ident v} : ${ty}.${e'})}.
69interpretation "error monad bind" 'bind e f = (bind ?? e f).
70notation > "vbox('do' 〈ident v1, ident v2〉 ← e; break e')" with precedence 40 for @{'bind2 ${e} (λ${ident v1}.λ${ident v2}.${e'})}.
71notation > "vbox('do' 〈ident v1 : ty1, ident v2 : ty2〉 ← e; break e')" with precedence 40 for @{'bind2 ${e} (λ${ident v1} : ${ty1}.λ${ident v2} : ${ty2}.${e'})}.
72notation < "vbox('do' \nbsp 〈ident v1, ident v2〉 ← e; break e')" with precedence 40 for @{'bind2 ${e} (λ${ident v1}.λ${ident v2}.${e'})}.
73notation < "vbox('do' \nbsp 〈ident v1 : ty1, ident v2 : ty2〉 ← e; break e')" with precedence 40 for @{'bind2 ${e} (λ${ident v1} : ${ty1}.λ${ident v2} : ${ty2}.${e'})}.
74interpretation "error monad pair bind" 'bind2 e f = (bind2 ??? e f).
75(*interpretation "error monad ret" 'ret e = (ret ? e).
76notation "'ret' e" non associative with precedence 45 for @{'ret ${e}}.*)
77
78(*
79(** The [do] notation, inspired by Haskell's, keeps the code readable. *)
80
81Notation "'do' X <- A ; B" := (bind A (fun X => B))
82 (at level 200, X ident, A at level 100, B at level 200)
83 : error_monad_scope.
84
85Notation "'do' ( X , Y ) <- A ; B" := (bind2 A (fun X Y => B))
86 (at level 200, X ident, Y ident, A at level 100, B at level 200)
87 : error_monad_scope.
88*)
89nremark bind_inversion:
90  ∀A,B: Type. ∀f: res A. ∀g: A → res B. ∀y: B.
91  bind ?? f g = OK ? y →
92  ∃x. f = OK ? x ∧ g x = OK ? y.
93#A B f g y; ncases f;
94##[ #a e; @a; nwhd in e:(??%?); /2/;
95##| #H; nwhd in H:(??%?); ndestruct (H);
96##] nqed.
97
98nremark bind2_inversion:
99  ∀A,B,C: Type. ∀f: res (A×B). ∀g: A → B → res C. ∀z: C.
100  bind2 ??? f g = OK ? z →
101  ∃x. ∃y. f = OK ? 〈x, y〉 ∧ g x y = OK ? z.
102#A B C f g z; ncases f;
103##[ #ab; ncases ab; #a b e; @a; @b; nwhd in e:(??%?); /2/;
104##| #H; nwhd in H:(??%?); ndestruct
105##] nqed.
106
107(*
108Open Local Scope error_monad_scope.
109
110(** This is the familiar monadic map iterator. *)
111
112Fixpoint mmap (A B: Type) (f: A -> res B) (l: list A) {struct l} : res (list B) :=
113  match l with
114  | nil => OK nil
115  | hd :: tl => do hd' <- f hd; do tl' <- mmap f tl; OK (hd' :: tl')
116  end.
117
118Remark mmap_inversion:
119  forall (A B: Type) (f: A -> res B) (l: list A) (l': list B),
120  mmap f l = OK l' ->
121  list_forall2 (fun x y => f x = OK y) l l'.
122Proof.
123  induction l; simpl; intros.
124  inversion_clear H. constructor.
125  destruct (bind_inversion _ _ H) as [hd' [P Q]].
126  destruct (bind_inversion _ _ Q) as [tl' [R S]].
127  inversion_clear S.
128  constructor. auto. auto.
129Qed.
130
131(** * Reasoning over monadic computations *)
132
133(** The [monadInv H] tactic below simplifies hypotheses of the form
134<<
135        H: (do x <- a; b) = OK res
136>>
137    By definition of the bind operation, both computations [a] and
138    [b] must succeed for their composition to succeed.  The tactic
139    therefore generates the following hypotheses:
140
141         x: ...
142        H1: a = OK x
143        H2: b x = OK res
144*)
145
146Ltac monadInv1 H :=
147  match type of H with
148  | (OK _ = OK _) =>
149      inversion H; clear H; try subst
150  | (Error _ = OK _) =>
151      discriminate
152  | (bind ?F ?G = OK ?X) =>
153      let x := fresh "x" in (
154      let EQ1 := fresh "EQ" in (
155      let EQ2 := fresh "EQ" in (
156      destruct (bind_inversion F G H) as [x [EQ1 EQ2]];
157      clear H;
158      try (monadInv1 EQ2))))
159  | (bind2 ?F ?G = OK ?X) =>
160      let x1 := fresh "x" in (
161      let x2 := fresh "x" in (
162      let EQ1 := fresh "EQ" in (
163      let EQ2 := fresh "EQ" in (
164      destruct (bind2_inversion F G H) as [x1 [x2 [EQ1 EQ2]]];
165      clear H;
166      try (monadInv1 EQ2)))))
167  | (mmap ?F ?L = OK ?M) =>
168      generalize (mmap_inversion F L H); intro
169  end.
170
171Ltac monadInv H :=
172  match type of H with
173  | (OK _ = OK _) => monadInv1 H
174  | (Error _ = OK _) => monadInv1 H
175  | (bind ?F ?G = OK ?X) => monadInv1 H
176  | (bind2 ?F ?G = OK ?X) => monadInv1 H
177  | (?F _ _ _ _ _ _ _ _ = OK _) =>
178      ((progress simpl in H) || unfold F in H); monadInv1 H
179  | (?F _ _ _ _ _ _ _ = OK _) =>
180      ((progress simpl in H) || unfold F in H); monadInv1 H
181  | (?F _ _ _ _ _ _ = OK _) =>
182      ((progress simpl in H) || unfold F in H); monadInv1 H
183  | (?F _ _ _ _ _ = OK _) =>
184      ((progress simpl in H) || unfold F in H); monadInv1 H
185  | (?F _ _ _ _ = OK _) =>
186      ((progress simpl in H) || unfold F in H); monadInv1 H
187  | (?F _ _ _ = OK _) =>
188      ((progress simpl in H) || unfold F in H); monadInv1 H
189  | (?F _ _ = OK _) =>
190      ((progress simpl in H) || unfold F in H); monadInv1 H
191  | (?F _ = OK _) =>
192      ((progress simpl in H) || unfold F in H); monadInv1 H
193  end.
194*)
195
196
197ndefinition opt_to_res ≝ λA.λv:option A. match v with [ None ⇒ Error A | Some v ⇒ OK A v ].
198nlemma opt_OK: ∀A,P,e.
199  (∀v. e = Some ? v → P v) →
200  match opt_to_res A e with [ Error ⇒ True | OK v ⇒ P v ].
201#A P e; nelim e; /2/;
202nqed.
Note: See TracBrowser for help on using the repository browser.