src/Pure/consts.ML
changeset 18060 afcc28d16629
child 18065 16608ab6ed84
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/consts.ML	Wed Nov 02 14:46:56 2005 +0100
@@ -0,0 +1,147 @@
+(*  Title:      Pure/consts.ML
+    ID:         $Id$
+    Author:     Makarius
+
+Polymorphic constants.
+*)
+
+signature CONSTS =
+sig
+  type T
+  val dest: T -> {declarations: typ NameSpace.table, constraints: typ NameSpace.table}
+  val space: T -> NameSpace.T
+  val declaration: T -> string -> typ  (*exception TYPE*)
+  val constraint: T -> string -> typ    (*exception TYPE*)
+  val monomorphic: T -> string -> bool
+  val typargs: T -> string -> typ -> typ list
+  val modify_typargs: T -> string -> (typ list -> typ list) -> typ -> typ
+  val map_typargs: T -> string -> (typ -> typ) -> typ -> typ
+  val fold_typargs: T -> string -> (typ -> 'a -> 'a) -> typ -> 'a -> 'a
+  val declare: NameSpace.naming -> bstring * typ -> T -> T
+  val constrain: string * typ -> T -> T
+  val hide: bool -> string -> T -> T
+  val empty: T
+  val merge: T * T -> T
+end
+
+structure Consts: CONSTS =
+struct
+
+
+(** datatype T **)
+
+type arg = (indexname * sort) * int list;  (*type variable with first occurrence*)
+
+datatype T = Consts of
+ {declarations: ((typ * arg list) * serial) NameSpace.table,
+  constraints: typ Symtab.table};
+
+fun make_consts (declarations, constraints) =
+  Consts {declarations = declarations, constraints = constraints};
+
+fun map_consts f (Consts {declarations, constraints}) =
+  make_consts (f (declarations, constraints));
+
+fun dest (Consts {declarations = (space, decls), constraints}) =
+ {declarations = (space, Symtab.map (#1 o #1) decls),
+  constraints = (space, constraints)};
+
+fun space (Consts {declarations = (space, _), ...}) = space;
+
+
+(* lookup consts *)
+
+fun the_const (Consts {declarations = (_, decls), ...}) c =
+  (case Symtab.lookup decls c of SOME (decl, _) => decl
+  | NONE => raise TYPE ("Undeclared constant " ^ quote c, [], []));
+
+fun declaration consts c = #1 (the_const consts c);
+
+fun constraint (consts as Consts {constraints, ...}) c =
+  (case Symtab.lookup constraints c of
+    SOME T => T
+  | NONE => declaration consts c);
+
+fun monomorphic consts c = null (#2 (the_const consts c));
+
+
+(* typargs -- view actual const type as instance of declaration *)
+
+fun sub (Type (_, Ts)) (i :: is) = sub (nth Ts i) is
+  | sub T [] = T
+  | sub T _ = raise Subscript;
+
+fun typargs consts c =
+  let val (_, args) = the_const consts c
+  in fn T => map (sub T o #2) args end;
+
+fun modify_typargs consts c =
+  let val (declT, args) = the_const consts c in
+    fn f => fn T =>
+      let
+        val Us = f (map (sub T o #2) args);
+        val _ =
+          if length args = length Us then ()
+          else raise TYPE ("modify_typargs: bad number of args", [T], []);
+        val inst = ListPair.map (fn ((v, _), U) => (v, U)) (args, Us);
+      in declT |> Term.instantiateT inst end
+  end;
+
+fun map_typargs consts c =
+  let val (declT, args) = the_const consts c in
+    fn f => fn T => declT |> Term.instantiateT (args |> map (fn (v, pos) => (v, f (sub T pos))))
+  end;
+
+fun fold_typargs consts c =
+  let val (_, args) = the_const consts c
+  in fn f => fn T => fold (f o sub T o #2) args end;
+
+
+
+(** build consts **)
+
+fun err_dup_consts cs =
+  error ("Duplicate declaration of constant(s) " ^ commas_quote cs);
+
+fun err_inconsistent_constraints cs =
+  error ("Inconsistent type constraints for constant(s) " ^ commas_quote cs);
+
+
+(* declarations etc. *)
+
+fun args_of declT =
+  let
+    fun args (Type (_, Ts)) pos = args_list Ts 0 pos
+      | args (TVar v) pos = insert (eq_fst op =) (v, rev pos)
+      | args (TFree _) _ = I
+    and args_list (T :: Ts) i is = args T (i :: is) #> args_list Ts (i + 1) is
+      | args_list [] _ _ = I;
+  in rev (args declT [] []) end;
+
+fun declare naming (c, T) = map_consts (apfst (fn declarations =>
+  let
+    val decl = (c, ((T, args_of T), serial ()));
+    val declarations' = NameSpace.extend_table naming (declarations, [decl])
+      handle Symtab.DUPS cs => err_dup_consts cs;
+  in declarations' end));
+
+val constrain = map_consts o apsnd o Symtab.update;
+
+fun hide fully c = map_consts (apfst (apfst (NameSpace.hide fully c)));
+
+
+(* empty and merge *)
+
+val empty = make_consts (NameSpace.empty_table, Symtab.empty);
+
+fun merge
+  (Consts {declarations = declarations1, constraints = constraints1},
+   Consts {declarations = declarations2, constraints = constraints2}) =
+  let
+    val declarations = NameSpace.merge_tables (eq_snd (op =)) (declarations1, declarations2)
+      handle Symtab.DUPS cs => err_dup_consts cs;
+    val constraints = Symtab.merge (op =) (constraints1, constraints2)
+      handle Symtab.DUPS cs => err_inconsistent_constraints cs;
+  in make_consts (declarations, constraints) end;
+
+end;