Refine the supression of abbreviations for morphisms that are not identities.
authorballarin
Wed, 18 Nov 2015 21:18:33 +0100
changeset 61701 e89cfc004f18
parent 61700 286c1741285c
child 61702 2e89bc578935
Refine the supression of abbreviations for morphisms that are not identities.
NEWS
src/Doc/Locales/Examples1.thy
src/Doc/Locales/Examples3.thy
src/FOL/ex/Locale_Test/Locale_Test1.thy
src/Pure/Isar/generic_target.ML
--- a/NEWS	Wed Nov 18 17:37:00 2015 +0000
+++ b/NEWS	Wed Nov 18 21:18:33 2015 +0100
@@ -314,6 +314,28 @@
 * Keyword 'rewrites' identifies rewrite morphisms in interpretation
 commands.  Previously, the keyword was 'where'.  INCOMPATIBILITY.
 
+* More gentle suppression of syntax along locale morphisms while
+printing terms.  Previously 'abbreviation' and 'notation' declarations
+would be suppressed for morphisms except term identity.  Now
+'abbreviation' is also kept for morphims that only change the involved
+parameters, and only 'notation' is suppressed.  This can be of great
+help when working with complex locale hierarchies, because proof
+states are displayed much more succinctly.  It also means that only
+notation needs to be redeclared if desired, as illustrated by this
+example:
+
+  locale struct = fixes composition :: "'a => 'a => 'a" (infixl "\<cdot>" 65)
+  begin
+    definition derived (infixl "\<odot>" 65) where ...
+  end
+
+  locale morphism =
+    left: struct composition + right: struct composition'
+    for composition (infix "\<cdot>" 65) and composition' (infix "\<cdot>''" 65)
+  begin
+    notation right.derived ("\<odot>''")
+  end
+
 * Command 'sublocale' accepts mixin definitions after keyword
 'defines'.
 
--- a/src/Doc/Locales/Examples1.thy	Wed Nov 18 17:37:00 2015 +0000
+++ b/src/Doc/Locales/Examples1.thy	Wed Nov 18 21:18:33 2015 +0100
@@ -70,13 +70,13 @@
   The prefix @{text int} is applied to all names introduced in locale
   conclusions including names introduced in definitions.  The
   qualified name @{text int.less} is short for
-  the interpretation of the definition, which is @{term int.less}.
+  the interpretation of the definition, which is @{text "partial_order.less op \<le>"}.
   Qualified name and expanded form may be used almost
   interchangeably.%
