terminology: code labels are renamed to (code) marks

new syntax 'L: to introduce a mark
new syntax at t 'L in logical expressions
parent a9b29015
* marks an incompatible change
o [WhyML] programs labels with new syntax 'L: (instead of label L:)
o [Coq output] fixed bug 12934: type def with several type params
o [IDE] interactive detection of provers disabled because incompatible
with session. Detection must be done with why3config --detect-provers
o WhyML with mutable record fields and type models
o [WhyML] mutable record fields and type models
o why3replayer
* "parameter" keyword renamed to "val"
* new syntax for conjunction (/\) and disjunction (\/)
......@@ -18,7 +19,7 @@
o [IDE] displays explanations using labels of the form "expl:..."
o fixed Coq output for polymorphic inductive predicates
o [IDE] dropped dependence on Sqlite
* calls to prover can now be asynchronous
* calls to prover can now be asynchronous
Driver.prove_task now returns some intermediate value (of type
prover_call), which can be queried in two ways:
- blocking way with Call_provers.wait_on_call
......@@ -41,7 +42,7 @@ version 0.64, Feb 16, 2011
* syntax: /\ renamed into && and \/ into ||
o accept lowercase names for axioms, lemmas, goals, and cases in
inductive predicates
o labels in terms and formulas are not printed by default.
o labels in terms and formulas are not printed by default.
o transformation split-goal does not split under disjunction anymore
o fixed --enable-local
o why.conf is no more looked for in the current directory; use -C or
......
......@@ -913,7 +913,7 @@ ifeq (@enable_doc@,yes)
doc: doc/manual.pdf
# doc/manual.html
BNF = qualid constant operator term type formula theory why_file \
BNF = qualid label constant operator term type formula theory why_file \
typev expr module whyml_file
BNFTEX = $(addprefix doc/, $(addsuffix _bnf.tex, $(BNF)))
......
......@@ -8,12 +8,12 @@ val x : ref int
val f : unit -> { } unit writes x { !x = 1 - old !x }
let p () =
'Init:
begin
label Init:
let t = () in ();
(f ());
(f ());
assert { !x = at !x Init };
assert { !x = at !x 'Init };
()
end
......
......@@ -12,7 +12,6 @@
| "let" "rec" recfun ("with" recfun)* ; recursive functions
| "if" expr "then" expr ("else" expr)? ; conditional
| expr ";" expr ; sequence
| "label" uident ":" expr ; label
| "loop" loop-annot "end" ; infinite loop
| "while" expr "do" loop-annot expr "done" ; while loop
| "for" lident "=" expr to-downto expr ; for loop
......@@ -32,6 +31,8 @@
| expr "." lqualid "<-" expr ; field assignment
| "{|" expr "with" field-value+ "|}" ; field update
| expr ":" type ; cast
| label expr ; label
| "'" uident ":" expr ; code mark
| "(" expr ")" ; parentheses
\
expr-case ::= pattern "->" expr ;
......
\begin{syntax}
label ::= string ;
| "#" filename digit+ digit+ digit+ "#" ;
\
filename ::= string ;%
\end{syntax}
......@@ -15,6 +15,8 @@ Comments are enclosed by \texttt{(*} and \texttt{*)} and can be nested.
\paragraph{Strings.}
Strings are enclosed in double quotes (\verb!"!). Double quotes can be
inserted in strings using the backslash character (\verb!\!).
In the following, strings are referred to with the non-terminal
\nonterm{string}{}.
% TODO: escape sequences for strings
......@@ -53,6 +55,12 @@ characters they are built from:
\item level 1: all other operators (non-terminal \textit{infix-op-1}).
\end{itemize}
\paragraph{Labels.} Identifiers, terms, formulas, program expressions
can all be labeled, either with a string, or with a location tag.
\begin{center}\framebox{\input{./label_bnf.tex}}\end{center}
A location tag consists of a file name, a line number, and starting
and ending characters.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Why3 Language}
......
......@@ -20,6 +20,7 @@
| "{|" term "with" field-value+ "|}" ; field update
| term ":" type ; cast
| label term ; label
| "'" uident ; code mark
| "(" term ")" ; parentheses
\
term-case ::= pattern "->" term ;
......
This diff is collapsed.
......@@ -612,9 +612,9 @@ The precondition relates \texttt{board}, \texttt{pos}, and \texttt{n}
and requires \texttt{board} to be a solution up to \texttt{pos}:
\begin{verbatim}
{ length board = n /\ 0 <= pos <= n /\ solution board pos }
label Init:
'Init:
\end{verbatim}
We place a label \texttt{Init} immediately after the precondition to
We place a code mark \texttt{'Init} immediately after the precondition to
be able to refer to the value of \texttt{board} in the pre-state.
Whenever we reach the end of the chess board, we have found a solution
and we signal it using exception \texttt{Solution}:
......@@ -632,7 +632,7 @@ extend this prefix with a queen on row \texttt{pos} at a column below
\texttt{i}:
\begin{verbatim}
invariant {
eq_board board (at board Init) pos /\
eq_board board (at board 'Init) pos /\
forall b:array int. length b = n -> is_board b n ->
eq_board board b pos -> 0 <= b[pos] < i -> not (solution b n) }
\end{verbatim}
......@@ -688,11 +688,11 @@ automatically, including the verification of the lemmas themselves.
let rec bt_queens (board: array int) (n: int) (pos: int) variant { n - pos } =
{ length board = n /\ 0 <= pos <= n /\ solution board pos }
label Init:
'Init:
if pos = n then raise Solution;
for i = 0 to n - 1 do
invariant {
eq_board board (at board Init) pos /\
eq_board board (at board 'Init) pos /\
forall b:array int. length b = n -> is_board b n ->
eq_board board b pos -> 0 <= b[pos] < i -> not (solution b n) }
board[pos] <- i;
......
......@@ -41,17 +41,15 @@ module Algo64
let rec quicksort (a:array int) (m:int) (n:int) : unit variant { n-m } =
{ 0 <= m <= n < length a }
label Init:
'Init:
if m < n then begin
let i = ref 0 in
let j = ref 0 in
partition a m n i j;
label L1:
quicksort a m !j;
assert { permut_sub (at a L1) a m n };
label L2:
quicksort a !i n;
assert { permut_sub (at a L2) a m n }
'L1: quicksort a m !j;
assert { permut_sub (at a 'L1) a m n };
'L2: quicksort a !i n;
assert { permut_sub (at a 'L2) a m n }
end
{ permut_sub (old a) a m n /\ sorted_sub a m n }
......
......@@ -38,12 +38,12 @@ module Algo65
if m < n then begin
let i = ref 0 in
let j = ref 0 in
label L1:
'L1:
partition a m n i j;
assert { permut_sub (at a L1) a m n };
label L2:
assert { permut_sub (at a 'L1) a m n };
'L2:
if k <= !j then find a m !j k;
assert { permut_sub (at a L2) a m n };
assert { permut_sub (at a 'L2) a m n };
if !i <= k then find a !i n k
end
{ permut_sub (old a) a m n /\
......
......@@ -26,14 +26,14 @@ module Flag
let b = ref 0 in
let i = ref 0 in
let r = ref n in
label Init:
'Init:
while !i < !r do
invariant { 0 <= !b <= !i <= !r <= n /\
monochrome a 0 !b Blue /\
monochrome a !b !i White /\
monochrome a !r n Red /\
length a = n /\
permut_sub a (at a Init) 0 n }
permut_sub a (at a 'Init) 0 n }
variant { !r - !i }
match a[!i] with
| Blue ->
......
......@@ -8,14 +8,14 @@ module M
let gcd (x:int) (y:int) =
{ x >= 0 /\ y >= 0 }
let x = ref x in let y = ref y in
label Pre:
'Pre:
let a = ref 1 in let b = ref 0 in
let c = ref 0 in let d = ref 1 in
while (!y > 0) do
invariant { !x >= 0 /\ !y >= 0 /\
(forall d:int. gcd !x !y d -> gcd (at !x Pre) (at !y Pre) d) /\
!a * (at !x Pre) + !b * (at !y Pre) = !x /\
!c * (at !x Pre) + !d * (at !y Pre) = !y }
(forall d:int. gcd !x !y d -> gcd (at !x 'Pre) (at !y 'Pre) d) /\
!a * (at !x 'Pre) + !b * (at !y 'Pre) = !x /\
!c * (at !x 'Pre) + !d * (at !y 'Pre) = !y }
variant { !y }
let r = mod !x !y in let q = div !x !y in
x := !y; y := r;
......
......@@ -12,22 +12,22 @@ module InsertionSort
let insertion_sort (a: array int) =
{ }
label L:
'L:
for i = 1 to length a - 1 do
(* a[0..i[ is sorted; now insert a[i] *)
invariant { sorted_sub a 0 i /\ permut a (at a L) }
invariant { sorted_sub a 0 i /\ permut a (at a 'L) }
let v = a[i] in
let j = ref i in
while !j > 0 && a[!j - 1] > v do
invariant {
0 <= !j <= i /\ permut a[!j <- v] (at a L) /\
0 <= !j <= i /\ permut a[!j <- v] (at a 'L) /\
(forall k1 k2: int.
0 <= k1 <= k2 <= i -> k1 <> !j -> k2 <> !j -> a[k1] <= a[k2]) /\
(forall k: int. !j+1 <= k <= i -> v < a[k]) }
variant { !j }
label L1:
'L1:
a[!j] <- a[!j - 1];
assert { exchange a[!j-1 <- v] (at a L1)[!j <- v] (!j - 1) !j};
assert { exchange a[!j-1 <- v] (at a 'L1)[!j <- v] (!j - 1) !j};
j := !j - 1
done;
assert { forall k: int. 0 <= k < !j -> a[k] <= v };
......
......@@ -330,11 +330,11 @@ module M2
let old_next = !next in
let old_p = !p in
let q = ref null in
label Init:
'Init:
while !p <> null do
invariant { is_list !next !p /\ is_list !next !q
/\ sep_list_list !next !p !q /\
reverse (model (at !next Init) (old_p)) =
reverse (model (at !next 'Init) (old_p)) =
(reverse (model !next !p)) ++ (model !next !q)}
let tmp = !next[!p] in
let bak_next = !next in
......
......@@ -81,7 +81,7 @@ exception Success
let search_safety () =
{ length x = m }
label Init:
'Init:
let s = ref 0 in
for i = 0 to m - 1 do (* could be n instead of m *)
s := !s + x[i]
......@@ -116,7 +116,7 @@ let search_safety () =
let search () =
{ length x = m /\ is_integer x.elts }
label Init:
'Init:
let s = ref 0 in
for i = 0 to m - 1 do (* could be n instead of m *)
invariant { !s = sum x.elts 0 i }
......@@ -125,11 +125,11 @@ let search () =
assert { !s = sum x.elts 0 m };
for d = 0 to m - 1 do
invariant {
x = at x Init /\
x = at x 'Init /\
!s = sum x.elts d m
}
for c = x[d] + 1 to 9 do
invariant { x = at x Init }
invariant { x = at x 'Init }
let delta = y - !s - c + x[d] in
if 0 <= delta && delta <= 9 * d then begin
x[d] <- c;
......@@ -240,7 +240,7 @@ let search_smallest () =
(* x has at most n digits *)
forall k : int. n <= k < m -> x[k] = 0
}
label Init:
'Init:
let s = ref 0 in
for i = 0 to m - 1 do (* could be n instead of m *)
invariant { !s = sum x.elts 0 i }
......@@ -249,24 +249,24 @@ let search_smallest () =
assert { !s = sum x.elts 0 m };
for d = 0 to m - 1 do
invariant {
x = at x Init /\
x = at x 'Init /\
!s = sum x.elts d m /\
forall u : int.
interp (at x.elts Init) 0 m < u <= interp9 x.elts d m -> sum_digits u <> y
interp (at x.elts 'Init) 0 m < u <= interp9 x.elts d m -> sum_digits u <> y
}
for c = x[d] + 1 to 9 do
invariant {
x = at x Init /\
x = at x 'Init /\
forall c' : int. x[d] < c' < c ->
forall u : int.
interp (at x.elts Init) 0 m < u <= interp9 (M.set x.elts d c') d m ->
interp (at x.elts 'Init) 0 m < u <= interp9 (M.set x.elts d c') d m ->
sum_digits u <> y }
let delta = y - !s - c + x[d] in
if 0 <= delta && delta <= 9 * d then begin
assert { smallest_size delta <= d };
x[d] <- c;
assert { sum x.elts d m = y - delta };
assert { gt_digit x.elts (at x.elts Init) d };
assert { gt_digit x.elts (at x.elts 'Init) d };
let k = div delta 9 in
assert { k <= d };
for i = 0 to d - 1 do
......@@ -277,7 +277,7 @@ let search_smallest () =
(forall j : int. 0 <= j < i ->
(j < smallest_size delta -> x[j] = M.get (smallest delta) j) /\
(j >= smallest_size delta -> x[j] = 0)) /\
gt_digit x.elts (at x.elts Init) d }
gt_digit x.elts (at x.elts 'Init) d }
if i < k then x[i] <- 9
else if i = k then x[i] <- mod delta 9
else x[i] <- 0;
......
......@@ -26,11 +26,11 @@ module Quicksort
if l < r then begin
let v = t[l] in
let m = ref l in
label L: begin
'L: begin
for i = l + 1 to r do
invariant { (forall j:int. l < j <= !m -> t[j] < v) /\
(forall j:int. !m < j < i -> t[j] >= v) /\
permut_sub t (at t L) l (r+1) /\
permut_sub t (at t 'L) l (r+1) /\
t[l] = v /\ l <= !m < i }
if t[i] < v then begin m := !m + 1; swap t i !m end
done;
......
......@@ -19,11 +19,11 @@ module Quicksort
let selection_sort (a: array int) =
{ }
label L:
'L:
for i = 0 to length a - 1 do
(* a[0..i[ is sorted; now find minimum of a[i..n[ *)
invariant
{ sorted_sub a 0 i /\ permut a (at a L) /\
{ sorted_sub a 0 i /\ permut a (at a 'L) /\
forall k1 k2: int. 0 <= k1 < i <= k2 < length a -> a[k1] <= a[k2] }
let min = ref i in
for j = i + 1 to length a - 1 do
......@@ -31,9 +31,9 @@ module Quicksort
{ i <= !min < j && forall k: int. i <= k < j -> a[!min] <= a[k] }
if a[j] < a[!min] then min := j
done;
label L1:
'L1:
if !min <> i then swap a !min i;
assert { permut a (at a L1) }
assert { permut a (at a 'L1) }
done
{ sorted a /\ permut a (old a) }
......
......@@ -15,9 +15,9 @@ module HoareLogic
let slow_subtraction (x: ref int) (z: ref int) =
{ !x >= 0 }
label Init:
'Init:
while !x <> 0 do
invariant { 0 <= !x /\ !z - !x = at !z Init - at !x Init } variant { !x }
invariant { 0 <= !x /\ !z - !x = at !z 'Init - at !x 'Init } variant { !x }
z := !z - 1;
x := !x - 1
done
......@@ -34,9 +34,9 @@ module HoareLogic
let slow_addition (x: ref int) (z: ref int) =
{ !x >= 0 }
label Init:
'Init:
while !x <> 0 do
invariant { 0 <= !x /\ !z + !x = at !z Init + at !x Init } variant { !x }
invariant { 0 <= !x /\ !z + !x = at !z 'Init + at !x 'Init } variant { !x }
z := !z + 1;
x := !x - 1
done
......@@ -53,10 +53,10 @@ module HoareLogic
let parity (x: ref int) (y: ref int) =
{ !x >= 0 }
y := 0;
label Init:
'Init:
while !x <> 0 do
invariant { 0 <= !x /\ (!y=0 /\ even (at !x Init - !x) \/
!y=1 /\ even (at !x Init - !x + 1)) }
invariant { 0 <= !x /\ (!y=0 /\ even (at !x 'Init - !x) \/
!y=1 /\ even (at !x 'Init - !x + 1)) }
variant { !x }
y := 1 - !y;
x := !x - 1
......@@ -112,10 +112,10 @@ module MoreHoareLogic
let list_sum (l: ref (list int)) (y: ref int) =
{}
y := 0;
label Init:
'Init:
while !l <> Nil do
invariant { length !l <= length (at !l Init) /\
!y + sum !l = sum (at !l Init) }
invariant { length !l <= length (at !l 'Init) /\
!y + sum !l = sum (at !l 'Init) }
variant { length !l }
y := !y + head !l;
l := tail !l
......@@ -129,12 +129,12 @@ module MoreHoareLogic
let list_member (x : ref (list 'a)) (y: 'a) (z: ref int) =
{}
z := 0;
label Init:
'Init:
while !x <> Nil do
invariant { length !x <= length (at !x Init) /\
(mem y !x -> mem y (at !x Init)) /\
(!z=1 /\ mem y (at !x Init) \/
!z=0 /\ (mem y (at !x Init) -> mem y !x)) }
invariant { length !x <= length (at !x 'Init) /\
(mem y !x -> mem y (at !x 'Init)) /\
(!z=1 /\ mem y (at !x 'Init) \/
!z=0 /\ (mem y (at !x 'Init) -> mem y !x)) }
variant { length !x }
if y = head !x then z := 1;
x := tail !x
......
......@@ -82,11 +82,11 @@ module NQueens
let rec bt_queens (board: array int) (n: int) (pos: int) variant { n - pos } =
{ length board = n /\ 0 <= pos <= n /\ solution board pos }
label Init:
'Init:
if pos = n then raise Solution;
for i = 0 to n - 1 do
invariant {
eq_board board (at board Init) pos /\
eq_board board (at board 'Init) pos /\
forall b:array int. length b = n -> is_board b n ->
eq_board board b pos -> 0 <= b[pos] < i -> not (solution b n) }
board[pos] <- i;
......
......@@ -69,11 +69,11 @@ module Array
let fill (a: array 'a) (ofs: int) (len: int) (v: 'a) =
{ 0 <= ofs /\ ofs + len <= length a }
label Init:
'Init:
for k = 0 to len - 1 do
invariant {
(forall i:int.
(0 <= i < ofs \/ ofs + len <= i < length a) -> a[i] = (at a Init)[i])
(0 <= i < ofs \/ ofs + len <= i < length a) -> a[i] = (at a 'Init)[i])
/\
(forall i:int. ofs <= i < ofs + k -> a[i] = v)
}
......
......@@ -90,7 +90,6 @@
"fun", FUN;
(* "ghost", GHOST; *)
"invariant", INVARIANT;
"label", LABEL;
"loop", LOOP;
"model", MODEL;
"module", MODULE;
......@@ -206,8 +205,6 @@ rule token = parse
{ comment_start_loc := loc lexbuf; comment lexbuf; token lexbuf }
| "'"
{ QUOTE }
| "`"
{ BACKQUOTE }
| ","
{ COMMA }
| "("
......
......@@ -82,6 +82,8 @@ end
let prefix s = "prefix " ^ s
let mixfix s = "mixfix " ^ s
let quote id = { id with id = "'" ^ id.id }
let mk_id id loc = { id = id; id_lab = []; id_loc = loc }
let add_lab id l = { id with id_lab = l }
......@@ -160,9 +162,9 @@ end
pc_pre = p;
pc_post = q; }
let add_init_label e =
let add_init_mark e =
let init = { id = "Init"; id_lab = []; id_loc = e.expr_loc } in
{ e with expr_desc = Elabel (init, e) }
{ e with expr_desc = Emark (init, e) }
%}
......@@ -187,13 +189,13 @@ end
%token ABSTRACT ABSURD ANY ASSERT ASSUME BEGIN CHECK DO DONE DOWNTO
%token EXCEPTION FOR
%token FUN INVARIANT LABEL LOOP MODEL MODULE MUTABLE RAISE
%token FUN INVARIANT LOOP MODEL MODULE MUTABLE RAISE
%token RAISES READS REC TO TRY VAL VARIANT WHILE WRITES
/* symbols */
%token AND ARROW
%token BACKQUOTE BAR
%token BAR
%token COLON COMMA
%token DOT EQUAL FUNC LAMBDA LTGT
%token LEFTPAR LEFTPAR_STAR_RIGHTPAR LEFTREC LEFTSQ
......@@ -210,7 +212,7 @@ end
/* Precedences */
%nonassoc prec_label
%nonassoc prec_mark
%nonassoc prec_post
%nonassoc BAR
......@@ -550,7 +552,7 @@ list1_primitive_type_sep_comma:
;
type_var:
| QUOTE ident { $2 }
| QUOTE lident { $2 }
;
/* Logic expressions */
......@@ -634,6 +636,7 @@ lexpr_arg:
| FALSE { mk_pp PPfalse }
| OPPREF lexpr_arg { mk_l_prefix $1 $2 }
| lexpr_sub { $1 }
| QUOTE uident { mk_pp (PPvar (Qident (quote $2))) }
;
lexpr_dot:
......@@ -1097,8 +1100,8 @@ expr:
{ mk_expr (Ematch ($2, $5)) }
| MATCH expr COMMA list1_expr_sep_comma WITH bar_ program_match_cases END
{ mk_expr (Ematch (mk_expr (Etuple ($2::$4)), $7)) }
| LABEL uident COLON expr %prec prec_label
{ mk_expr (Elabel ($2, $4)) }
| QUOTE uident COLON expr %prec prec_mark
{ mk_expr (Emark (quote $2, $4)) }
| LOOP loop_annotation expr END
{ mk_expr (Eloop ($2, $3)) }
| WHILE expr DO loop_annotation expr DONE
......
......@@ -227,7 +227,7 @@ and expr_desc =
| Efor of ident * expr * for_direction * expr * lexpr option * expr
(* annotations *)
| Eassert of assertion_kind * lexpr
| Elabel of ident * expr
| Emark of ident * expr
| Ecast of expr * pty
| Eany of type_c
| Enamed of label * expr
......
......@@ -170,12 +170,12 @@ let ts_unit = create_tysymbol (id_fresh "unit") [] (Some ty_unit)
(* logic ignore 'a : () *)
let ts_label = create_tysymbol (id_fresh "label") [] None
let ty_label = ty_app ts_label []
let ts_mark = create_tysymbol (id_fresh "mark") [] None
let ty_mark = ty_app ts_mark []
let fs_at =
let ty = ty_var (create_tvsymbol (id_fresh "a")) in
create_lsymbol (id_fresh "at") [ty; ty_label] (Some ty)
create_lsymbol (id_fresh "at") [ty; ty_mark] (Some ty)
let fs_old =
let ty = ty_var (create_tvsymbol (id_fresh "a")) in
......@@ -185,7 +185,7 @@ let th_prelude =
let uc = create_theory (id_fresh "Prelude") in
let uc = use_export uc (tuple_theory 0) in
let uc = add_ty_decl uc [ts_unit, Tabstract] in
let uc = add_ty_decl uc [ts_label, Tabstract] in
let uc = add_ty_decl uc [ts_mark, Tabstract] in
let uc = add_logic_decl uc [fs_at, None] in
let uc = add_logic_decl uc [fs_old, None] in
close_theory uc
......
......@@ -86,8 +86,8 @@ val add_pdecl :
(** builtins *)
val ts_label : tysymbol
val ty_label : ty
val ts_mark : tysymbol
val ty_mark : ty
val ts_unit : tysymbol
val ty_unit : ty
......
......@@ -55,8 +55,8 @@ let rec print_expr fmt e = match e.expr_desc with
| Eany c ->
fprintf fmt "@[[any %a]@]" print_type_c c
| Elabel (_, _) ->
fprintf fmt "<todo: Elabel>"
| Emark (_, _) ->
fprintf fmt "<todo: Emark>"
| Eassert (_, f) ->
fprintf fmt "@[assert {%a}@]" print_term f
| Efor (_, _, _, _, _, e) ->
......
......@@ -99,7 +99,7 @@ and dexpr_desc =
| DEfor of ident * dexpr * for_direction * dexpr * Ptree.lexpr option * dexpr
| DEassert of assertion_kind * Ptree.lexpr
| DElabel of string * dexpr
| DEmark of string * dexpr
| DEany of dutype_c
| DEnamed of Ptree.label * dexpr
......@@ -153,7 +153,7 @@ and itype_c =
and ibinder = ivsymbol * itype_v
type label = Term.vsymbol
type mark = Term.vsymbol
type irec_variant = ivsymbol * Term.term * variant_rel
......@@ -199,7 +199,7 @@ and iexpr_desc =
Term.term option * iexpr
| IEassert of assertion_kind * Term.term
| IElabel of label * iexpr
| IEmark of mark * iexpr
| IEany of itype_c
| IEnamed of Ptree.label * iexpr
......@@ -256,7 +256,7 @@ and expr_desc =
Term.term option * expr
| Eassert of assertion_kind * Term.term
| Elabel of label * expr
| Emark of mark * expr
| Eany of type_c