Improved parameter management of locales.
authorballarin
Tue, 06 Jun 2006 10:05:57 +0200
changeset 19783 82f365a14960
parent 19782 48c4632e2c28
child 19784 fa5080577da9
Improved parameter management of locales.
NEWS
src/FOL/ex/LocaleTest.thy
src/HOL/Algebra/CRing.thy
src/HOL/Algebra/Group.thy
src/HOL/Algebra/Lattice.thy
src/HOL/Algebra/Module.thy
src/HOL/Algebra/UnivPoly.thy
src/Pure/Isar/locale.ML
src/Pure/Pure.thy
--- a/NEWS	Tue Jun 06 09:28:24 2006 +0200
+++ b/NEWS	Tue Jun 06 10:05:57 2006 +0200
@@ -196,6 +196,12 @@
 slightly different -- use 'const_syntax' instead of raw 'syntax', and
 'translations' with explicit "CONST" markup to accommodate this.
 
+* Isar/locales: improved parameter handling:
+- use of locales "var" and "struct" no longer necessary;
+- parameter renamings are no longer required to be injective.
+  This enables, for example, to define a locale for endomorphisms thus:
+  locale endom = homom mult mult h.
+
 * Provers/induct: improved internal context management to support
 local fixes and defines on-the-fly.  Thus explicit meta-level
 connectives !! and ==> are rarely required anymore in inductive goals
--- a/src/FOL/ex/LocaleTest.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/FOL/ex/LocaleTest.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -53,8 +53,16 @@
 locale LU = LT mult (infixl "**" 60) + LT add (infixl "++" 55) + var h +
   assumes hom: "h(x ** y) = h(x) ++ h(y)"
 
+(*
+Graceful handling of type errors?
+locale LY = LT mult (infixl "**" 60) + LT add (binder "++" 55) + var h +
+  assumes "mult(x) == add"
+*)
+
 locale LV = LU _ add
 
+locale LW = LU _ mult (infixl "**" 60)
+
 
 subsection {* Constrains *}
 
--- a/src/HOL/Algebra/CRing.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/HOL/Algebra/CRing.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -23,7 +23,8 @@
   a_minus :: "[('a, 'm) ring_scheme, 'a, 'a] => 'a" (infixl "\<ominus>\<index>" 65)
   "[| x \<in> carrier R; y \<in> carrier R |] ==> x \<ominus> y == x \<oplus> (\<ominus> y)"
 
-locale abelian_monoid = struct G +
+locale abelian_monoid =
+  fixes G (structure)
   assumes a_comm_monoid:
      "comm_monoid (| carrier = carrier G, mult = add G, one = zero G |)"
 
@@ -40,7 +41,7 @@
 subsection {* Basic Properties *}
 
 lemma abelian_monoidI:
-  includes struct R
+  fixes R (structure)
   assumes a_closed:
       "!!x y. [| x \<in> carrier R; y \<in> carrier R |] ==> x \<oplus> y \<in> carrier R"
     and zero_closed: "\<zero> \<in> carrier R"
@@ -54,7 +55,10 @@
   by (auto intro!: abelian_monoid.intro comm_monoidI intro: prems)
 
 lemma abelian_groupI:
+(*
   includes struct R
+*)
+  fixes R (structure)
   assumes a_closed:
       "!!x y. [| x \<in> carrier R; y \<in> carrier R |] ==> x \<oplus> y \<in> carrier R"
     and zero_closed: "zero R \<in> carrier R"
@@ -309,7 +313,10 @@
 subsection {* Basic Facts of Rings *}
 
 lemma ringI:
+(*
   includes struct R
+*)
+  fixes R (structure)
   assumes abelian_group: "abelian_group R"
     and monoid: "monoid R"
     and l_distr: "!!x y z. [| x \<in> carrier R; y \<in> carrier R; z \<in> carrier R |]
@@ -329,7 +336,10 @@
   by (auto intro!: monoidI m_assoc)
 
 lemma cringI:
+(*
   includes struct R
+*)
+  fixes R (structure)
   assumes abelian_group: "abelian_group R"
     and comm_monoid: "comm_monoid R"
     and l_distr: "!!x y z. [| x \<in> carrier R; y \<in> carrier R; z \<in> carrier R |]
@@ -539,7 +549,10 @@
       h \<one> = \<one>\<^bsub>S\<^esub>}"
 
 lemma ring_hom_memI:
+(*
   includes struct R + struct S
+*)
+  fixes R (structure) and S (structure)
   assumes hom_closed: "!!x. x \<in> carrier R ==> h x \<in> carrier S"
     and hom_mult: "!!x y. [| x \<in> carrier R; y \<in> carrier R |] ==>
       h (x \<otimes> y) = h x \<otimes>\<^bsub>S\<^esub> h y"
