This commit is contained in:
Burkhart Wolff 2023-05-12 16:19:29 +02:00
commit 543c647bcc
4 changed files with 120 additions and 73 deletions

View File

@ -131,7 +131,7 @@ text\<open>Now assume the following ontology:\<close>
doc_class title =
short_title :: "string option" <= "None"
doc_class Author =
doc_class author =
email :: "string" <= "''''"
datatype classification = SIL0 | SIL1 | SIL2 | SIL3 | SIL4
@ -141,18 +141,18 @@ doc_class abstract =
safety_level :: "classification" <= "SIL3"
doc_class text_section =
authored_by :: "Author set" <= "{}"
authored_by :: "author set" <= "{}"
level :: "int option" <= "None"
type_synonym notion = string
doc_class Introduction = text_section +
authored_by :: "Author set" <= "UNIV"
doc_class introduction = text_section +
authored_by :: "author set" <= "UNIV"
uses :: "notion set"
invariant author_finite :: "finite (authored_by \<sigma>)"
and force_level :: "(level \<sigma>) \<noteq> None \<and> the (level \<sigma>) > 1"
doc_class claim = Introduction +
doc_class claim = introduction +
based_on :: "notion list"
doc_class technical = text_section +
@ -181,7 +181,10 @@ text\<open>Next we define some instances (docitems): \<close>
declare[[invariants_checking_with_tactics = true]]
text*[church::Author, email="\<open>church@lambda.org\<close>"]\<open>\<close>
text*[church::author, email="\<open>church@lambda.org\<close>"]\<open>\<close>
text\<open>We can also reference instances of classes defined in parent theories:\<close>
text*[church'::scholarly_paper.author, email="\<open>church'@lambda.org\<close>"]\<open>\<close>
text*[resultProof::result, evidence = "proof", property="[@{thm \<open>HOL.refl\<close>}]"]\<open>\<close>
text*[resultArgument::result, evidence = "argument"]\<open>\<close>
@ -193,29 +196,41 @@ text\<open>The invariants \<^theory_text>\<open>author_finite\<close> and \<^the
declare[[invariants_checking_with_tactics = true]]
text*[curry::Author, email="\<open>curry@lambda.org\<close>"]\<open>\<close>
text*[introduction2::Introduction, authored_by = "{@{Author \<open>church\<close>}}", level = "Some 2"]\<open>\<close>
text*[curry::author, email="\<open>curry@lambda.org\<close>"]\<open>\<close>
text*[introduction2::introduction, authored_by = "{@{author \<open>church\<close>}}", level = "Some 2"]\<open>\<close>
(* When not commented, should violated the invariant:
update_instance*[introduction2::Introduction
, authored_by := "{@{Author \<open>church\<close>}}"
, level := "Some 1"]
*)
text\<open>Use of the instance @{docitem_name "church'"}
to instantiate a \<^doc_class>\<open>scholarly_paper.introduction\<close> class:\<close>
text*[introduction2'::scholarly_paper.introduction,
main_author = "Some @{scholarly-paper.author \<open>church'\<close>}", level = "Some 2"]\<open>\<close>
value*\<open>@{scholarly-paper.author \<open>church'\<close>}\<close>
value*\<open>@{author \<open>church\<close>}\<close>
value*\<open>@{Concept-High-Level-Invariants.author \<open>church\<close>}\<close>
text*[introduction3::Introduction, authored_by = "{@{Author \<open>church\<close>}}", level = "Some 2"]\<open>\<close>
text*[introduction4::Introduction, authored_by = "{@{Author \<open>curry\<close>}}", level = "Some 4"]\<open>\<close>
value*\<open>@{scholarly-paper.author-instances}\<close>
value*\<open>@{author-instances}\<close>
value*\<open>@{Concept-High-Level-Invariants.author-instances}\<close>
text*[introduction3::introduction, authored_by = "{@{author \<open>church\<close>}}", level = "Some 2"]\<open>\<close>
text*[introduction4::introduction, authored_by = "{@{author \<open>curry\<close>}}", level = "Some 4"]\<open>\<close>
text*[resultProof2::result, evidence = "proof", property="[@{thm \<open>HOL.sym\<close>}]"]\<open>\<close>
text\<open>Then we can evaluate expressions with instances:\<close>
term*\<open>authored_by @{Introduction \<open>introduction2\<close>} = authored_by @{Introduction \<open>introduction3\<close>}\<close>
value*\<open>authored_by @{Introduction \<open>introduction2\<close>} = authored_by @{Introduction \<open>introduction3\<close>}\<close>
value*\<open>authored_by @{Introduction \<open>introduction2\<close>} = authored_by @{Introduction \<open>introduction4\<close>}\<close>
term*\<open>authored_by @{introduction \<open>introduction2\<close>} = authored_by @{introduction \<open>introduction3\<close>}\<close>
value*\<open>authored_by @{introduction \<open>introduction2\<close>} = authored_by @{introduction \<open>introduction3\<close>}\<close>
value*\<open>authored_by @{introduction \<open>introduction2\<close>} = authored_by @{introduction \<open>introduction4\<close>}\<close>
value*\<open>@{Introduction \<open>introduction2\<close>}\<close>
value*\<open>@{introduction \<open>introduction2\<close>}\<close>
value*\<open>{@{Author \<open>curry\<close>}} = {@{Author \<open>church\<close>}}\<close>
value*\<open>{@{author \<open>curry\<close>}} = {@{author \<open>church\<close>}}\<close>
term*\<open>property @{result \<open>resultProof\<close>} = property @{result \<open>resultProof2\<close>}\<close>
value*\<open>property @{result \<open>resultProof\<close>} = property @{result \<open>resultProof2\<close>}\<close>

View File

@ -22,9 +22,12 @@ begin
section\<open>Test Purpose.\<close>
text\<open> Creation of document parts that are controlled by (nested, locally defined) monitors. \<close>
doc_class test_monitor_B =
tmB :: int
doc_class monitor_M =
tmM :: int
rejects "test_monitor_B"
rejects "Concept_MonitorTest1.test_monitor_B"
accepts "test_monitor_E ~~ test_monitor_C"
doc_class test_monitor_head =

View File

@ -200,10 +200,10 @@ Consequently, it has the same limitations as \<^emph>\<open>value*\<close>.
text\<open>Using the ontology defined in \<^theory>\<open>Isabelle_DOF-Unit-Tests.Concept_High_Level_Invariants\<close>
we can check logical statements:\<close>
term*\<open>authored_by @{Introduction \<open>introduction2\<close>} = authored_by @{Introduction \<open>introduction3\<close>}\<close>
assert*\<open>authored_by @{Introduction \<open>introduction2\<close>} = authored_by @{Introduction \<open>introduction3\<close>}\<close>
assert*\<open>\<not>(authored_by @{Introduction \<open>introduction2\<close>}
= authored_by @{Introduction \<open>introduction4\<close>})\<close>
term*\<open>authored_by @{introduction \<open>introduction2\<close>} = authored_by @{introduction \<open>introduction3\<close>}\<close>
assert*\<open>authored_by @{introduction \<open>introduction2\<close>} = authored_by @{introduction \<open>introduction3\<close>}\<close>
assert*\<open>\<not>(authored_by @{introduction \<open>introduction2\<close>}
= authored_by @{introduction \<open>introduction4\<close>})\<close>
text\<open>Assertions must be boolean expressions, so the following assertion triggers an error:\<close>
(* Error:

View File

@ -806,24 +806,24 @@ fun binding_from_onto_class_pos name thy =
fun binding_from_instance_pos name thy =
binding_from_pos get_instances get_instance_name_global name thy
fun check_invs get_ml_invs cid_long oid is_monitor thy =
fun check_invs get_ml_invs invariant_class_of invariant_check_of cid_long oid is_monitor thy =
thy |> Context.Theory
|> (fn ctxt =>
let val invs = get_ml_invs (Proof_Context.init_global thy)
|> Name_Space.dest_table
val checks = invs |> filter (fn (_, inv) => let val ML_Invariant class = inv
in class |> #class |> equal cid_long
end)
|> map (fn (_, inv) => let val ML_Invariant check = inv
in check |> #check end)
val checks = invs |> filter (fn (name, _) =>
equal (invariant_class_of name thy) cid_long)
|> map (fn (name, _) => invariant_check_of name thy)
|> map (fn check => check oid is_monitor ctxt)
in (List.all I checks) end)
in (forall I checks) end)
val check_ml_invs = check_invs get_ml_invariants
val check_ml_invs = check_invs get_ml_invariants ml_invariant_class_of ml_invariant_check_of
val check_opening_ml_invs = check_invs get_opening_ml_invariants
val check_opening_ml_invs =
check_invs get_opening_ml_invariants opening_ml_invariant_class_of opening_ml_invariant_check_of
val check_closing_ml_invs = check_invs get_closing_ml_invariants
val check_closing_ml_invs =
check_invs get_closing_ml_invariants closing_ml_invariant_class_of closing_ml_invariant_check_of
(* Output name for LaTeX macros.
Also rewrite "." to allow macros with objects long names *)
@ -833,12 +833,10 @@ val ISA_prefix = "Isabelle_DOF_"
val doc_class_prefix = ISA_prefix ^ "doc_class_"
val long_doc_class_prefix = ISA_prefix ^ "long_doc_class_"
fun is_ISA s = String.isPrefix ISA_prefix (Long_Name.base_name s)
fun get_class_name_without_prefix s = String.extract (s, String.size(doc_class_prefix), NONE)
fun get_doc_class_name_without_ISA_prefix s = String.extract (s, String.size(ISA_prefix), NONE)
fun transduce_term_global {mk_elaboration=mk_elaboration} (term,pos) thy =
(* pre: term should be fully typed in order to allow type-related term-transformations *)
@ -1115,19 +1113,20 @@ fun ML_isa_check_thm thy (term, _, pos) _ =
fun ML_isa_check_file thy (term, _, pos) _ =
let fun check thy (name, _) = name |> Syntax.read_input
|> Resources.check_file (Proof_Context.init_global thy) NONE
|> Resources.check_file (Proof_Context.init_global thy) NONE
in ML_isa_check_generic check thy (term, pos) end;
fun check_instance thy (term, _, pos) s =
let
val bname = Long_Name.base_name s;
val qual = Long_Name.qualifier s;
val class_name =
Long_Name.qualify qual (String.extract(bname , String.size(DOF_core.doc_class_prefix), NONE));
val class_name = (case try (unprefix DOF_core.doc_class_prefix) bname of
NONE => unprefix DOF_core.long_doc_class_prefix bname
| SOME name => name)
|> Long_Name.qualify qual
fun check thy (name, _) =
let
val object_cid = let val DOF_core.Instance cid = DOF_core.get_instance_global name thy
in cid |> #cid end
val object_cid = DOF_core.cid_of name thy
fun check' (class_name, object_cid) =
if class_name = object_cid then
DOF_core.value_of name thy
@ -1150,6 +1149,11 @@ fun ML_isa_check_trace_attribute thy (term, _, _) _ =
val _ = DOF_core.get_instance_global oid thy
in SOME term end
fun ML_isa_elaborate_generic (_:theory) isa_name ty term_option _ =
case term_option of
NONE => error("Wrong term option. You must use a defined term")
| SOME term => Const (isa_name, ty) $ term
(* Convert excluded mixfix symbols.
Unfortunately due to different lexical conventions for constant symbols and mixfix symbols
we can not use "_" or "'" for classes names in term antiquotation.
@ -1159,10 +1163,19 @@ val clean_string = translate_string
| "'" => "-"
| c => c);
fun ML_isa_elaborate_generic (_:theory) isa_name ty term_option _ =
case term_option of
NONE => error("Wrong term option. You must use a defined term")
| SOME term => Const (isa_name, ty) $ term
fun rm_mixfix name mixfix thy =
let
val old_constants =
Consts.dest (Sign.consts_of thy) |> #constants
|> map fst
|> filter (Long_Name.base_name #> equal name)
|> map (pair mixfix)
|> map swap
|> map (apfst (Syntax.read_term_global thy))
|> map (apsnd Mixfix.mixfix)
in thy |> (Local_Theory.notation false Syntax.mode_default old_constants
|> Named_Target.theory_map)
end
fun elaborate_instance thy _ _ term_option pos =
case term_option of
@ -1177,49 +1190,64 @@ fun elaborate_instance thy _ _ term_option pos =
because the class name is already bound to "doc_class Regular_Exp.rexp" constant
by add_doc_class_cmd function
*)
fun declare_ISA_class_accessor_and_check_instance doc_class_name =
fun declare_ISA_class_accessor_and_check_instance (doc_class_name, bind_pos) thy =
let
val bind = Binding.prefix_name DOF_core.doc_class_prefix doc_class_name
val typestring = "string => " ^ (Binding.name_of doc_class_name)
val conv_class_name = clean_string (Binding.name_of doc_class_name)
val mixfix_string = "@{" ^ conv_class_name ^ " _}"
val bname = Long_Name.base_name doc_class_name
val bname' = prefix DOF_core.doc_class_prefix bname
val bind = bname' |> pair bind_pos |> swap |> Binding.make
val bind' = prefix DOF_core.long_doc_class_prefix bname
|> pair bind_pos |> swap |> Binding.make
val const_typ = \<^typ>\<open>string\<close> --> Syntax.read_typ (Proof_Context.init_global thy) doc_class_name
fun mixfix_enclose name = name |> enclose "@{" " _}"
val mixfix = clean_string bname |> mixfix_enclose
val mixfix' = clean_string doc_class_name |> mixfix_enclose
in
Sign.add_consts_cmd [(bind, typestring, Mixfix.mixfix(mixfix_string))]
#> DOF_core.add_isa_transformer bind ((check_instance, elaborate_instance)
|> DOF_core.make_isa_transformer)
thy |> rm_mixfix bname' mixfix
|> Sign.add_consts [(bind, const_typ, Mixfix.mixfix mixfix)]
|> DOF_core.add_isa_transformer bind ((check_instance, elaborate_instance)
|> DOF_core.make_isa_transformer)
|> Sign.add_consts [(bind', const_typ, Mixfix.mixfix mixfix')]
|> DOF_core.add_isa_transformer bind' ((check_instance, elaborate_instance)
|> DOF_core.make_isa_transformer)
end
fun elaborate_instances_list thy isa_name _ _ _ =
let
val base_name = Long_Name.base_name isa_name
fun get_isa_name_without_intances_suffix s =
String.extract (s, 0, SOME (String.size(s) - String.size(instances_of_suffixN)))
val base_name_without_suffix = get_isa_name_without_intances_suffix base_name
val base_name' = DOF_core.get_class_name_without_prefix (base_name_without_suffix)
val class_typ = Proof_Context.read_typ (Proof_Context.init_global thy)
(base_name')
val long_class_name = DOF_core.get_onto_class_name_global base_name' thy
val qualifier = Long_Name.qualifier isa_name
val isa_name' = (case try (unprefix DOF_core.doc_class_prefix) base_name of
NONE => unprefix DOF_core.long_doc_class_prefix base_name
| SOME name => name)
|> unsuffix instances_of_suffixN
|> Long_Name.qualify qualifier
val class_typ = isa_name' |> Proof_Context.read_typ (Proof_Context.init_global thy)
val long_class_name = DOF_core.get_onto_class_name_global isa_name' thy
val values = thy |> Proof_Context.init_global |> DOF_core.get_instances
|> Name_Space.dest_table
|> filter (fn (_, instance) =>
let val DOF_core.Instance cid = instance
in (cid |> #cid) = long_class_name end)
|> filter (fn (name, _) => equal (DOF_core.cid_of name thy) long_class_name)
|> map (fn (oid, _) => DOF_core.value_of oid thy)
in HOLogic.mk_list class_typ values end
fun declare_class_instances_annotation thy doc_class_name =
fun declare_class_instances_annotation (doc_class_name, bind_pos) thy =
let
val bind = Binding.prefix_name DOF_core.doc_class_prefix doc_class_name
|> Binding.suffix_name instances_of_suffixN
val class_list_typ = Proof_Context.read_typ (Proof_Context.init_global thy)
((Binding.name_of doc_class_name) ^ " List.list")
val conv_class_name' = clean_string ((Binding.name_of doc_class_name) ^ instances_of_suffixN)
val mixfix_string = "@{" ^ conv_class_name' ^ "}"
val bname = Long_Name.base_name doc_class_name
val bname' = prefix DOF_core.doc_class_prefix bname |> suffix instances_of_suffixN
val bind = bname' |> pair bind_pos |> swap |> Binding.make
val bind' = prefix DOF_core.long_doc_class_prefix bname
|> suffix instances_of_suffixN |> pair bind_pos |> swap |> Binding.make
val class_typ = doc_class_name |> Proof_Context.read_typ (Proof_Context.init_global thy)
fun mixfix_enclose name = name |> enclose "@{" "}"
val mixfix = clean_string (bname ^ instances_of_suffixN) |> mixfix_enclose
val mixfix' = clean_string (doc_class_name ^ instances_of_suffixN) |> mixfix_enclose
in
Sign.add_consts [(bind, class_list_typ, Mixfix.mixfix(mixfix_string))]
#> DOF_core.add_isa_transformer bind ((check_identity, elaborate_instances_list)
|> DOF_core.make_isa_transformer)
thy |> rm_mixfix bname' mixfix
|> Sign.add_consts [(bind, \<^Type>\<open>list class_typ\<close>, Mixfix.mixfix mixfix)]
|> DOF_core.add_isa_transformer bind ((check_identity, elaborate_instances_list)
|> DOF_core.make_isa_transformer)
|> Sign.add_consts [(bind', \<^Type>\<open>list class_typ\<close>, Mixfix.mixfix mixfix')]
|> DOF_core.add_isa_transformer bind' ((check_identity, elaborate_instances_list)
|> DOF_core.make_isa_transformer)
end
fun symbex_attr_access0 ctxt proj_term term =
@ -2968,6 +2996,7 @@ fun define_inv cid_long ((lbl, pos), inv) thy =
fun add_doc_class_cmd overloaded (raw_params, binding)
raw_parent raw_fieldsNdefaults reject_Atoms regexps invariants thy =
let
val bind_pos = Binding.pos_of binding
val ctxt = Proof_Context.init_global thy;
val params = map (apsnd (Typedecl.read_constraint ctxt)) raw_params;
val ctxt1 = fold (Variable.declare_typ o TFree) params ctxt;
@ -3024,8 +3053,8 @@ fun add_doc_class_cmd overloaded (raw_params, binding)
(* The function declare_ISA_class_accessor_and_check_instance uses a prefix
because the class name is already bound to "doc_class Regular_Exp.rexp" constant
by add_doc_class_cmd function *)
|> ISA_core.declare_ISA_class_accessor_and_check_instance binding
|> (fn thy => (ISA_core.declare_class_instances_annotation thy binding) thy)
|> (fn thy => ISA_core.declare_ISA_class_accessor_and_check_instance (cid thy, bind_pos) thy)
|> (fn thy => ISA_core.declare_class_instances_annotation (cid thy, bind_pos) thy)
end;