-\footnote{Since @{term "op \<le>"} is polymorphic, for @{term int.less} a
+\footnote{Since @{term "op \<le>"} is polymorphic, for @{text "partial_order.less op \<le>"} a
   more general type will be inferred than for @{text int.less} which
   is over type @{typ int}.}
-  The latter is preferred on output, as for example in the theorem
+  The former is preferred on output, as for example in the theorem
   @{thm [source] int.less_le_trans}: @{thm [display, indent=2]
   int.less_le_trans}
   Both notations for the strict order are not satisfactory.  The
--- a/src/Doc/Locales/Examples3.thy	Wed Nov 18 17:37:00 2015 +0000
+++ b/src/Doc/Locales/Examples3.thy	Wed Nov 18 21:18:33 2015 +0100
@@ -223,15 +223,13 @@
 
   \hspace*{1em}@{thm [source] le'.less_le_trans}:
   @{thm [display, indent=4] le'.less_le_trans}
-  While there is infix syntax for the strict operation associated to
+  While there is infix syntax for the strict operation associated with
   @{term "op \<sqsubseteq>"}, there is none for the strict version of @{term
-  "op \<preceq>"}.  The abbreviation @{text less} with its infix syntax is only
+  "op \<preceq>"}.  The syntax @{text "\<sqsubset>"} for @{text less} is only
   available for the original instance it was declared for.  We may
-  introduce the abbreviation @{text less'} with infix syntax~@{text \<prec>}
-  with the following declaration:\<close>
+  introduce infix syntax for @{text le'.less} with the following declaration:\<close>
 
-  abbreviation (in order_preserving)
-    less' (infixl "\<prec>" 50) where "less' \<equiv> partial_order.less le'"
+  notation (in order_preserving) le'.less (infixl "\<prec>" 50)
 
 text (in order_preserving) \<open>Now the theorem is displayed nicely as
   @{thm [source]  le'.less_le_trans}:
@@ -306,8 +304,8 @@
 
   context lattice_hom
   begin
-  abbreviation meet' (infixl "\<sqinter>''" 50) where "meet' \<equiv> le'.meet"
-  abbreviation join' (infixl "\<squnion>''" 50) where "join' \<equiv> le'.join"
+  notation le'.meet (infixl "\<sqinter>''" 50)
+  notation le'.join (infixl "\<squnion>''" 50)
   end
 
 text \<open>The next example makes radical use of the short hand
--- a/src/FOL/ex/Locale_Test/Locale_Test1.thy	Wed Nov 18 17:37:00 2015 +0000
+++ b/src/FOL/ex/Locale_Test/Locale_Test1.thy	Wed Nov 18 21:18:33 2015 +0100
@@ -126,26 +126,7 @@
 thm var.test_def
 
 
-text \<open>Under which circumstances term syntax remains active.\<close>
-
-locale "syntax" =
-  fixes p1 :: "'a => 'b"
-    and p2 :: "'b => o"
-begin
-
-definition d1 :: "'a => o" where "d1(x) \<longleftrightarrow> \<not> p2(p1(x))"
-definition d2 :: "'b => o" where "d2(x) \<longleftrightarrow> \<not> p2(x)"
-
-thm d1_def d2_def
-
-end
-
-thm syntax.d1_def syntax.d2_def
-
-locale syntax' = "syntax" p1 p2 for p1 :: "'a => 'a" and p2 :: "'a => o"
-begin
-
-thm d1_def d2_def  (* should print as "d1(?x) <-> ..." and "d2(?x) <-> ..." *)
+text \<open>Under which circumstances notation remains active.\<close>
 
 ML \<open>
   fun check_syntax ctxt thm expected =
@@ -161,9 +142,28 @@
 
 declare [[show_hyps]]
 
+locale "syntax" =
+  fixes p1 :: "'a => 'b"
+    and p2 :: "'b => o"
+begin
+
+definition d1 :: "'a => o" ("D1'(_')") where "d1(x) \<longleftrightarrow> \<not> p2(p1(x))"
+definition d2 :: "'b => o" ("D2'(_')") where "d2(x) \<longleftrightarrow> \<not> p2(x)"
+
+thm d1_def d2_def
+
+end
+
+thm syntax.d1_def syntax.d2_def
+
+locale syntax' = "syntax" p1 p2 for p1 :: "'a => 'a" and p2 :: "'a => o"
+begin
+
+thm d1_def d2_def  (* should print as "D1(?x) <-> ..." and "D2(?x) <-> ..." *)
+
 ML \<open>
-  check_syntax @{context} @{thm d1_def} "d1(?x) \<longleftrightarrow> \<not> p2(p1(?x))";
-  check_syntax @{context} @{thm d2_def} "d2(?x) \<longleftrightarrow> \<not> p2(?x)";
+  check_syntax @{context} @{thm d1_def} "D1(?x) \<longleftrightarrow> \<not> p2(p1(?x))";
+  check_syntax @{context} @{thm d2_def} "D2(?x) \<longleftrightarrow> \<not> p2(?x)";
 \<close>
 
 end
@@ -172,11 +172,11 @@
 begin
 
 thm d1_def d2_def
-  (* should print as "syntax.d1(p3, p2, ?x) <-> ..." and "d2(?x) <-> ..." *)
+  (* should print as "d1(?x) <-> ..." and "D2(?x) <-> ..." *)
 
 ML \<open>
-  check_syntax @{context} @{thm d1_def} "syntax.d1(p3, p2, ?x) \<longleftrightarrow> \<not> p2(p3(?x))";
-  check_syntax @{context} @{thm d2_def} "d2(?x) \<longleftrightarrow> \<not> p2(?x)";
+  check_syntax @{context} @{thm d1_def} "d1(?x) \<longleftrightarrow> \<not> p2(p3(?x))";
+  check_syntax @{context} @{thm d2_def} "D2(?x) \<longleftrightarrow> \<not> p2(?x)";
 \<close>
 
 end
--- a/src/Pure/Isar/generic_target.ML	Wed Nov 18 17:37:00 2015 +0000
+++ b/src/Pure/Isar/generic_target.ML	Wed Nov 18 21:18:33 2015 +0100
@@ -112,12 +112,17 @@
   else (warning ("Dropping global mixfix syntax: " ^ Binding.print b ^ " " ^
     Pretty.string_of (Mixfix.pretty_mixfix mx)); NoSyn);
 
+fun same_const (Const (c, _), Const (c', _)) = c = c'
+  | same_const (t $ _, t' $ _) = same_const (t, t')
+  | same_const (_, _) = false;
+
 fun const_decl phi_pred prmode ((b, mx), rhs) phi context =
   if phi_pred phi then
     let
       val b' = Morphism.binding phi b;
       val rhs' = Morphism.term phi rhs;
       val same_shape = Term.aconv_untyped (rhs, rhs');
+      val same_stem = same_shape orelse same_const (rhs, rhs');
       val const_alias =
         if same_shape then
           (case rhs' of
@@ -141,9 +146,9 @@
       | NONE =>
           context
           |> Proof_Context.generic_add_abbrev Print_Mode.internal (b', Term.close_schematic_term rhs')
-          |-> (fn (const as Const (c, _), _) => same_shape ?
+          |-> (fn (const as Const (c, _), _) => same_stem ?
                 (Proof_Context.generic_revert_abbrev (#1 prmode) c #>
-                 Morphism.form (Proof_Context.generic_notation true prmode [(const, mx)]))))
+                 same_shape ? Morphism.form (Proof_Context.generic_notation true prmode [(const, mx)]))))
     end
   else context;