@@ -554,25 +567,26 @@
   by (auto simp add: ring_hom_def funcset_mem)
 
 lemma ring_hom_mult:
-  includes struct R + struct S
+  fixes R (structure) and S (structure)
   shows
     "[| h \<in> ring_hom R S; x \<in> carrier R; y \<in> carrier R |] ==>
     h (x \<otimes> y) = h x \<otimes>\<^bsub>S\<^esub> h y"
     by (simp add: ring_hom_def)
 
 lemma ring_hom_add:
-  includes struct R + struct S
+  fixes R (structure) and S (structure)
   shows
     "[| h \<in> ring_hom R S; x \<in> carrier R; y \<in> carrier R |] ==>
     h (x \<oplus> y) = h x \<oplus>\<^bsub>S\<^esub> h y"
     by (simp add: ring_hom_def)
 
 lemma ring_hom_one:
-  includes struct R + struct S
+  fixes R (structure) and S (structure)
   shows "h \<in> ring_hom R S ==> h \<one> = \<one>\<^bsub>S\<^esub>"
   by (simp add: ring_hom_def)
 
-locale ring_hom_cring = cring R + cring S + var h +
+locale ring_hom_cring = cring R + cring S +
+  fixes h
   assumes homh [simp, intro]: "h \<in> ring_hom R S"
   notes hom_closed [simp, intro] = ring_hom_closed [OF homh]
     and hom_mult [simp] = ring_hom_mult [OF homh]
--- a/src/HOL/Algebra/Group.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/HOL/Algebra/Group.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -40,7 +40,8 @@
     let p = nat_rec \<one>\<^bsub>G\<^esub> (%u b. b \<otimes>\<^bsub>G\<^esub> a)
     in if neg z then inv\<^bsub>G\<^esub> (p (nat (-z))) else p (nat z)"
 
-locale monoid = struct G +
+locale monoid =
+  fixes G (structure)
   assumes m_closed [intro, simp]:
          "\<lbrakk>x \<in> carrier G; y \<in> carrier G\<rbrakk> \<Longrightarrow> x \<otimes> y \<in> carrier G"
       and m_assoc:
@@ -51,7 +52,7 @@
       and r_one [simp]: "x \<in> carrier G \<Longrightarrow> x \<otimes> \<one> = x"
 
 lemma monoidI:
-  includes struct G
+  fixes G (structure)
   assumes m_closed:
       "!!x y. [| x \<in> carrier G; y \<in> carrier G |] ==> x \<otimes> y \<in> carrier G"
     and one_closed: "\<one> \<in> carrier G"
@@ -192,7 +193,7 @@
   by (rule group.intro [OF prems]) 
 
 theorem groupI:
-  includes struct G
+  fixes G (structure)
   assumes m_closed [simp]:
       "!!x y. [| x \<in> carrier G; y \<in> carrier G |] ==> x \<otimes> y \<in> carrier G"
     and one_closed [simp]: "\<one> \<in> carrier G"
@@ -359,7 +360,8 @@
 
 subsection {* Subgroups *}
 
-locale subgroup = var H + struct G + 
+locale subgroup =
+  fixes H and G (structure)
   assumes subset: "H \<subseteq> carrier G"
     and m_closed [intro, simp]: "\<lbrakk>x \<in> H; y \<in> H\<rbrakk> \<Longrightarrow> x \<otimes> y \<in> H"
     and  one_closed [simp]: "\<one> \<in> H"
@@ -600,7 +602,7 @@
 lemmas (in comm_monoid) m_ac = m_assoc m_comm m_lcomm
 
 lemma comm_monoidI:
-  includes struct G
+  fixes G (structure)
   assumes m_closed:
       "!!x y. [| x \<in> carrier G; y \<in> carrier G |] ==> x \<otimes> y \<in> carrier G"
     and one_closed: "\<one> \<in> carrier G"
@@ -645,7 +647,7 @@
                   is_group prems)
 
 lemma comm_groupI:
-  includes struct G
+  fixes G (structure)
   assumes m_closed:
       "!!x y. [| x \<in> carrier G; y \<in> carrier G |] ==> x \<otimes> y \<in> carrier G"
     and one_closed: "\<one> \<in> carrier G"
--- a/src/HOL/Algebra/Lattice.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/HOL/Algebra/Lattice.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -19,7 +19,8 @@
 record 'a order = "'a partial_object" +
   le :: "['a, 'a] => bool" (infixl "\<sqsubseteq>\<index>" 50)
 
