Theory C_paper
chapter ‹Examples from the F-IDE Paper›
theory C_paper
imports "../main/C_Main"
begin
text ‹ This theory contains the examples presented in F-IDE 2019 paper~\cite{Tuong-IsabelleC:2019}. ›
section ‹Setup›
ML‹
val _ = Theory.setup
(C_Inner_Syntax.command C_Inner_Isar_Cmd.setup' C_Parse.ML_source ("≃setup", ⌂, ⌂))
val C' = C_Module.C' o SOME
fun C opt = case opt of NONE => C' (C_Module.env (Context.the_generic_context ()))
| SOME env => C' env
fun C_def dir name _ _ =
Context.map_theory
(C_Inner_Syntax.command'
(C_Inner_Syntax.drop1
(C_Scan.Right ( (fn src => fn context =>
C' (C_Stack.Data_Lang.get' context |> #2) src context)
, dir)))
C_Parse.C_source
name)
local
in
val _ = Theory.setup
(ML_Antiquotation.declaration
@{binding "C_def"}
(Scan.lift (Parse.sym_ident -- Parse.position Parse.name))
(fn _ => fn (top_down, (name, pos)) =>
tap (fn ctxt => Context_Position.reports ctxt [(pos, Markup.keyword1)]) #>
C_Context.fun_decl
"cmd" "x" ( "C_def "
^ (case top_down of "⇑" => "C_Inner_Syntax.bottom_up"
| "⇓" => "C_Env.Top_down"
| _ => error "Illegal symbol")
^ " (\"" ^ name ^ "\", " ^ ML_Syntax.print_position pos ^ ")")))
end
›
text ‹ The next command is predefined here, so that the example below can later refer to the
constant. ›
definition [simplified]: "UINT_MAX ≡ (2 :: nat) ^ 32 - 1"
section ‹Defining Annotation Commands›
ML ‹
local
datatype antiq_hol = Invariant of string
val scan_colon = C_Parse.$$$ ":" >> SOME
fun command cmd scan0 scan f =
C_Annotation.command' cmd "" (K (scan0 -- (scan >> f)
>> K C_Env.Never))
in
val _ = Theory.setup (
command ("INVARIANT", ⌂) scan_colon C_Parse.term Invariant
#> command ("INV", ⌂) scan_colon C_Parse.term Invariant)
end
›
text‹Demonstrating the Effect of Annotation Command Context Navigation ›
C ‹
int sum1(int a)
{
while (a < 10)
/*@ @ INV: ‹…›
@ highlight */
{ a = a + 1; }
return a;
}›
C ‹
int sum2(int a)
/*@ ++@ INV: ‹…›
++@ highlight */
{
while (a < 10)
{ a = a + 1; }
return a;
}›
C ‹
int a (int b) { return &a + b + c; }
/*@ ≃setup ‹fn stack_top => fn env =>
C (SOME env) ‹int c = &a + b + c;››
≃setup ‹fn stack_top => fn env =>
C NONE ‹int c = &a + b + c;››
declare [[C⇩e⇩n⇩v⇩0 = last]]
C ‹int c = &a + b + c;›
*/›
section ‹Proofs inside C-Annotations›
C ‹
#define SQRT_UINT_MAX 65536
/*@ lemma uint_max_factor [simp]:
"UINT_MAX = SQRT_UINT_MAX * SQRT_UINT_MAX - 1"
by (clarsimp simp: UINT_MAX_def SQRT_UINT_MAX_def)
*/›
term SQRT_UINT_MAX
section ‹Scheduling the Effects on the Logical Context›
C ‹int _;
/*@ @ C ‹//@ C1 ‹int _; //@ @ ≃setup⇓ ‹@{C_def ⇑ C2}› \
@ C1 ‹› \
@ C1⇓ ‹//* C2 ‹int _;›› ››
@ C ‹//* C2 ‹int _;› ›
≃setup ‹@{C_def ⇑ (* bottom-up *) C1 }›
≃setup ‹@{C_def ⇓ (* top-down *) "C1⇓"}›
*/›
section ‹As Summary: A Spaghetti Language --- Bon Appétit!›
text‹... with the Bonus of a local C-inside-ML-inside-C-inside-Isar ...›
ML‹
fun highlight (_, (_, pos1, pos2)) =
tap (fn _ => Position.reports_text [((Position.range (pos1, pos2)
|> Position.range_position, Markup.intensify), "")])
›
C
‹int f (int a)
//@ ++& ≃setup ‹fn stack_top => fn env => highlight stack_top›
{ /*@ @ ≃setup ‹fn stack_top => fn env =>
C (SOME env)
‹int b = a + b; //@ C1' ‹int c; //@ @ ≃setup⇓ ‹@{C_def ⇑ C2'}› \
@ C1' ‹› \
@ C1'⇓ ‹//* C2' ‹int d;›› ›
int b = a + b + c + d;››
@ ≃setup ‹fn stack_top => fn env => C NONE ‹#define int int
int b = a + b; //* C2' ‹int c = b;›››
≃setup ‹@{C_def ⇑ (* bottom-up *) C1' }›
≃setup ‹@{C_def ⇓ (* top-down *) "C1'⇓"}›
*/
return a + b + c + d; }›
text ‹ Note that in the current design-implementation of Isabelle/C, C directives have a
propagation side-effect to any occurring subsequent C annotations, even if C directives are supposed
to be all evaluated before any C code. (Making such effect inexistent would be equally easier to
implement though, this is what was the default behavior of directives in previous versions of
Isabelle/C.)›
end