src/Pure/locale.ML
author paulson
Mon Dec 07 18:26:25 1998 +0100 (1998-12-07)
changeset 6019 0e55c2fb2ebb
parent 5782 7559f116cb10
child 6022 259e4f2114e1
permissions -rw-r--r--
tidying
wenzelm@5244
     1
(*  Title:      Pure/locale.ML
wenzelm@5244
     2
    ID:         $Id$
wenzelm@5244
     3
    Author:     Florian Kammueller, University of Cambridge
wenzelm@5244
     4
paulson@5782
     5
Locales. The theory section 'locale' declarings constants, assumptions and
paulson@5782
     6
definitions that have local scope.  Typical form is
paulson@5782
     7
paulson@5782
     8
    locale Locale_name =
paulson@5782
     9
      fixes   (*variables that are fixed in the locale's scope*)
paulson@5782
    10
	v :: T
paulson@5782
    11
      assumes (*meta-hypothesis that hold in the locale*)
paulson@5782
    12
	Asm_name "meta-formula"  
paulson@5782
    13
      defines (*local definitions of fixed variables in terms of others*)
paulson@5782
    14
	v_def "v x == ...x..."
wenzelm@5244
    15
wenzelm@5244
    16
TODO:
paulson@5782
    17
  - operations on locales: extension, renaming.
wenzelm@5244
    18
*)
wenzelm@5244
    19
wenzelm@5244
    20
signature BASIC_LOCALE =
wenzelm@5244
    21
sig
wenzelm@5244
    22
  val print_locales: theory -> unit
wenzelm@5244
    23
  val print_goals: int -> thm -> unit
wenzelm@5729
    24
  val print_goals_marker: string -> int -> thm -> unit
wenzelm@5244
    25
end;
wenzelm@5244
    26
wenzelm@5244
    27
signature LOCALE =
wenzelm@5244
    28
sig
wenzelm@5244
    29
  include BASIC_LOCALE
wenzelm@5244
    30
  val get_thm: theory -> xstring -> thm
wenzelm@5244
    31
  val get_thms: theory -> xstring -> thm list
wenzelm@5244
    32
  type locale
wenzelm@5244
    33
  val add_locale: bstring -> (string * string * mixfix) list ->
wenzelm@5244
    34
    (string * string) list -> (string * string) list -> theory -> theory
wenzelm@5244
    35
  val add_locale_i: bstring -> (string * typ * mixfix) list ->
wenzelm@5244
    36
    (string * term) list -> (string * term) list -> theory -> theory
wenzelm@5244
    37
  val open_locale: xstring -> theory -> theory
wenzelm@5244
    38
  val close_locale: theory -> theory
wenzelm@5244
    39
  val in_locale: term list -> Sign.sg -> bool
wenzelm@5244
    40
  val is_open_loc_sg: Sign.sg -> bool
wenzelm@5244
    41
  val is_open_loc: theory -> bool
wenzelm@5244
    42
  val read_cterm: Sign.sg -> string * typ -> cterm
wenzelm@5244
    43
  val get_scope: theory -> (string * locale) list
wenzelm@5244
    44
  val get_scope_sg: Sign.sg -> (string * locale) list
wenzelm@5244
    45
  val collect_consts: Sign.sg -> string list
wenzelm@5244
    46
  val setup: (theory -> theory) list
wenzelm@5244
    47
end;
wenzelm@5244
    48
wenzelm@5244
    49
structure Locale: LOCALE =
wenzelm@5244
    50
struct
wenzelm@5244
    51
wenzelm@5244
    52
wenzelm@5244
    53
(** type locale **)
wenzelm@5244
    54
wenzelm@5244
    55
type locale =
wenzelm@5244
    56
 {consts: (string * typ) list,
wenzelm@5244
    57
  nosyn: string list,
wenzelm@5244
    58
  rules: (string * term) list,
wenzelm@5244
    59
  defs: (string * term) list,
wenzelm@5244
    60
  thms: (string * thm) list,
wenzelm@5244
    61
  defaults: (string * sort) list * (string * typ) list * string list};
wenzelm@5244
    62
wenzelm@5244
    63
fun make_locale consts nosyn rules defs thms defaults =
wenzelm@5244
    64
  {consts = consts, nosyn = nosyn, rules = rules, defs = defs,
wenzelm@5244
    65
    thms = thms, defaults = defaults}: locale;
wenzelm@5244
    66
wenzelm@5244
    67
fun pretty_locale sg (name, {consts, rules, defs, nosyn = _, thms = _, defaults = _}) =
wenzelm@5244
    68
  let
wenzelm@5244
    69
    val prt_typ = Pretty.quote o Sign.pretty_typ sg;
wenzelm@5244
    70
    val prt_term = Pretty.quote o Sign.pretty_term sg;
wenzelm@5244
    71
wenzelm@5244
    72
    fun pretty_const (c, T) = Pretty.block
wenzelm@5244
    73
      [Pretty.str (c ^ " ::"), Pretty.brk 1, prt_typ T];
wenzelm@5244
    74
wenzelm@5244
    75
    fun pretty_axiom (a, t) = Pretty.block
wenzelm@5244
    76
      [Pretty.str (a ^ ":"), Pretty.brk 1, prt_term t];
wenzelm@5244
    77
  in
wenzelm@5244
    78
    Pretty.big_list (name ^ " =")
wenzelm@5244
    79
     [Pretty.big_list "consts:" (map pretty_const consts),
wenzelm@5244
    80
      Pretty.big_list "rules:" (map pretty_axiom rules),
wenzelm@5244
    81
      Pretty.big_list "defs:" (map pretty_axiom defs)]
wenzelm@5244
    82
  end;
wenzelm@5244
    83
wenzelm@5244
    84
wenzelm@5244
    85
wenzelm@5244
    86
(** theory data **)
wenzelm@5244
    87
wenzelm@5244
    88
(* data kind 'Pure/locales' *)
wenzelm@5244
    89
wenzelm@5244
    90
type locale_data =
wenzelm@5244
    91
  {space: NameSpace.T,
wenzelm@5244
    92
    locales: locale Symtab.table,
wenzelm@5244
    93
    scope: (string * locale) list ref};
wenzelm@5244
    94
wenzelm@5244
    95
fun make_locale_data space locales scope =
wenzelm@5244
    96
  {space = space, locales = locales, scope = scope}: locale_data;
wenzelm@5244
    97
wenzelm@5244
    98
structure LocalesArgs =
wenzelm@5244
    99
struct
wenzelm@5244
   100
  val name = "Pure/locales";
wenzelm@5244
   101
  type T = locale_data;
wenzelm@5244
   102
wenzelm@5244
   103
  val empty = make_locale_data NameSpace.empty Symtab.empty (ref []);
wenzelm@5244
   104
  fun prep_ext {space, locales, scope = _} = make_locale_data space locales (ref []);
wenzelm@5244
   105
  fun merge ({space = space1, locales = locales1, scope = _},
wenzelm@5244
   106
    {space = space2, locales = locales2, scope = _}) =
wenzelm@5244
   107
      make_locale_data (NameSpace.merge (space1, space2))
wenzelm@5244
   108
        (Symtab.merge (K true) (locales1, locales2))
wenzelm@5244
   109
        (ref []);
wenzelm@5244
   110
wenzelm@5244
   111
  fun print sg {space, locales, scope} =
wenzelm@5244
   112
    let
wenzelm@5244
   113
      fun extrn name =
wenzelm@5244
   114
        if ! long_names then name else NameSpace.extern space name;
wenzelm@5244
   115
      val locs = map (apfst extrn) (Symtab.dest locales);
wenzelm@5244
   116
      val scope_names = rev (map (extrn o fst) (! scope));
wenzelm@5244
   117
    in
wenzelm@5244
   118
      Pretty.writeln (Display.pretty_name_space ("locale name space", space));
wenzelm@5244
   119
      Pretty.writeln (Pretty.big_list "locales:" (map (pretty_locale sg) locs));
wenzelm@5244
   120
      Pretty.writeln (Pretty.strs ("current scope:" :: scope_names))
wenzelm@5244
   121
    end;
wenzelm@5244
   122
end;
wenzelm@5244
   123
wenzelm@5244
   124
wenzelm@5244
   125
structure LocalesData = TheoryDataFun(LocalesArgs);
wenzelm@5244
   126
val print_locales = LocalesData.print;
wenzelm@5244
   127
wenzelm@5244
   128
wenzelm@5244
   129
(* access locales *)
wenzelm@5244
   130
wenzelm@5244
   131
fun get_locale_sg sg name = Symtab.lookup (#locales (LocalesData.get_sg sg), name);
wenzelm@5244
   132
wenzelm@5244
   133
val get_locale = get_locale_sg o Theory.sign_of;
wenzelm@5244
   134
wenzelm@5244
   135
fun put_locale (name, locale) thy =
wenzelm@5244
   136
  let
wenzelm@5244
   137
    val {space, locales, scope} = LocalesData.get thy;
wenzelm@5244
   138
    val space' = NameSpace.extend (space, [name]);
wenzelm@5244
   139
    val locales' = Symtab.update ((name, locale), locales);
wenzelm@5244
   140
  in thy |> LocalesData.put (make_locale_data space' locales' scope) end;
wenzelm@5244
   141
wenzelm@5244
   142
fun lookup_locale thy xname =
wenzelm@5244
   143
  let
wenzelm@5244
   144
    val {space, locales, ...} = LocalesData.get thy;
wenzelm@5244
   145
    val name = NameSpace.intern space xname;
wenzelm@5244
   146
  in apsome (pair name) (get_locale thy name) end;
wenzelm@5244
   147
wenzelm@5244
   148
wenzelm@5244
   149
(* access scope *)
wenzelm@5244
   150
wenzelm@5244
   151
val get_scope_sg = ! o #scope o LocalesData.get_sg;
wenzelm@5244
   152
wenzelm@5244
   153
val get_scope = get_scope_sg o Theory.sign_of;
wenzelm@5244
   154
wenzelm@5244
   155
fun change_scope f thy =
wenzelm@5244
   156
  let val {scope, ...} = LocalesData.get thy
wenzelm@5244
   157
  in scope := f (! scope) end;
wenzelm@5244
   158
wenzelm@5244
   159
wenzelm@5244
   160
wenzelm@5244
   161
(** scope operations **)
wenzelm@5244
   162
wenzelm@5244
   163
(* change scope *)
wenzelm@5244
   164
wenzelm@5244
   165
fun the_locale thy xname =
wenzelm@5244
   166
  (case lookup_locale thy xname of
wenzelm@5244
   167
    Some loc => loc
wenzelm@5244
   168
  | None => error ("Unknown locale " ^ quote xname));
wenzelm@5244
   169
wenzelm@5244
   170
fun open_locale xname thy =
wenzelm@5244
   171
  (change_scope (cons (the_locale thy xname)) thy; thy);
wenzelm@5244
   172
wenzelm@5244
   173
fun pop_locale [] = error "Currently no open locales"
wenzelm@5244
   174
  | pop_locale (_ :: locs) = locs;
wenzelm@5244
   175
wenzelm@5244
   176
fun close_locale thy = (change_scope pop_locale thy; thy);
wenzelm@5244
   177
wenzelm@5244
   178
wenzelm@5244
   179
(** functions for goals.ML **)
wenzelm@5244
   180
wenzelm@5244
   181
(* in_locale: check if hyps (: term list) of a proof are contained in the
wenzelm@5244
   182
   (current) scope. This function is needed in prepare_proof. It needs to
wenzelm@5244
   183
   refer to the signature, because theory is not available in prepare_proof. *)
wenzelm@5244
   184
wenzelm@5244
   185
fun in_locale hyps sg =
wenzelm@5244
   186
    let val cur_sc = get_scope_sg sg;
wenzelm@5244
   187
        val rule_lists = map (#rules o snd) cur_sc;
wenzelm@5244
   188
        val def_lists = map (#defs o snd) cur_sc;
wenzelm@5244
   189
        val rules = map snd (foldr (op union) (rule_lists, []));
wenzelm@5244
   190
        val defs = map snd (foldr (op union) (def_lists, []));
wenzelm@5244
   191
        val defnrules = rules @ defs;
wenzelm@5244
   192
    in
wenzelm@5244
   193
        hyps subset defnrules
wenzelm@5244
   194
    end;
wenzelm@5244
   195
wenzelm@5244
   196
wenzelm@5244
   197
(* is_open_loc: check if any locale is open, i.e. in the scope of the current thy *)
wenzelm@5244
   198
fun is_open_loc_sg sign =
wenzelm@5244
   199
    let val cur_sc = get_scope_sg sign
wenzelm@5244
   200
    in not(null(cur_sc)) end;
wenzelm@5244
   201
wenzelm@5244
   202
val is_open_loc = is_open_loc_sg o Theory.sign_of;
wenzelm@5244
   203
wenzelm@5244
   204
wenzelm@5244
   205
(* get theorems *)
wenzelm@5244
   206
wenzelm@5244
   207
fun get_thm_locale name ((_, {thms, ...}: locale)) = assoc (thms, name);
wenzelm@5244
   208
wenzelm@5244
   209
fun get_thmx f get thy name =
wenzelm@5244
   210
  (case get_first (get_thm_locale name) (get_scope thy) of
wenzelm@5244
   211
    Some thm => f thm
wenzelm@5244
   212
  | None => get thy name);
wenzelm@5244
   213
wenzelm@5244
   214
val get_thm = get_thmx I PureThy.get_thm;
wenzelm@5244
   215
wenzelm@5244
   216
val get_thms = get_thmx (fn x => [x]) PureThy.get_thms;
wenzelm@5244
   217
wenzelm@5244
   218
wenzelm@5244
   219
wenzelm@5244
   220
(** define locales **)
wenzelm@5244
   221
wenzelm@5244
   222
(* prepare types *)
wenzelm@5244
   223
wenzelm@5244
   224
fun read_typ sg (envT, s) =
wenzelm@5244
   225
  let
wenzelm@5244
   226
    fun def_sort (x, ~1) = assoc (envT, x)
wenzelm@5244
   227
      | def_sort _ = None;
wenzelm@5244
   228
    val T = Type.no_tvars (Sign.read_typ (sg, def_sort) s) handle TYPE (msg, _, _) => error msg;
wenzelm@5244
   229
  in (Term.add_typ_tfrees (T, envT), T) end;
wenzelm@5244
   230
wenzelm@5244
   231
fun cert_typ sg (envT, raw_T) =
wenzelm@5244
   232
  let val T = Type.no_tvars (Sign.certify_typ sg raw_T) handle TYPE (msg, _, _) => error msg
wenzelm@5244
   233
  in (Term.add_typ_tfrees (T, envT), T) end;
wenzelm@5244
   234
wenzelm@5244
   235
wenzelm@5244
   236
(* prepare props *)
wenzelm@5244
   237
wenzelm@5244
   238
val add_frees = foldl_aterms (fn (vs, Free v) => v ins vs | (vs, _) => vs);
wenzelm@5244
   239
wenzelm@5244
   240
fun enter_term t (envS, envT, used) =
wenzelm@5244
   241
  (Term.add_term_tfrees (t, envS), add_frees (envT, t), Term.add_term_tfree_names (t, used));
wenzelm@5244
   242
wenzelm@5244
   243
fun read_axm sg ((envS, envT, used), (name, s)) =
wenzelm@5244
   244
  let
wenzelm@5244
   245
    fun def_sort (x, ~1) = assoc (envS, x)
wenzelm@5244
   246
      | def_sort _ = None;
wenzelm@5244
   247
    fun def_type (x, ~1) = assoc (envT, x)
wenzelm@5244
   248
      | def_type _ = None;
wenzelm@5244
   249
    val (_, t) = Theory.read_def_axm (sg, def_type, def_sort) used (name, s);
wenzelm@5244
   250
  in
wenzelm@5244
   251
    (enter_term t (envS, envT, used), t)
wenzelm@5244
   252
  end;
wenzelm@5244
   253
wenzelm@5244
   254
wenzelm@5244
   255
fun cert_axm sg ((envS, envT, used), (name, raw_t)) =
wenzelm@5244
   256
  let val (_, t) = Theory.cert_axm sg (name, raw_t)
wenzelm@5244
   257
  in (enter_term t (envS, envT, used), t) end;
wenzelm@5244
   258
wenzelm@5244
   259
wenzelm@5244
   260
(* Locale.read_cterm: read in a string as a certified term, and respect the bindings
wenzelm@5244
   261
   that already exist for subterms. If no locale is open, this function is equal to
wenzelm@5244
   262
   Thm.read_cterm  *)
wenzelm@5244
   263
wenzelm@5244
   264
fun read_cterm sign =
wenzelm@5244
   265
    let val cur_sc = get_scope_sg sign;
wenzelm@5244
   266
        val defaults = map (#defaults o snd) cur_sc;
wenzelm@5244
   267
        val envS = flat (map #1 defaults);
wenzelm@5244
   268
        val envT = flat (map #2 defaults);
wenzelm@5244
   269
        val used = flat (map #3 defaults);
wenzelm@5244
   270
        fun def_sort (x, ~1) = assoc (envS, x)
wenzelm@5244
   271
          | def_sort _ = None;
wenzelm@5244
   272
        fun def_type (x, ~1) = assoc (envT, x)
wenzelm@5244
   273
          | def_type _ = None;
wenzelm@5244
   274
    in (if (is_open_loc_sg sign)
wenzelm@5244
   275
        then (#1 o read_def_cterm (sign, def_type, def_sort) used true)
wenzelm@5244
   276
        else Thm.read_cterm sign)
wenzelm@5244
   277
    end;
wenzelm@5244
   278
wenzelm@5244
   279
(* basic functions needed for definitions and display *)
wenzelm@5244
   280
(* collect all locale constants of a scope, i.e. a list of locales *)
wenzelm@5244
   281
fun collect_consts sg =
wenzelm@5244
   282
    let val cur_sc = get_scope_sg sg;
wenzelm@5244
   283
        val locale_list = map snd cur_sc;
wenzelm@5244
   284
        val const_list = flat (map #consts locale_list)
wenzelm@5244
   285
    in map fst const_list end;
wenzelm@5244
   286
wenzelm@5244
   287
(* filter out the Free's in a term *)
wenzelm@5244
   288
fun list_frees t =
wenzelm@5244
   289
    case t of Const(c,T) => []
wenzelm@5244
   290
  | Var(v,T) => []
wenzelm@5244
   291
  | Free(v,T)=> [Free(v,T)]
wenzelm@5244
   292
  | Bound x  => []
wenzelm@5244
   293
  | Abs(a,T,u) => list_frees u
wenzelm@5244
   294
  | t1 $ t2  => (list_frees t1)  @ (list_frees t2);
wenzelm@5244
   295
wenzelm@5244
   296
(* filter out all Free's in a term that are not contained
wenzelm@5244
   297
   in a list of strings. Used to prepare definitions. The list of strings
wenzelm@5244
   298
   will be the consts of the scope. We filter out the "free" Free's to be
wenzelm@5244
   299
   able to bind them *)
wenzelm@5244
   300
fun difflist term clist =
wenzelm@5244
   301
    let val flist = list_frees term;
wenzelm@5244
   302
        fun builddiff [] sl = []
wenzelm@5244
   303
          | builddiff (t :: tl) sl =
wenzelm@5244
   304
            let val Free(v,T) = t
wenzelm@5244
   305
            in
wenzelm@5244
   306
                if (v mem sl)
wenzelm@5244
   307
                then builddiff tl sl
wenzelm@5244
   308
                else t :: (builddiff tl sl)
wenzelm@5244
   309
            end;
wenzelm@5244
   310
    in distinct(builddiff flist clist) end;
wenzelm@5244
   311
paulson@5782
   312
(* Bind a term with !! over a list of "free" Free's.
paulson@5782
   313
   To enable definitions like x + y == .... (without quantifier).
paulson@5782
   314
   Complications, because x and y have to be removed from defaults *)
paulson@5782
   315
fun abs_over_free clist ((defaults: (string * sort) list * (string * typ) list * string list), (s, term)) =
wenzelm@5244
   316
    let val diffl = rev(difflist term clist);
wenzelm@5244
   317
        fun abs_o (t, (x as Free(v,T))) = all(T) $ Abs(v, T, abstract_over (x,t))
wenzelm@5244
   318
          | abs_o (_ , _) = error ("Can't be: abs_over_free");
paulson@5782
   319
        val diffl' = map (fn (Free (s, T)) => s) diffl;
paulson@5782
   320
        val defaults' = (#1 defaults, filter (fn x => not((fst x) mem diffl')) (#2 defaults), #3 defaults)
paulson@5782
   321
    in (defaults', (s, foldl abs_o (term, diffl))) end;
wenzelm@5244
   322
wenzelm@5244
   323
(* assume a definition, i.e assume the cterm of a definiton term and then eliminate
wenzelm@5244
   324
   the binding !!, so that the def can be applied as rewrite. The meta hyp will still contain !! *)
paulson@5782
   325
fun prep_hyps clist sg = forall_elim_vars(0) o Thm.assume o (Thm.cterm_of sg);
wenzelm@5244
   326
wenzelm@5244
   327
wenzelm@5244
   328
(* concrete syntax *)
wenzelm@5244
   329
wenzelm@5244
   330
fun mark_syn c = "\\<^locale>" ^ c;
wenzelm@5244
   331
wenzelm@5244
   332
fun mk_loc_tr c ts = list_comb (Free (c, dummyT), ts);
wenzelm@5244
   333
wenzelm@5244
   334
wenzelm@5244
   335
(* add_locale *)
wenzelm@5244
   336
wenzelm@5244
   337
fun gen_add_locale prep_typ prep_term bname raw_consts raw_rules raw_defs thy =
wenzelm@5244
   338
  let val sign = Theory.sign_of thy;
wenzelm@5244
   339
wenzelm@5244
   340
    val name = Sign.full_name sign bname;
wenzelm@5244
   341
wenzelm@5244
   342
wenzelm@5244
   343
    (* prepare locale consts *)
wenzelm@5244
   344
wenzelm@5244
   345
    fun prep_const (envS, (raw_c, raw_T, raw_mx)) =
wenzelm@5244
   346
      let
wenzelm@5244
   347
        val c = Syntax.const_name raw_c raw_mx;
wenzelm@5244
   348
        val c_syn = mark_syn c;
wenzelm@5244
   349
        val mx = Syntax.fix_mixfix raw_c raw_mx;
wenzelm@5244
   350
        val (envS', T) = prep_typ sign (envS, raw_T) handle ERROR =>
wenzelm@5244
   351
          error ("The error(s) above occured in locale constant " ^ quote c);
wenzelm@5244
   352
        val trfun = if mx = Syntax.NoSyn then None else Some (c_syn, mk_loc_tr c);
wenzelm@5244
   353
      in (envS', ((c, T), (c_syn, T, mx), trfun)) end;
wenzelm@5244
   354
wenzelm@5244
   355
    val (envS0, loc_consts_syn) = foldl_map prep_const ([], raw_consts);
wenzelm@5244
   356
    val loc_consts = map #1 loc_consts_syn;
wenzelm@5244
   357
    val loc_syn = map #2 loc_consts_syn;
wenzelm@5244
   358
    val nosyn = map (#1 o #1) (filter (fn x => (#3(#2 x)) = NoSyn) loc_consts_syn);
wenzelm@5244
   359
    val loc_trfuns = mapfilter #3 loc_consts_syn;
wenzelm@5244
   360
wenzelm@5244
   361
wenzelm@5244
   362
    (* 1st stage: syntax_thy *)
wenzelm@5244
   363
wenzelm@5244
   364
    val syntax_thy =
wenzelm@5244
   365
      thy
wenzelm@5244
   366
      |> Theory.add_modesyntax_i ("", true) loc_syn
wenzelm@5244
   367
      |> Theory.add_trfuns ([], loc_trfuns, [], []);
wenzelm@5244
   368
wenzelm@5244
   369
    val syntax_sign = Theory.sign_of syntax_thy;
wenzelm@5244
   370
wenzelm@5244
   371
wenzelm@5244
   372
    (* prepare rules and defs *)
wenzelm@5244
   373
wenzelm@5244
   374
    fun prep_axiom (env, (a, raw_t)) =
wenzelm@5244
   375
      let
wenzelm@5244
   376
        val (env', t) = prep_term syntax_sign (env, (a, raw_t)) handle ERROR =>
wenzelm@5244
   377
          error ("The error(s) above occured in locale rule / definition " ^ quote a);
wenzelm@5244
   378
      in (env', (a, t)) end;
wenzelm@5244
   379
wenzelm@5244
   380
    val ((envS1, envT1, used1), loc_rules) =
wenzelm@5244
   381
      foldl_map prep_axiom ((envS0, loc_consts, map fst envS0), raw_rules);
wenzelm@5244
   382
    val (defaults, loc_defs) = foldl_map prep_axiom ((envS1, envT1, used1), raw_defs);
wenzelm@5244
   383
wenzelm@5244
   384
    val old_loc_consts = collect_consts syntax_sign;
wenzelm@5244
   385
    val new_loc_consts = (map #1 loc_consts);
wenzelm@5244
   386
    val all_loc_consts = old_loc_consts @ new_loc_consts;
wenzelm@5244
   387
paulson@5782
   388
    val (defaults, loc_defs_terms) = foldl_map (abs_over_free all_loc_consts) (defaults, loc_defs);
paulson@5782
   389
    val loc_defs_thms = map (apsnd (prep_hyps (map #1 loc_consts) syntax_sign)) loc_defs_terms;
paulson@5782
   390
    val (defaults, loc_thms_terms) = foldl_map (abs_over_free all_loc_consts) (defaults, loc_rules);
paulson@5782
   391
    val loc_thms = (map (apsnd (prep_hyps (map #1 loc_consts) syntax_sign)) (loc_thms_terms)) 
paulson@5782
   392
                   @ loc_defs_thms;
wenzelm@5244
   393
wenzelm@5244
   394
wenzelm@5244
   395
    (* error messages *)        (* FIXME improve *)
wenzelm@5244
   396
wenzelm@5244
   397
    val err_dup_locale =
wenzelm@5244
   398
      if is_none (get_locale thy name) then []
wenzelm@5244
   399
      else ["Duplicate definition of locale " ^ quote name];
wenzelm@5244
   400
paulson@5782
   401
    (* check if definientes are locale constants (in the same locale, so no redefining!) *)
paulson@5749
   402
    val err_def_head =
paulson@5749
   403
      let fun peal_appl t = 
paulson@5749
   404
            case t of 
paulson@5749
   405
                 t1 $ t2 => peal_appl t1
paulson@5749
   406
               | Free(t) => t
paulson@5749
   407
               | _ => error ("a bad locale definition");
paulson@5749
   408
	  fun lhs (_, Const ("==" , _) $  d1 $ d2) = peal_appl d1
paulson@5749
   409
	    | lhs _ = error ("an illegal definition");
paulson@5749
   410
          val defs = map lhs loc_defs;
paulson@5749
   411
          val check = defs subset loc_consts
paulson@5749
   412
      in if check then [] 
paulson@5749
   413
         else ["defined item not declared fixed in locale " ^ quote name]
paulson@5749
   414
      end; 
paulson@5749
   415
paulson@5782
   416
    (* check that variables on rhs of definitions are either fixed or on lhs *)
paulson@5782
   417
    val err_var_rhs = 
paulson@5782
   418
      let fun compare_var_sides (t, (_, Const ("==", _) $ d1 $ d2)) = 
paulson@5782
   419
            let val varl1 = difflist d1 all_loc_consts;
paulson@5782
   420
                val varl2 = difflist d2 all_loc_consts
paulson@5782
   421
            in t andalso (varl2 subset varl1)
paulson@5782
   422
            end
paulson@5782
   423
            | compare_var_sides (_,_) = error ("an illegal definition");
paulson@5782
   424
          val check = foldl compare_var_sides (true, loc_defs)
paulson@5782
   425
      in if check then []
paulson@5782
   426
         else ["nonfixed variable on right hand side of a locale definition in locale" ^ quote name]
paulson@5782
   427
      end;
paulson@5782
   428
paulson@5782
   429
    val errs = err_dup_locale @ err_def_head @ err_var_rhs;
wenzelm@5244
   430
  in
wenzelm@5244
   431
    if null errs then ()
wenzelm@5244
   432
    else error (cat_lines errs);
wenzelm@5244
   433
wenzelm@5244
   434
    syntax_thy
paulson@5749
   435
    |> put_locale (name, 
paulson@5782
   436
		   make_locale loc_consts nosyn loc_thms_terms loc_defs_terms
paulson@5749
   437
		               loc_thms defaults)
wenzelm@5244
   438
  end;
wenzelm@5244
   439
wenzelm@5244
   440
wenzelm@5244
   441
val add_locale = gen_add_locale read_typ read_axm;
wenzelm@5244
   442
val add_locale_i = gen_add_locale cert_typ cert_axm;
wenzelm@5244
   443
wenzelm@5244
   444
(** print functions **)
wenzelm@5244
   445
(* idea: substitute all locale contants (Free's) that are syntactical by their
wenzelm@5244
   446
         "real" constant representation (i.e. \\<^locale>constname).
wenzelm@5244
   447
   - function const_ssubst does this substitution
wenzelm@5244
   448
   - function Locale.pretty_term:
wenzelm@5244
   449
             if locale is open then do this substitution & then call Sign.pretty_term
wenzelm@5244
   450
             else call Sign.pretty_term
wenzelm@5244
   451
*)
wenzelm@5244
   452
(* substitutes all Free variables s in t by Const's s *)
wenzelm@5244
   453
fun const_ssubst t s =
wenzelm@5244
   454
    case t  of
wenzelm@5244
   455
        Free(v,T) => if v = s then Const("\\<^locale>" ^ s,T) else Free(v,T)
wenzelm@5244
   456
      | Const(c,T) => Const(c,T)
wenzelm@5244
   457
      | Var(v,T) => Var(v,T)
wenzelm@5244
   458
      | Bound x  => Bound x
wenzelm@5244
   459
      | Abs(a,T,u) => Abs(a,T, const_ssubst u s)
wenzelm@5244
   460
      | t1 $ t2  => const_ssubst t1 s $ const_ssubst t2 s;
wenzelm@5244
   461
wenzelm@5244
   462
(* FIXME: improve: can be expressed with foldl *)
wenzelm@5244
   463
fun const_ssubst_list [] t = t
wenzelm@5244
   464
  | const_ssubst_list (s :: l) t = const_ssubst_list l (const_ssubst t s);
wenzelm@5244
   465
wenzelm@5244
   466
(* Locale.pretty_term *)
wenzelm@5244
   467
fun pretty_term sign =
wenzelm@5244
   468
    if (is_open_loc_sg sign) then
wenzelm@5244
   469
        let val locale_list = map snd(get_scope_sg sign);
wenzelm@5244
   470
            val nosyn = flat (map #nosyn locale_list);
wenzelm@5244
   471
            val str_list = (collect_consts sign) \\ nosyn
wenzelm@5244
   472
        in Sign.pretty_term sign o (const_ssubst_list str_list)
wenzelm@5244
   473
        end
wenzelm@5244
   474
    else Sign.pretty_term sign;
wenzelm@5244
   475
wenzelm@5244
   476
wenzelm@5244
   477
wenzelm@5244
   478
(** print_goals **)
wenzelm@5244
   479
wenzelm@5244
   480
(*print thm A1,...,An/B in "goal style" -- premises as numbered subgoals*)
wenzelm@5244
   481
wenzelm@5244
   482
local
wenzelm@5244
   483
wenzelm@5244
   484
  (* utils *)
wenzelm@5244
   485
wenzelm@5244
   486
  fun ins_entry (x, y) [] = [(x, [y])]
wenzelm@5244
   487
    | ins_entry (x, y) ((pair as (x', ys')) :: pairs) =
wenzelm@5244
   488
        if x = x' then (x', y ins ys') :: pairs
wenzelm@5244
   489
        else pair :: ins_entry (x, y) pairs;
wenzelm@5244
   490
wenzelm@5244
   491
  fun add_consts (Const (c, T), env) = ins_entry (T, (c, T)) env
wenzelm@5244
   492
    | add_consts (t $ u, env) = add_consts (u, add_consts (t, env))
wenzelm@5244
   493
    | add_consts (Abs (_, _, t), env) = add_consts (t, env)
wenzelm@5244
   494
    | add_consts (_, env) = env;
wenzelm@5244
   495
wenzelm@5244
   496
  fun add_vars (Free (x, T), env) = ins_entry (T, (x, ~1)) env
wenzelm@5244
   497
    | add_vars (Var (xi, T), env) = ins_entry (T, xi) env
wenzelm@5244
   498
    | add_vars (Abs (_, _, t), env) = add_vars (t, env)
wenzelm@5244
   499
    | add_vars (t $ u, env) = add_vars (u, add_vars (t, env))
wenzelm@5244
   500
    | add_vars (_, env) = env;
wenzelm@5244
   501
wenzelm@5244
   502
  fun add_varsT (Type (_, Ts), env) = foldr add_varsT (Ts, env)
wenzelm@5244
   503
    | add_varsT (TFree (x, S), env) = ins_entry (S, (x, ~1)) env
wenzelm@5244
   504
    | add_varsT (TVar (xi, S), env) = ins_entry (S, xi) env;
wenzelm@5244
   505
wenzelm@5244
   506
  fun sort_idxs vs = map (apsnd (sort (prod_ord string_ord int_ord))) vs;
wenzelm@5244
   507
  fun sort_cnsts cs = map (apsnd (sort_wrt fst)) cs;
wenzelm@5244
   508
wenzelm@5244
   509
wenzelm@5244
   510
  (* prepare atoms *)
wenzelm@5244
   511
wenzelm@5244
   512
  fun consts_of t = sort_cnsts (add_consts (t, []));
wenzelm@5244
   513
  fun vars_of t = sort_idxs (add_vars (t, []));
wenzelm@5244
   514
  fun varsT_of t = rev (sort_idxs (it_term_types add_varsT (t, [])));
wenzelm@5244
   515
wenzelm@5244
   516
in
wenzelm@5244
   517
wenzelm@5729
   518
  fun print_goals_marker begin_goal maxgoals state =
wenzelm@5244
   519
    let
wenzelm@5244
   520
      val {sign, ...} = rep_thm state;
wenzelm@5244
   521
wenzelm@5244
   522
      val prt_term = pretty_term sign;
wenzelm@5244
   523
      val prt_typ = Sign.pretty_typ sign;
wenzelm@5244
   524
      val prt_sort = Sign.pretty_sort sign;
wenzelm@5244
   525
wenzelm@5244
   526
      fun prt_atoms prt prtT (X, xs) = Pretty.block
wenzelm@5244
   527
        [Pretty.block (Pretty.commas (map prt xs)), Pretty.str " ::",
wenzelm@5244
   528
          Pretty.brk 1, prtT X];
wenzelm@5244
   529
wenzelm@5244
   530
      fun prt_var (x, ~1) = prt_term (Syntax.free x)
wenzelm@5244
   531
        | prt_var xi = prt_term (Syntax.var xi);
wenzelm@5244
   532
wenzelm@5244
   533
      fun prt_varT (x, ~1) = prt_typ (TFree (x, []))
wenzelm@5244
   534
        | prt_varT xi = prt_typ (TVar (xi, []));
wenzelm@5244
   535
wenzelm@5244
   536
      val prt_consts = prt_atoms (prt_term o Const) prt_typ;
wenzelm@5244
   537
      val prt_vars = prt_atoms prt_var prt_typ;
wenzelm@5244
   538
      val prt_varsT = prt_atoms prt_varT prt_sort;
wenzelm@5244
   539
wenzelm@5244
   540
wenzelm@5244
   541
      fun print_list _ _ [] = ()
wenzelm@5244
   542
        | print_list name prt lst = (writeln "";
wenzelm@5244
   543
            Pretty.writeln (Pretty.big_list name (map prt lst)));
wenzelm@5244
   544
wenzelm@5244
   545
      fun print_subgoals (_, []) = ()
wenzelm@5244
   546
        | print_subgoals (n, A :: As) = (Pretty.writeln (Pretty.blk (0,
wenzelm@5729
   547
            [Pretty.str (begin_goal ^ " " ^ string_of_int n ^ ". "), prt_term A]));
wenzelm@5244
   548
              print_subgoals (n + 1, As));
wenzelm@5244
   549
wenzelm@5244
   550
      val print_ffpairs =
wenzelm@5244
   551
        print_list "Flex-flex pairs:" (prt_term o Logic.mk_flexpair);
wenzelm@5244
   552
wenzelm@5244
   553
      val print_consts = print_list "Constants:" prt_consts o consts_of;
wenzelm@5244
   554
      val print_vars = print_list "Variables:" prt_vars o vars_of;
wenzelm@5244
   555
      val print_varsT = print_list "Type variables:" prt_varsT o varsT_of;
wenzelm@5244
   556
wenzelm@5244
   557
wenzelm@5244
   558
      val {prop, ...} = rep_thm state;
wenzelm@5244
   559
      val (tpairs, As, B) = Logic.strip_horn prop;
wenzelm@5244
   560
      val ngoals = length As;
wenzelm@5244
   561
wenzelm@5244
   562
      fun print_gs (types, sorts) =
wenzelm@5244
   563
       (Pretty.writeln (prt_term B);
wenzelm@5244
   564
        if ngoals = 0 then writeln "No subgoals!"
wenzelm@5244
   565
        else if ngoals > maxgoals then
wenzelm@5244
   566
          (print_subgoals (1, take (maxgoals, As));
wenzelm@5244
   567
            writeln ("A total of " ^ string_of_int ngoals ^ " subgoals..."))
wenzelm@5244
   568
        else print_subgoals (1, As);
wenzelm@5244
   569
wenzelm@5244
   570
        print_ffpairs tpairs;
wenzelm@5244
   571
wenzelm@5244
   572
        if types andalso ! show_consts then print_consts prop else ();
wenzelm@5244
   573
        if types then print_vars prop else ();
wenzelm@5244
   574
        if sorts then print_varsT prop else ());
wenzelm@5244
   575
    in
wenzelm@5244
   576
      setmp show_no_free_types true
wenzelm@5244
   577
        (setmp show_types (! show_types orelse ! show_sorts)
wenzelm@5244
   578
          (setmp show_sorts false print_gs))
wenzelm@5244
   579
     (! show_types orelse ! show_sorts, ! show_sorts)
wenzelm@5244
   580
  end;
wenzelm@5244
   581
wenzelm@5729
   582
  val print_goals = print_goals_marker "";
wenzelm@5729
   583
wenzelm@5244
   584
end;
wenzelm@5244
   585
wenzelm@5244
   586
wenzelm@5244
   587
wenzelm@5244
   588
(** locale theory setup **)
wenzelm@5244
   589
wenzelm@5244
   590
val setup =
wenzelm@5244
   591
 [LocalesData.init];
wenzelm@5244
   592
wenzelm@5244
   593
end;
wenzelm@5244
   594
wenzelm@5244
   595
structure BasicLocale: BASIC_LOCALE = Locale;
wenzelm@5244
   596
open BasicLocale;