-locale partial_order = struct L +
+locale partial_order =
+  fixes L (structure)
   assumes refl [intro, simp]:
                   "x \<in> carrier L ==> x \<sqsubseteq> x"
     and anti_sym [intro]:
@@ -69,12 +70,12 @@
   by (unfold Upper_def) clarify
 
 lemma UpperD [dest]:
-  includes struct L
+  fixes L (structure)
   shows "[| u \<in> Upper L A; x \<in> A; A \<subseteq> carrier L |] ==> x \<sqsubseteq> u"
   by (unfold Upper_def) blast
 
 lemma Upper_memI:
-  includes struct L
+  fixes L (structure)
   shows "[| !! y. y \<in> A ==> y \<sqsubseteq> x; x \<in> carrier L |] ==> x \<in> Upper L A"
   by (unfold Upper_def) blast
 
@@ -90,12 +91,12 @@
   by (unfold Lower_def) clarify
 
 lemma LowerD [dest]:
-  includes struct L
+  fixes L (structure)
   shows "[| l \<in> Lower L A; x \<in> A; A \<subseteq> carrier L |] ==> l \<sqsubseteq> x"
   by (unfold Lower_def) blast
 
 lemma Lower_memI:
-  includes struct L
+  fixes L (structure)
   shows "[| !! y. y \<in> A ==> x \<sqsubseteq> y; x \<in> carrier L |] ==> x \<in> Lower L A"
   by (unfold Lower_def) blast
 
@@ -119,12 +120,12 @@
   by (unfold least_def) blast
 
 lemma least_le:
-  includes struct L
+  fixes L (structure)
   shows "[| least L x A; a \<in> A |] ==> x \<sqsubseteq> a"
   by (unfold least_def) fast
 
 lemma least_UpperI:
-  includes struct L
+  fixes L (structure)
   assumes above: "!! x. x \<in> A ==> x \<sqsubseteq> s"
     and below: "!! y. y \<in> Upper L A ==> s \<sqsubseteq> y"
     and L: "A \<subseteq> carrier L"  "s \<in> carrier L"
@@ -152,12 +153,12 @@
   by (unfold greatest_def) blast
 
 lemma greatest_le:
-  includes struct L
+  fixes L (structure)
   shows "[| greatest L x A; a \<in> A |] ==> a \<sqsubseteq> x"
   by (unfold greatest_def) fast
 
 lemma greatest_LowerI:
-  includes struct L
+  fixes L (structure)
   assumes below: "!! x. x \<in> A ==> i \<sqsubseteq> x"
     and above: "!! y. y \<in> Lower L A ==> y \<sqsubseteq> i"
     and L: "A \<subseteq> carrier L"  "i \<in> carrier L"
@@ -179,12 +180,12 @@
     "[| x \<in> carrier L; y \<in> carrier L |] ==> EX s. greatest L s (Lower L {x, y})"
 
 lemma least_Upper_above:
-  includes struct L
+  fixes L (structure)
   shows "[| least L s (Upper L A); x \<in> A; A \<subseteq> carrier L |] ==> x \<sqsubseteq> s"
   by (unfold least_def) blast
 
 lemma greatest_Lower_above:
-  includes struct L
+  fixes L (structure)
   shows "[| greatest L i (Lower L A); x \<in> A; A \<subseteq> carrier L |] ==> i \<sqsubseteq> x"
   by (unfold greatest_def) blast
 
@@ -211,8 +212,7 @@
   by (rule least_UpperI) fast+
 
 lemma (in partial_order) sup_of_singleton [simp]:
-  includes struct L
-  shows "x \<in> carrier L ==> \<Squnion>{x} = x"
+  "x \<in> carrier L ==> \<Squnion>{x} = x"
   by (unfold sup_def) (blast intro: least_unique least_UpperI sup_of_singletonI)
 
 
@@ -400,7 +400,7 @@
 qed (simp_all add: L)
 
 lemma join_comm:
-  includes struct L
+  fixes L (structure)
   shows "x \<squnion> y = y \<squnion> x"
   by (unfold join_def) (simp add: insert_commute)
 
@@ -439,8 +439,7 @@
   by (rule greatest_LowerI) fast+
 
 lemma (in partial_order) inf_of_singleton [simp]:
-  includes struct L
-  shows "x \<in> carrier L ==> \<Sqinter> {x} = x"
+  "x \<in> carrier L ==> \<Sqinter> {x} = x"
   by (unfold inf_def) (blast intro: greatest_unique greatest_LowerI inf_of_singletonI)
 
 text {* Condition on A: infimum exists. *}
@@ -629,7 +628,7 @@
 qed (simp_all add: L)
 
 lemma meet_comm:
-  includes struct L
+  fixes L (structure)
   shows "x \<sqinter> y = y \<sqinter> x"
   by (unfold meet_def) (simp add: insert_commute)
 
