attribute "code" declares concrete and abstract code equations uniformly; added explicit "code equation" instead
--- a/NEWS Sat Jul 13 17:53:57 2013 +0200
+++ b/NEWS Sat Jul 13 17:53:58 2013 +0200
@@ -84,6 +84,9 @@
*** HOL ***
+* Attibute 'code': 'code' now declares concrete and abstract code equations uniformly.
+Use explicit 'code equation' and 'code abstract' to distinguish both when desired.
+
* Code generator:
* 'code_printing' unifies 'code_const' / 'code_type' / 'code_class' / 'code_instance'.
* 'code_identifier' declares name hints for arbitrary identifiers in generated code,
--- a/src/Doc/Codegen/Refinement.thy Sat Jul 13 17:53:57 2013 +0200
+++ b/src/Doc/Codegen/Refinement.thy Sat Jul 13 17:53:58 2013 +0200
@@ -236,7 +236,7 @@
\noindent This we have to prove indirectly as follows:
*}
-lemma %quote [code abstract]:
+lemma %quote [code]:
"list_of_dlist Dlist.empty = []"
by (fact list_of_dlist_empty)
@@ -247,11 +247,11 @@
similar:
*}
-lemma %quote [code abstract]:
+lemma %quote [code]:
"list_of_dlist (Dlist.insert x dxs) = List.insert x (list_of_dlist dxs)"
by (fact list_of_dlist_insert)
-lemma %quote [code abstract]:
+lemma %quote [code]:
"list_of_dlist (Dlist.remove x dxs) = remove1 x (list_of_dlist dxs)"
by (fact list_of_dlist_remove)
@@ -261,7 +261,7 @@
text %quotetypewriter {*
@{code_stmts Dlist.empty Dlist.insert Dlist.remove list_of_dlist (Haskell)}
-*} (*(types) dlist (consts) dempty dinsert dremove list_of List.member insert remove *)
+*}
text {*
Typical data structures implemented by representations involving
--- a/src/Doc/IsarRef/HOL_Specific.thy Sat Jul 13 17:53:57 2013 +0200
+++ b/src/Doc/IsarRef/HOL_Specific.thy Sat Jul 13 17:53:58 2013 +0200
@@ -2242,7 +2242,7 @@
target: 'SML' | 'OCaml' | 'Haskell' | 'Scala' | 'Eval'
;
- @@{attribute (HOL) code} ( 'del' | 'abstype' | 'abstract' )?
+ @@{attribute (HOL) code} ( 'del' | 'equation' | 'abstype' | 'abstract' )?
;
@@{command (HOL) code_abort} ( const + )
@@ -2397,12 +2397,18 @@
``@{verbatim "deriving (Read, Show)"}'' clause to each appropriate
datatype declaration.
- \item @{attribute (HOL) code} explicitly selects (or with option
- ``@{text "del"}'' deselects) a code equation for code generation.
- Usually packages introducing code equations provide a reasonable
- default setup for selection. Variants @{text "code abstype"} and
+ \item @{attribute (HOL) code} declare code equations for code
+ generation. Variant @{text "code equation"} declares a conventional
+ equation as code equation. Variants @{text "code abstype"} and
@{text "code abstract"} declare abstract datatype certificates or
code equations on abstract datatype representations respectively.
+ Vanilla @{text "code"} falls back to @{text "code equation"}
+ or @{text "code abstype"} depending on the syntactic shape
+ of the underlying equation. Variant @{text "code del"}
+ deselects a code equation for code generation.
+
+ Usually packages introducing code equations provide a reasonable
+ default setup for selection.
\item @{command (HOL) "code_abort"} declares constants which are not
required to have a definition by means of code equations; if needed
--- a/src/Pure/Isar/code.ML Sat Jul 13 17:53:57 2013 +0200
+++ b/src/Pure/Isar/code.ML Sat Jul 13 17:53:58 2013 +0200
@@ -22,7 +22,6 @@
(*code equations and certificates*)
val mk_eqn: theory -> thm * bool -> thm * bool
- val mk_eqn_warning: theory -> thm -> (thm * bool) option
val mk_eqn_liberal: theory -> thm -> (thm * bool) option
val assert_eqn: theory -> thm * bool -> thm * bool
val const_typ_eqn: theory -> thm -> string * typ
@@ -535,7 +534,9 @@
val _ = case some_tyco of SOME tyco' => if tyco = tyco' then ()
else bad_thm ("Abstract type mismatch:" ^ quote tyco ^ " vs. " ^ quote tyco')
| NONE => ();
- val (vs', (_, (rep', _))) = get_abstype_spec thy tyco;
+ val (vs', (_, (rep', _))) = case try (get_abstype_spec thy) tyco
+ of SOME data => data
+ | NONE => bad_thm ("Not an abstract type: " ^ tyco);
val _ = if rep_const = rep' then ()
else bad_thm ("Projection mismatch: " ^ quote rep_const ^ " vs. " ^ quote rep');
val _ = check_eqn thy { allow_nonlinear = false,
@@ -551,12 +552,19 @@
fun mk_eqn thy = error_thm (gen_assert_eqn thy false) thy o
apfst (meta_rewrite thy);
-fun mk_eqn_warning thy = Option.map (fn (thm, _) => (thm, is_linear thm))
- o warning_thm (gen_assert_eqn thy false) thy o rpair false o meta_rewrite thy;
-
fun mk_eqn_liberal thy = Option.map (fn (thm, _) => (thm, is_linear thm))
o try_thm (gen_assert_eqn thy false) o rpair false o meta_rewrite thy;
+fun mk_eqn_maybe_abs thy raw_thm =
+ let
+ val thm = meta_rewrite thy raw_thm;
+ val some_abs_thm = try_thm (assert_abs_eqn thy NONE) thm;
+ in case some_abs_thm
+ of SOME (thm, tyco) => SOME ((thm, true), SOME tyco)
+ | NONE => (Option.map (fn (thm, _) => ((thm, is_linear thm), NONE))
+ o warning_thm (gen_assert_eqn thy false) thy) (thm, false)
+ end;
+
fun mk_abs_eqn thy = error_abs_thm (assert_abs_eqn thy NONE) thy o meta_rewrite thy;
val head_eqn = dest_Const o fst o strip_comb o fst o Logic.dest_equals o Thm.plain_prop_of;
@@ -1060,14 +1068,15 @@
| add_eqn' false _ = Eqns [(thm, proper)];
in change_fun_spec false c (add_eqn' default) thy end;
+fun gen_add_abs_eqn raw_thm thy =
+ let
+ val (abs_thm, tyco) = apfst Thm.close_derivation raw_thm;
+ val c = const_abs_eqn thy abs_thm;
+ in change_fun_spec false c (K (Abstr (abs_thm, tyco))) thy end;
+
fun add_eqn thm thy =
gen_add_eqn false (mk_eqn thy (thm, true)) thy;
-fun add_warning_eqn thm thy =
- case mk_eqn_warning thy thm
- of SOME eqn => gen_add_eqn false eqn thy
- | NONE => thy;
-
fun add_nbe_eqn thm thy =
gen_add_eqn false (mk_eqn thy (thm, false)) thy;
@@ -1087,11 +1096,13 @@
(fn thm => Context.mapping (add_nbe_default_eqn thm) I);
val add_nbe_default_eqn_attrib = Attrib.internal (K add_nbe_default_eqn_attribute);
-fun add_abs_eqn raw_thm thy =
- let
- val (abs_thm, tyco) = (apfst Thm.close_derivation o mk_abs_eqn thy) raw_thm;
- val c = const_abs_eqn thy abs_thm;
- in change_fun_spec false c (K (Abstr (abs_thm, tyco))) thy end;
+fun add_abs_eqn raw_thm thy = gen_add_abs_eqn (mk_abs_eqn thy raw_thm) thy;
+
+fun add_eqn_maybe_abs thm thy =
+ case mk_eqn_maybe_abs thy thm
+ of SOME (eqn, NONE) => gen_add_eqn false eqn thy
+ | SOME ((thm, _), SOME tyco) => gen_add_abs_eqn (thm, tyco) thy
+ | NONE => thy;
fun del_eqn thm thy = case mk_eqn_liberal thy thm
of SOME (thm, _) => let
@@ -1226,10 +1237,11 @@
fun mk_attribute f = Thm.declaration_attribute (fn thm => Context.mapping (f thm) I);
val code_attribute_parser =
Args.del |-- Scan.succeed (mk_attribute del_eqn)
+ || Args.$$$ "equation" |-- Scan.succeed (mk_attribute add_eqn)
|| Args.$$$ "nbe" |-- Scan.succeed (mk_attribute add_nbe_eqn)
|| Args.$$$ "abstype" |-- Scan.succeed (mk_attribute add_abstype)
|| Args.$$$ "abstract" |-- Scan.succeed (mk_attribute add_abs_eqn)
- || Scan.succeed (mk_attribute add_warning_eqn);
+ || Scan.succeed (mk_attribute add_eqn_maybe_abs);
in
Datatype_Interpretation.init
#> Attrib.setup (Binding.name "code") (Scan.lift code_attribute_parser)