1. Function package accepts a parameter (default "some_term"), which specifies the functions
authorkrauss
Thu, 21 Sep 2006 12:22:05 +0200
changeset 20654 d80502f0d701
parent 20653 24cda2c5fd40
child 20655 8c4d80e8025f
1. Function package accepts a parameter (default "some_term"), which specifies the functions behaviour outside its domain. 2. Bugfix: An exception occured when a function in a mutual definition was declared but no equation was given.
src/HOL/FunDef.thy
src/HOL/Tools/function_package/fundef_common.ML
src/HOL/Tools/function_package/fundef_datatype.ML
src/HOL/Tools/function_package/fundef_package.ML
src/HOL/Tools/function_package/fundef_prep.ML
src/HOL/Tools/function_package/mutual.ML
src/HOL/Tools/function_package/pattern_split.ML
--- a/src/HOL/FunDef.thy	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/FunDef.thy	Thu Sep 21 12:22:05 2006 +0200
@@ -41,25 +41,45 @@
 
 
 lemma fundef_ex1_existence:
-assumes f_def: "f \<equiv> \<lambda>x. THE_default d (\<lambda>y. (x,y)\<in>G)"
+assumes f_def: "f \<equiv> \<lambda>x. THE_default (d x) (\<lambda>y. (x,y)\<in>G)"
 assumes ex1: "\<exists>!y. (x,y)\<in>G"
 shows "(x, f x)\<in>G"
   by (simp only:f_def, rule THE_defaultI', rule ex1)
 
 lemma fundef_ex1_uniqueness:
-assumes f_def: "f \<equiv> \<lambda>x. THE_default d (\<lambda>y. (x,y)\<in>G)"
+assumes f_def: "f \<equiv> \<lambda>x. THE_default (d x) (\<lambda>y. (x,y)\<in>G)"
 assumes ex1: "\<exists>!y. (x,y)\<in>G"
 assumes elm: "(x, h x)\<in>G"
 shows "h x = f x"
   by (simp only:f_def, rule THE_default1_equality[symmetric], rule ex1, rule elm)
 
 lemma fundef_ex1_iff:
-assumes f_def: "f \<equiv> \<lambda>x. THE_default d (\<lambda>y. (x,y)\<in>G)"
+assumes f_def: "f \<equiv> \<lambda>x. THE_default (d x) (\<lambda>y. (x,y)\<in>G)"
 assumes ex1: "\<exists>!y. (x,y)\<in>G"
 shows "((x, y)\<in>G) = (f x = y)"
   apply (auto simp:ex1 f_def THE_default1_equality)
   by (rule THE_defaultI', rule ex1)
 
+lemma fundef_default_value:
+assumes f_def: "f \<equiv> \<lambda>x. THE_default (d x) (\<lambda>y. (x,y)\<in>G)"
+assumes graph: "\<And>x y. (x,y) \<in> G \<Longrightarrow> x \<in> D"
+assumes "x \<notin> D"
+shows "f x = d x"
+proof -
+  have "\<not>(\<exists>y. (x, y) \<in> G)"
+  proof
+    assume "(\<exists>y. (x, y) \<in> G)"
+    with graph and `x\<notin>D` show False by blast
+  qed
+  hence "\<not>(\<exists>!y. (x, y) \<in> G)" by blast
+  
+  thus ?thesis
+    unfolding f_def
+    by (rule THE_default_none)
+qed
+
+
+
 
 subsection {* Projections *}
 consts
--- a/src/HOL/Tools/function_package/fundef_common.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/fundef_common.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -214,6 +214,54 @@
 val map_fundef_congs = FundefCongs.map 
 val get_fundef_congs = FundefCongs.get
 
+
+(* Configuration management *)
+datatype fundef_opt 
+  = Sequential
+  | Default of string
+  | Preprocessor of string
+
+datatype fundef_config
+  = FundefConfig of
+   {
+    sequential: bool,
+    default: string,
+    preprocessor: string option
+   }
+
+
+val default_config = FundefConfig { sequential=false, default="%x. arbitrary", preprocessor=NONE }
+val fun_config = FundefConfig { sequential=true, default="%x. arbitrary", preprocessor=NONE }
+
+fun apply_opt Sequential (FundefConfig {sequential, default, preprocessor}) = 
+    FundefConfig {sequential=true, default=default, preprocessor=preprocessor }
+  | apply_opt (Default d) (FundefConfig {sequential, default, preprocessor}) = 
+    FundefConfig {sequential=sequential, default=d, preprocessor=preprocessor }
+  | apply_opt (Preprocessor p) (FundefConfig {sequential, default, preprocessor}) = 
+    FundefConfig {sequential=sequential, default=default, preprocessor=SOME p }
+
+    
+local structure P = OuterParse and K = OuterKeyword in
+
+val opt_sequential = Scan.optional ((P.$$$ "(" |-- P.$$$ "sequential" --| P.$$$ ")") >> K true) false
+
+val option_parser = (P.$$$ "sequential" >> K Sequential)
+               || ((P.reserved "default" |-- P.term) >> Default)
+
+val config_parser = (Scan.optional (P.$$$ "(" |-- P.list1 option_parser --| P.$$$ ")") [])
+                      >> (fn opts => fold apply_opt opts default_config)
+end
+
+
+
+
+
+
+
+
+
+
+
 end
 
 
--- a/src/HOL/Tools/function_package/fundef_datatype.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/fundef_datatype.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -192,7 +192,7 @@
   OuterSyntax.command "fun" "define general recursive functions (short version)" K.thy_decl
   ((P.opt_locale_target -- P.fixes --| P.$$$ "where" -- statements_ow)
      >> (fn ((target, fixes), statements) =>
-            Toplevel.print o Toplevel.local_theory NONE (FundefPackage.add_fundef fixes statements true 
+            Toplevel.print o Toplevel.local_theory NONE (FundefPackage.add_fundef fixes statements FundefCommon.fun_config 
                                                                                   #> by_pat_completeness_simp)));
 
 val _ = OuterSyntax.add_parsers [funP];
--- a/src/HOL/Tools/function_package/fundef_package.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/fundef_package.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -11,7 +11,7 @@
 sig
     val add_fundef :  (string * string option * mixfix) list 
                       -> ((bstring * Attrib.src list) * string list) list list
-                      -> bool 
+                      -> FundefCommon.fundef_config 
                       -> local_theory 
                       -> Proof.state
 
@@ -34,6 +34,7 @@
 
 open FundefCommon
 
+(*fn (ctxt,s) => Variable.importT_terms (fst (ProofContext.read_termTs ctxt (K false) (K NONE) (K NONE) [] [s])) ctxt;*)
 
 fun burrow_snd f ps = (* ('a list -> 'b list) -> ('c * 'a) list -> ('c * 'b) list *)
     let val (xs, ys) = split_list ps
@@ -101,14 +102,16 @@
     end
 
 
-fun gen_add_fundef prep_spec fixspec eqnss_flags preprocess lthy =
+fun gen_add_fundef prep_spec fixspec eqnss_flags config lthy =
     let
-      val ((fixes, spec), ctxt') = prep_with_flags prep_spec fixspec eqnss_flags preprocess lthy
+      val FundefConfig {sequential, default, ...} = config
+
+      val ((fixes, spec), ctxt') = prep_with_flags prep_spec fixspec eqnss_flags sequential lthy
       val t_eqns = spec
                      |> flat |> map snd |> flat (* flatten external structure *)
 
       val ((mutual_info, name, prep_result as Prep {goal, goalI, ...}), lthy) = 
-          FundefMutual.prepare_fundef_mutual fixes t_eqns lthy
+          FundefMutual.prepare_fundef_mutual fixes t_eqns default lthy
 
       val afterqed = fundef_afterqed fixes spec mutual_info name prep_result
     in
@@ -198,9 +201,9 @@
 
 val functionP =
   OuterSyntax.command "function" "define general recursive functions" K.thy_goal
-  ((opt_sequential -- P.opt_locale_target -- P.fixes --| P.$$$ "where" -- statements_ow)
-     >> (fn (((sequential, target), fixes), statements) =>
-            Toplevel.print o local_theory_to_proof (add_fundef fixes statements sequential)));
+  ((config_parser -- P.opt_locale_target -- P.fixes --| P.$$$ "where" -- statements_ow)
+     >> (fn (((config, target), fixes), statements) =>
+            Toplevel.print o local_theory_to_proof (add_fundef fixes statements config)));
 
 
 val terminationP =
@@ -211,7 +214,7 @@
 
 val _ = OuterSyntax.add_parsers [functionP];
 val _ = OuterSyntax.add_parsers [terminationP];
-val _ = OuterSyntax.add_keywords ["sequential", "otherwise"]; (* currently unused *)
+val _ = OuterSyntax.add_keywords ["sequential", "otherwise"];
 
 end;
 
--- a/src/HOL/Tools/function_package/fundef_prep.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/fundef_prep.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -12,6 +12,7 @@
     val prepare_fundef : string (* defname *)
                          -> (string * typ * mixfix) (* defined symbol *)
                          -> ((string * typ) list * term list * term * term) list (* specification *)
+                         -> string (* default_value, not parsed yet *)
                          -> local_theory
                          -> FundefCommon.prep_result * term * local_theory
 
@@ -419,10 +420,10 @@
 
 
 
-fun define_function fdefname (fname, mixfix) domT ranT G lthy =
+fun define_function fdefname (fname, mixfix) domT ranT G default lthy =
     let
       val f_def = 
-          Abs ("x", domT, Const ("FunDef.THE_default", ranT --> (ranT --> boolT) --> ranT) $ Const ("arbitrary", ranT) $
+          Abs ("x", domT, Const ("FunDef.THE_default", ranT --> (ranT --> boolT) --> ranT) $ (default $ Bound 0) $
                                 Abs ("y", ranT, mk_relmemT domT ranT (Bound 1, Bound 0) G))
           
       val ((f, (_, f_defthm)), lthy) = LocalTheory.def ((fname ^ "C", mixfix), ((fdefname, []), f_def)) lthy
@@ -486,11 +487,13 @@
 
 
 
-fun prepare_fundef defname (fname, fT, mixfix) abstract_qglrs lthy =
+fun prepare_fundef defname (fname, fT, mixfix) abstract_qglrs default_str lthy =
     let
       val fvar = Free (fname, fT)
       val domT = domain_type fT
       val ranT = range_type fT
+                            
+      val [default] = fst (Variable.importT_terms (fst (ProofContext.read_termTs lthy (K false) (K NONE) (K NONE) [] [(default_str, fT)])) lthy) (* FIXME *)
 
       val congs = get_fundef_congs (Context.Proof lthy)
       val (globals, ctxt') = fix_globals domT ranT fvar lthy
@@ -510,7 +513,7 @@
       val RCss = map find_calls trees
 
       val ((G, GIntro_thms, G_elim), lthy) = define_graph (defname ^ "_graph") fvar domT ranT clauses RCss lthy
-      val ((f, f_defthm), lthy) = define_function (defname ^ "_sum_def") (fname, mixfix) domT ranT G lthy
+      val ((f, f_defthm), lthy) = define_function (defname ^ "_sum_def") (fname, mixfix) domT ranT G default lthy
 
       val RCss = map (map (inst_RC (ProofContext.theory_of lthy) fvar f)) RCss
       val trees = map (FundefCtxTree.inst_tree (ProofContext.theory_of lthy) fvar f) trees
--- a/src/HOL/Tools/function_package/mutual.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/mutual.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -12,6 +12,7 @@
   
   val prepare_fundef_mutual : ((string * typ) * mixfix) list 
                               -> term list 
+                              -> string (* default, unparsed term *)
                               -> local_theory 
                               -> ((FundefCommon.mutual_info * string * FundefCommon.prep_result) * local_theory)
 
@@ -42,7 +43,7 @@
 
 fun check_head fs t =
     if (case t of 
-          (Free (n, _)) => n mem fs
+          (Free (n, _)) => n mem (map fst fs)
         | _ => false)
     then dest_Free t
     else raise ERROR "Head symbol of every left hand side must be the new function." (* FIXME: Output the equation here *)
@@ -54,7 +55,7 @@
 
 
 (* Builds a curried clause description in abstracted form *)
-fun split_def fnames geq =
+fun split_def fs geq arities =
     let
       val (qs, imp) = open_all_all geq
 
@@ -63,7 +64,7 @@
 
       val (f_args, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop eq)
       val (fc, args) = strip_comb f_args
-      val f as (fname, _) = check_head fnames fc
+      val f as (fname, _) = check_head fs fc
 
       fun add_bvs t is = add_loose_bnos (t, 0, is)
       val rhs_only = (add_bvs rhs [] \\ fold add_bvs args [])
@@ -71,8 +72,16 @@
                         |> map (fst o nth (rev qs))
       val _ = if null rhs_only then () 
 	      else raise ERROR "Variables occur on right hand side only." (* FIXME: Output vars *)
+
+      val k = length args
+
+      val arities' = case Symtab.lookup arities fname of
+                   NONE => Symtab.update (fname, k) arities
+                 | SOME i => if (i <> k) 
+                             then raise ERROR ("Function " ^ fname ^ " has different numbers of arguments in different equations")
+                             else arities
     in
-	((f, length args), (fname, qs, gs, args, rhs))
+	((fname, qs, gs, args, rhs), arities')
     end
 
 fun get_part fname =
@@ -89,45 +98,38 @@
     end;
 
 
-fun analyze_eqs ctxt fnames eqs =
+fun analyze_eqs ctxt fs eqs =
     let
-      (* FIXME: Add check for number of arguments
-	fun all_equal ((x as ((n:string,T), k:int))::xs) = if forall (fn ((n',_),k') => n = n' andalso k = k') xs then x
-							   else raise ERROR ("All equations in a block must describe the same "
-									     ^ "function and have the same number of arguments.")
-       *)
-								      
-        val (consts, fqgars) = split_list (map (split_def fnames) eqs)
+        val fnames = map fst fs 
+        val (fqgars, arities) = fold_map (split_def fs) eqs Symtab.empty
 
-        val different_consts = distinct (eq_fst (eq_fst eq_str)) consts
-	val cnames = map (fst o fst) different_consts
-
-	val check_rcs = exists_subterm (fn Free (n, _) => if n mem cnames 
+	val check_rcs = exists_subterm (fn Free (n, _) => if n mem fnames
 						          then raise ERROR "Recursive Calls not allowed in premises." else false
                                          | _ => false)
                         
 	val _ = forall (fn (_, _, gs, _, _) => forall check_rcs gs) fqgars
 
-	fun curried_types ((_,T), k) =
+	fun curried_types (fname, fT) =
 	    let
-		val (caTs, uaTs) = chop k (binder_types T)
+              val k = the_default 1 (Symtab.lookup arities fname)
+	      val (caTs, uaTs) = chop k (binder_types fT)
 	    in 
-		(caTs, uaTs ---> body_type T)
+		(caTs, uaTs ---> body_type fT)
 	    end
 
-	val (caTss, resultTs) = split_list (map curried_types different_consts)
+	val (caTss, resultTs) = split_list (map curried_types fs)
 	val argTs = map (foldr1 HOLogic.mk_prodT) caTss
 
 	val (RST,streeR, pthsR) = SumTools.mk_tree_distinct resultTs
 	val (ST, streeA, pthsA) = SumTools.mk_tree argTs
 
-	val def_name = foldr1 (fn (a,b) => a ^ "_" ^ b) (map Sign.base_name cnames)
+	val def_name = foldr1 (fn (a,b) => a ^ "_" ^ b) (map Sign.base_name fnames)
 	val fsum_type = ST --> RST
 
         val ([fsum_var_name], _) = Variable.add_fixes [ def_name ^ "_sum" ] ctxt
         val fsum_var = (fsum_var_name, fsum_type)
 
-	fun define (fvar as (n, T), _) caTs pthA pthR = 
+	fun define (fvar as (n, T)) caTs pthA pthR = 
 	    let 
 		val vars = map_index (fn (i,T) => Free ("x" ^ string_of_int i, T)) caTs (* FIXME: Bind xs properly *)
 
@@ -139,7 +141,7 @@
 		(MutualPart {fvar=fvar,cargTs=caTs,pthA=pthA,pthR=pthR,f_def=def,f=NONE,f_defthm=NONE}, rew)
 	    end
 
-	val (parts, rews) = split_list (map4 define different_consts caTss pthsA pthsR)
+	val (parts, rews) = split_list (map4 define fs caTss pthsA pthsR)
 
         fun convert_eqs (f, qs, gs, args, rhs) =
             let
@@ -181,17 +183,13 @@
     end
 
 
-
-  
-
-
-fun prepare_fundef_mutual fixes eqss lthy =
+fun prepare_fundef_mutual fixes eqss default lthy =
     let 
-	val mutual = analyze_eqs lthy (map (fst o fst) fixes) eqss
+	val mutual = analyze_eqs lthy (map fst fixes) eqss
 	val Mutual {defname, fsum_var=(n, T), qglrs, ...} = mutual
 
         val (prep_result, fsum, lthy') =
-            FundefPrep.prepare_fundef defname (n, T, NoSyn) qglrs lthy
+            FundefPrep.prepare_fundef defname (n, T, NoSyn) qglrs default lthy
 
         val (mutual', lthy'') = define_projections fixes mutual fsum lthy'
     in
--- a/src/HOL/Tools/function_package/pattern_split.ML	Thu Sep 21 03:17:51 2006 +0200
+++ b/src/HOL/Tools/function_package/pattern_split.ML	Thu Sep 21 12:22:05 2006 +0200
@@ -94,9 +94,6 @@
       val (vs, feq1 as (_ $ (_ $ lhs1 $ _))) = dest_all_all eq1
       val (_,  _ $ (_ $ lhs2 $ _)) = dest_all_all eq2
 
-      val _ = print (cterm_of thy eq1)
-      val _ = print (cterm_of thy eq2)
-
       val substs = pattern_subtract_subst ctx vs lhs1 lhs2
 
       fun instantiate (vs', sigma) =
@@ -105,10 +102,8 @@
           in
             fold_rev mk_forall (map Free (frees_in_term ctx t) inter vs') t
           end
-
-      fun prtrm t = let val _ = print (map (cterm_of thy) t) in t end
     in
-      prtrm (map instantiate substs)
+      map instantiate substs
     end