--- a/src/HOL/Algebra/Module.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/HOL/Algebra/Module.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -32,7 +32,7 @@
       (a \<odot>\<^bsub>M\<^esub> x) \<otimes>\<^bsub>M\<^esub> y = a \<odot>\<^bsub>M\<^esub> (x \<otimes>\<^bsub>M\<^esub> y)"
 
 lemma moduleI:
-  includes struct R + struct M
+  fixes R (structure) and M (structure)
   assumes cring: "cring R"
     and abelian_group: "abelian_group M"
     and smult_closed:
@@ -53,7 +53,7 @@
     module_axioms.intro prems)
 
 lemma algebraI:
-  includes struct R + struct M
+  fixes R (structure) and M (structure)
   assumes R_cring: "cring R"
     and M_cring: "cring M"
     and smult_closed:
--- a/src/HOL/Algebra/UnivPoly.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/HOL/Algebra/UnivPoly.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -163,7 +163,8 @@
 
 subsection {* Effect of operations on coefficients *}
 
-locale UP = struct R + struct P +
+locale UP =
+  fixes R (structure) and P (structure)
   defines P_def: "P == UP R"
 
 locale UP_cring = UP + cring R
@@ -1043,7 +1044,7 @@
 
 
 lemma (in UP) eval_on_carrier:
-  includes struct S
+  fixes S (structure)
   shows "p \<in> carrier P ==>
   eval R S phi s p = (\<Oplus>\<^bsub>S\<^esub> i \<in> {..deg R p}. phi (coeff P p i) \<otimes>\<^bsub>S\<^esub> s (^)\<^bsub>S\<^esub> i)"
   by (unfold eval_def, fold P_def) simp
@@ -1057,7 +1058,8 @@
 
 locale UP_pre_univ_prop = ring_hom_cring R S h + UP_cring R P
 
-locale UP_univ_prop = UP_pre_univ_prop + var s + var Eval +
+locale UP_univ_prop = UP_pre_univ_prop +
+  fixes s and Eval
   assumes indet_img_carrier [simp, intro]: "s \<in> carrier S"
   defines Eval_def: "Eval == eval R S h s"
 
--- a/src/Pure/Isar/locale.ML	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/Pure/Isar/locale.ML	Tue Jun 06 10:05:57 2006 +0200
@@ -151,7 +151,8 @@
        (cf. [1], normalisation of locale expressions.)
     *)
   import: expr,                                                     (*dynamic import*)
-  elems: (Element.context_i * stamp) list,                          (*static content*)
+  elems: (Element.context_i * stamp) list,
+    (* Static content, neither Fixes nor Constrains elements *)
   params: ((string * typ) * mixfix) list,                           (*all params*)
   lparams: string list,                                             (*local parmas*)
   term_syntax: ((Proof.context -> Proof.context) * stamp) list, (* FIXME depend on morphism *)
@@ -489,6 +490,23 @@
 fun err_in_locale' ctxt msg ids' = err_in_locale ctxt msg (map fst ids');
 
 
+fun pretty_ren NONE = Pretty.str "_"
+  | pretty_ren (SOME (x, NONE)) = Pretty.str x
+  | pretty_ren (SOME (x, SOME syn)) =
+      Pretty.block [Pretty.str x, Pretty.brk 1, Syntax.pretty_mixfix syn];
+
+fun pretty_expr thy (Locale name) = Pretty.str (extern thy name)
+  | pretty_expr thy (Rename (expr, xs)) =
+      Pretty.block [pretty_expr thy expr, Pretty.brk 1, Pretty.block (map pretty_ren xs |> Pretty.breaks)]
+  | pretty_expr thy (Merge es) =
+      Pretty.separate "+" (map (pretty_expr thy) es) |> Pretty.block;
+
+fun err_in_expr _ msg (Merge []) = error msg
+  | err_in_expr ctxt msg expr =
+    error (msg ^ "\n" ^ Pretty.string_of (Pretty.block
+      [Pretty.str "The error(s) above occured in locale expression:", Pretty.brk 1,
+       pretty_expr (ProofContext.theory_of ctxt) expr]));
+
 
 (** structured contexts: rename + merge + implicit type instantiation **)
 
@@ -552,18 +570,6 @@
 
 local
 
-fun unique_parms ctxt elemss =
-  let
-    val param_decls =
-      maps (fn (((name, (ps, qs)), _), _) => map (rpair (name, ps)) qs) elemss
-      |> Symtab.make_list |> Symtab.dest;
-  in
-    (case find_first (fn (_, ids) => length ids > 1) param_decls of
-      SOME (q, ids) => err_in_locale ctxt ("Multiple declaration of parameter " ^ quote q)
-          (map (apsnd (map fst)) ids)
-    | NONE => map (apfst (apfst (apsnd #1))) elemss)
-  end;
-
 fun unify_parms ctxt fixed_parms raw_parmss =
   let
     val thy = ProofContext.theory_of ctxt;
@@ -612,7 +618,7 @@
 
 (* like unify_elemss, but does not touch mode, additional
    parameter c_parms for enforcing further constraints (eg. syntax) *)
-(* FIXME avoid code duplication *)
+(* FIXME avoid code duplication *) (* FIXME: avoid stipulating comments *)
 
 fun unify_elemss' _ _ [] [] = []
   | unify_elemss' _ [] [elems] [] = [elems]
@@ -627,6 +633,84 @@
       in map inst (elemss ~~ Library.take (length elemss, envs)) end;
 
 
+(* params_of_expr:
+   Compute parameters (with types and syntax) of locale expression.
+*)
+
+fun params_of_expr ctxt fixed_params expr (prev_parms, prev_types, prev_syn) =
+  let
+    val thy = ProofContext.theory_of ctxt;
+
+    fun renaming (SOME x :: xs) (y :: ys) = (y, x) :: renaming xs ys
+      | renaming (NONE :: xs) (y :: ys) = renaming xs ys
+      | renaming [] _ = []
+      | renaming xs [] = error ("Too many arguments in renaming: " ^
+          commas (map (fn NONE => "_" | SOME x => quote (fst x)) xs));
+
+    fun merge_tenvs fixed tenv1 tenv2 =
+        let
+          val [env1, env2] = unify_parms ctxt fixed
+                [tenv1 |> Symtab.dest |> map (apsnd SOME),
+                 tenv2 |> Symtab.dest |> map (apsnd SOME)]
+        in
+          Symtab.merge (op =) (Symtab.map (Element.instT_type env1) tenv1,
+            Symtab.map (Element.instT_type env2) tenv2)
+        end;
+
+    fun merge_syn expr syn1 syn2 =
+        Symtab.merge (op =) (syn1, syn2)
+        handle Symtab.DUPS xs => err_in_expr ctxt
+          ("Conflicting syntax for parameter(s): " ^ commas_quote xs) expr;
+            
+    fun params_of (expr as Locale name) =
+          let
+            val {import, params, ...} = the_locale thy name;
+            val parms = map (fst o fst) params;
+            val (parms', types', syn') = params_of import;
+            val all_parms = merge_lists parms' parms;
+            val all_types = merge_tenvs [] types' (params |> map fst |> Symtab.make);
+            val all_syn = merge_syn expr syn' (params |> map (apfst fst) |> Symtab.make);
+          in (all_parms, all_types, all_syn) end
+      | params_of (expr as Rename (e, xs)) =
+          let
+            val (parms', types', syn') = params_of e;
+            val ren = renaming xs parms';
+            (* renaming may reduce number of parameters *)
+            val new_parms = map (Element.rename ren) parms' |> distinct (op =);
+            val ren_syn = syn' |> Symtab.dest |> map (Element.rename_var ren);
+            val new_syn = fold (Symtab.insert (op =)) ren_syn Symtab.empty
+                handle Symtab.DUP x =>
+                  err_in_expr ctxt ("Conflicting syntax for parameter: " ^ quote x) expr;
+            val syn_types = map (apsnd (fn mx => SOME (Type.freeze_type (#1 (TypeInfer.paramify_dummies (TypeInfer.mixfixT mx) 0))))) (Symtab.dest new_syn);
+            val ren_types = types' |> Symtab.dest |> map (apfst (Element.rename ren));
+            val (env :: _) = unify_parms ctxt [] 
+                ((ren_types |> map (apsnd SOME)) :: map single syn_types);
+            val new_types = fold (Symtab.insert (op =))
+                (map (apsnd (Element.instT_type env)) ren_types) Symtab.empty;
+          in (new_parms, new_types, new_syn) end
+      | params_of (Merge es) =
+          fold (fn e => fn (parms, types, syn) =>
+                   let
+                     val (parms', types', syn') = params_of e
+                   in
+                     (merge_lists parms parms', merge_tenvs [] types types',
+                      merge_syn e syn syn')
+                   end)
+            es ([], Symtab.empty, Symtab.empty)
+
+      val (parms, types, syn) = params_of expr;
+    in
+      (merge_lists prev_parms parms, merge_tenvs fixed_params prev_types types,
+       merge_syn expr prev_syn syn)
+    end;
+
+fun make_params_ids params = [(("", params), ([], Assumed []))];
+fun make_raw_params_elemss (params, tenv, syn) =
+    [((("", map (fn p => (p, Symtab.lookup tenv p)) params), Assumed []),
+      Int [Fixes (map (fn p =>
+        (p, Symtab.lookup tenv p, Symtab.lookup syn p |> the)) params)])];
+
+
 (* flatten_expr:
    Extend list of identifiers by those new in locale expression expr.
    Compute corresponding list of lists of locale elements (one entry per
@@ -659,14 +743,11 @@
           commas (map (fn NONE => "_" | SOME x => quote (fst x)) xs));
 
     fun rename_parms top ren ((name, ps), (parms, mode)) =
-      let val ps' = map (Element.rename ren) ps in
-        (case duplicates (op =) ps' of
-          [] => ((name, ps'),
-                 if top then (map (Element.rename ren) parms,
-                   map_mode (map (Element.rename_witness ren)) mode)
-                 else (parms, mode))
-        | dups => err_in_locale ctxt ("Duplicate parameters: " ^ commas_quote dups) [(name, ps')])
-      end;
+        ((name, map (Element.rename ren) ps),
+         if top
+         then (map (Element.rename ren) parms,
+               map_mode (map (Element.rename_witness ren)) mode)
+         else (parms, mode));
 
     (* add registrations of (name, ps), recursively; adjust hyps of witnesses *)
 
@@ -739,8 +820,8 @@
 
             val ids'' = distinct (eq_fst (op =)) (map (rename_parms top ren) ids');
             val parms'' = distinct (op =) (maps (#2 o #1) ids'');
-            val syn'' = syn' |> Symtab.dest |> map (Element.rename_var ren) |> Symtab.make;
-            (* check for conflicting syntax? *)
+            val syn'' = fold (Symtab.insert (op =))
+                (map (Element.rename_var ren) (Symtab.dest syn')) Symtab.empty;
           in (ids'', parms'', syn'') end
       | identify top (Merge es) =
           fold (fn e => fn (ids, parms, syn) =>
@@ -765,8 +846,8 @@
         fun lookup_syn x = (case Symtab.lookup syn x of SOME Structure => NONE | opt => opt);
         val ren = map #1 ps' ~~ map (fn x => (x, lookup_syn x)) xs;
         val (params', elems') =
-          if null ren then ((ps', qs), map #1 elems)
-          else ((map (apfst (Element.rename ren)) ps', map (Element.rename ren) qs),
+          if null ren then ((ps'(*, qs*)), map #1 elems)
+          else ((map (apfst (Element.rename ren)) ps'(*, map (Element.rename ren) qs*)),
             map (Element.rename_ctxt ren o #1) elems);
         val elems'' = elems' |> map (Element.map_ctxt
           {var = I, typ = I, term = I, fact = I, attrib = I,
@@ -781,8 +862,8 @@
     val (ids, _, syn) = identify true expr;
     val idents = gen_rems (eq_fst (op =)) (ids, prev_idents);
     val syntax = merge_syntax ctxt ids (syn, prev_syntax);
-    (* add types to params, check for unique params and unify them *)
-    val raw_elemss = unique_parms ctxt (map (eval syntax) idents);
+    (* add types to params and unify them *)
+    val raw_elemss = (*unique_parms ctxt*) (map (eval syntax) idents);
     val elemss = unify_elemss' ctxt [] raw_elemss (map (apsnd mixfix_type) (Symtab.dest syntax));
     (* replace params in ids by params from axioms,
        adjust types in mode *)
@@ -909,52 +990,13 @@
   | intern_expr thy (Rename (expr, xs)) = Rename (intern_expr thy expr, xs);
 
 
-(* experimental code for type inference *)
-
-local
-
-fun declare_int_elem (ctxt, Fixes fixes) =
-      (ctxt |> ProofContext.add_fixes_i (map (fn (x, T, mx) =>
-        (x, Option.map (Term.map_type_tfree (TypeInfer.param 0)) T, mx)) fixes) |> snd, [])
-  | declare_int_elem (ctxt, _) = (ctxt, []);
-
-fun declare_ext_elem prep_vars (ctxt, Fixes fixes) =
-      let val (vars, _) = prep_vars fixes ctxt
-      in (ctxt |> ProofContext.add_fixes_i vars |> snd, []) end
-  | declare_ext_elem prep_vars (ctxt, Constrains csts) =
-      let val (_, ctxt') = prep_vars (map (fn (x, T) => (x, SOME T, NoSyn)) csts) ctxt
-      in (ctxt', []) end
-  | declare_ext_elem _ (ctxt, Assumes asms) = (ctxt, map #2 asms)
-  | declare_ext_elem _ (ctxt, Defines defs) = (ctxt, map (fn (_, (t, ps)) => [(t, ps)]) defs)
-  | declare_ext_elem _ (ctxt, Notes facts) = (ctxt, []);
-
-fun declare_elems prep_vars (ctxt, (((name, ps), Assumed _), elems)) =
-    let val (ctxt', propps) =
-      (case elems of
-        Int es => foldl_map declare_int_elem (ctxt, es)
-      | Ext e => foldl_map (declare_ext_elem prep_vars) (ctxt, [e]))
-      handle ERROR msg => err_in_locale ctxt msg [(name, map fst ps)]
-    in (ctxt', propps) end
-  | declare_elems _ (ctxt, ((_, Derived _), elems)) = (ctxt, []);
-
-in
-
-(* The Plan:
-- tell context about parameters and their syntax (possibly also types)
-- add declarations to context
-- retrieve parameter types
-*)
-
-end; (* local *)
-
-
 (* propositions and bindings *)
 
 (* flatten (ctxt, prep_expr) ((ids, syn), expr)
    normalises expr (which is either a locale
    expression or a single context element) wrt.
    to the list ids of already accumulated identifiers.
-   It returns (ids', syn', elemss) where ids' is an extension of ids
+   It returns ((ids', syn'), elemss) where ids' is an extension of ids
    with identifiers generated for expr, and elemss is the list of
    context elements generated from expr.
    syn and syn' are symtabs mapping parameter names to their syntax.  syn'
@@ -977,7 +1019,7 @@
          merge_syntax ctxt ids'
            (syn, Symtab.make (map (fn fx => (#1 fx, #3 fx)) fixes))
            handle Symtab.DUPS xs => err_in_locale ctxt
-             ("Conflicting syntax for parameters: " ^ commas_quote xs)
+             ("Conflicting syntax (3) for parameters: " ^ commas_quote xs)
              (map #1 ids')),
          [((("", map (rpair NONE o #1) fixes), Assumed []), Ext (Fixes fixes))])
       end
@@ -1297,9 +1339,13 @@
 fun parameters_of_expr thy expr =
   let
     val ctxt = ProofContext.init thy;
+    val pts = params_of_expr ctxt [] (intern_expr thy expr)
+        ([], Symtab.empty, Symtab.empty);
+    val raw_params_elemss = make_raw_params_elemss pts;
     val ((_, syn), raw_elemss) = flatten (ctxt, intern_expr thy)
         (([], Symtab.empty), Expr expr);
-    val ((parms, _, _), _) = read_elemss false ctxt [] raw_elemss [];
+    val ((parms, _, _), _) =
+        read_elemss false ctxt [] (raw_params_elemss @ raw_elemss) [];
   in map (fn p as (n, _) => (p, Symtab.lookup syn n |> the)) parms end;
 
 fun local_asms_of thy name =
@@ -1320,24 +1366,43 @@
   let
     val thy = ProofContext.theory_of context;
 
-    val ((import_ids, import_syn), raw_import_elemss) =
+    val (import_params, import_tenv, import_syn) =
+      params_of_expr context fixed_params (prep_expr thy import)
+        ([], Symtab.empty, Symtab.empty);
+    val includes = map_filter (fn Expr e => SOME e | Elem _ => NONE) elements;
+    val (incl_params, incl_tenv, incl_syn) = fold (params_of_expr context fixed_params)
+      (map (prep_expr thy) includes) (import_params, import_tenv, import_syn);
+
+    val ((import_ids, _), raw_import_elemss) =
       flatten (context, prep_expr thy) (([], Symtab.empty), Expr import);
     (* CB: normalise "includes" among elements *)
     val ((ids, syn), raw_elemsss) = foldl_map (flatten (context, prep_expr thy))
-      ((import_ids, import_syn), elements);
+      ((import_ids, incl_syn), elements);
 
     val raw_elemss = flat raw_elemsss;
     (* CB: raw_import_elemss @ raw_elemss is the normalised list of
        context elements obtained from import and elements. *)
+    (* Now additional elements for parameters are inserted. *)
+    val import_params_ids = make_params_ids import_params;
+    val incl_params_ids =
+        make_params_ids (incl_params \\ import_params);
+    val raw_import_params_elemss =
+        make_raw_params_elemss (import_params, incl_tenv, incl_syn);
+    val raw_incl_params_elemss =
+        make_raw_params_elemss (incl_params \\ import_params, incl_tenv, incl_syn);
     val ((parms, all_elemss, concl), (spec, (_, _, defs))) = prep_elemss do_close
-      context fixed_params (raw_import_elemss @ raw_elemss) raw_concl;
+      context fixed_params
+      (raw_import_params_elemss @ raw_import_elemss @ raw_incl_params_elemss @ raw_elemss) raw_concl;
+
     (* replace extended ids (for axioms) by ids *)
+    val (import_ids', incl_ids) = chop (length import_ids) ids;
+    val add_ids = import_params_ids @ import_ids' @ incl_params_ids @ incl_ids;
     val all_elemss' = map (fn (((_, ps), _), (((n, ps'), mode), elems)) =>
         (((n, map (fn p => (p, (the o AList.lookup (op =) ps') p)) ps), mode), elems))
-      (ids ~~ all_elemss);
+      (add_ids ~~ all_elemss);
+    (* CB: all_elemss and parms contain the correct parameter types *)
 
-    (* CB: all_elemss and parms contain the correct parameter types *)
-    val (ps, qs) = chop (length raw_import_elemss) all_elemss';
+    val (ps, qs) = chop (length raw_import_params_elemss + length raw_import_elemss) all_elemss';
     val (import_ctxt, (import_elemss, _)) =
       activate_facts prep_facts (context, ps);
 
@@ -1348,7 +1413,8 @@
                            | ((_, Derived _), _) => []) qs);
     val cstmt = map (cterm_of thy) stmt;
   in
-    ((((import_ctxt, import_elemss), (ctxt, elemss, syn)), (parms, spec, defs)), (cstmt, concl))
+    ((((import_ctxt, import_elemss), (ctxt, elemss, syn)),
+      (parms, spec, defs)), (cstmt, concl))
   end;
 
 fun prep_statement prep_locale prep_ctxt raw_locale elems concl ctxt =
@@ -1716,14 +1782,14 @@
     val export = ProofContext.export_view predicate_statement ctxt thy_ctxt;
     val facts' = facts |> map (fn (a, ths) => ((a, []), [(map export ths, [])]));
     val elems' = maps #2 (filter (equal "" o #1 o #1) elemss');
-
+    val elems'' = map_filter (fn (Fixes _) => NONE | e => SOME e) elems';
     val thy' = pred_thy
       |> PureThy.note_thmss_qualified "" bname facts' |> snd
       |> declare_locale name
       |> put_locale name
        {predicate = predicate,
         import = import,
-        elems = map (fn e => (e, stamp ())) elems',
+        elems = map (fn e => (e, stamp ())) elems'',
         params = params_of elemss' |> map (fn (x, SOME T) => ((x, T), the (Symtab.lookup syn x))),
         lparams = map #1 (params_of body_elemss),
         term_syntax = [],
@@ -1918,10 +1984,14 @@
     val thy = ProofContext.theory_of ctxt;
 
     val ctxt' = ctxt |> ProofContext.theory_of |> ProofContext.init;
+    val pts = params_of_expr ctxt' [] (intern_expr thy expr)
+          ([], Symtab.empty, Symtab.empty);
+    val params_ids = make_params_ids (#1 pts);
+    val raw_params_elemss = make_raw_params_elemss pts;
     val ((ids, _), raw_elemss) = flatten (ctxt', intern_expr thy)
           (([], Symtab.empty), Expr expr);
     val ((parms, all_elemss, _), (_, (_, defs, _))) =
-          read_elemss false ctxt' [] raw_elemss [];
+          read_elemss false ctxt' [] (raw_params_elemss @ raw_elemss) [];
 
     (** compute instantiation **)
 
@@ -1975,11 +2045,13 @@
     val insts = (tinst, inst);
     (* Note: insts contain no vars. *)
 
+
     (** compute proof obligations **)
 
     (* restore "small" ids *)
     val ids' = map (fn ((n, ps), (_, mode)) =>
-          ((n, map (fn p => Free (p, (the o AList.lookup (op =) parms) p)) ps), mode)) ids;
+          ((n, map (fn p => Free (p, (the o AList.lookup (op =) parms) p)) ps), mode))
+        (params_ids @ ids);
     (* instantiate ids and elements *)
     val inst_elemss = (ids' ~~ all_elemss) |> map (fn (((n, ps), _), ((_, mode), elems)) =>
       ((n, map (Element.inst_term insts) ps),
--- a/src/Pure/Pure.thy	Tue Jun 06 09:28:24 2006 +0200
+++ b/src/Pure/Pure.thy	Tue Jun 06 10:05:57 2006 +0200
@@ -1,7 +1,7 @@
 (*  Title:      Pure/Pure.thy
     ID:         $Id$
 
-The actual Pure theory.
+The Pure theory.
 *)
 
 header {* The Pure theory *}
@@ -9,7 +9,7 @@
 theory Pure
 imports ProtoPure
 begin
-
+ML{*set Toplevel.debug*}
 setup  -- {* Common setup of internal components *}