src/Pure/Isar/code.ML
changeset 30023 55954f726043
parent 29970 cbf46080ea3a
child 30060 672012330c4e
equal deleted inserted replaced
30022:1d8b8fa19074 30023:55954f726043
    33   val operational_algebra: theory -> (sort -> sort) * Sorts.algebra
    33   val operational_algebra: theory -> (sort -> sort) * Sorts.algebra
    34   val these_eqns: theory -> string -> (thm * bool) list
    34   val these_eqns: theory -> string -> (thm * bool) list
    35   val these_raw_eqns: theory -> string -> (thm * bool) list
    35   val these_raw_eqns: theory -> string -> (thm * bool) list
    36   val get_datatype: theory -> string -> ((string * sort) list * (string * typ list) list)
    36   val get_datatype: theory -> string -> ((string * sort) list * (string * typ list) list)
    37   val get_datatype_of_constr: theory -> string -> string option
    37   val get_datatype_of_constr: theory -> string -> string option
    38   val get_case_scheme: theory -> string -> (int * string list) option
    38   val get_case_scheme: theory -> string -> (int * (int * string list)) option
    39   val is_undefined: theory -> string -> bool
    39   val is_undefined: theory -> string -> bool
    40   val default_typscheme: theory -> string -> (string * sort) list * typ
    40   val default_typscheme: theory -> string -> (string * sort) list * typ
    41 
    41 
    42   val preprocess_conv: theory -> cterm -> thm
    42   val preprocess_conv: theory -> cterm -> thm
    43   val preprocess_term: theory -> term -> term
    43   val preprocess_term: theory -> term -> term
   109   end;
   109   end;
   110 
   110 
   111 
   111 
   112 (** logical and syntactical specification of executable code **)
   112 (** logical and syntactical specification of executable code **)
   113 
   113 
   114 (* defining equations *)
   114 (* code equations *)
   115 
   115 
   116 type eqns = bool * (thm * bool) list lazy;
   116 type eqns = bool * (thm * bool) list lazy;
   117   (*default flag, theorems with linear flag (perhaps lazy)*)
   117   (*default flag, theorems with linear flag (perhaps lazy)*)
   118 
   118 
   119 fun pretty_lthms ctxt r = case Lazy.peek r
   119 fun pretty_lthms ctxt r = case Lazy.peek r
   134     val incr_idx = Logic.incr_indexes ([], Thm.maxidx_of thm + 1);
   134     val incr_idx = Logic.incr_indexes ([], Thm.maxidx_of thm + 1);
   135     fun matches_args args' = length args <= length args' andalso
   135     fun matches_args args' = length args <= length args' andalso
   136       Pattern.matchess thy (args, (map incr_idx o curry Library.take (length args)) args');
   136       Pattern.matchess thy (args, (map incr_idx o curry Library.take (length args)) args');
   137     fun drop (thm', linear') = if (linear orelse not linear')
   137     fun drop (thm', linear') = if (linear orelse not linear')
   138       andalso matches_args (args_of thm') then 
   138       andalso matches_args (args_of thm') then 
   139         (warning ("Code generator: dropping redundant defining equation\n" ^ Display.string_of_thm thm'); true)
   139         (warning ("Code generator: dropping redundant code equation\n" ^ Display.string_of_thm thm'); true)
   140       else false;
   140       else false;
   141   in (thm, linear) :: filter_out drop thms end;
   141   in (thm, linear) :: filter_out drop thms end;
   142 
   142 
   143 fun add_thm thy _ thm (false, thms) = (false, Lazy.map_force (add_drop_redundant thy thm) thms)
   143 fun add_thm thy _ thm (false, thms) = (false, Lazy.map_force (add_drop_redundant thy thm) thms)
   144   | add_thm thy true thm (true, thms) = (true, Lazy.map_force (fn thms => thms @ [thm]) thms)
   144   | add_thm thy true thm (true, thms) = (true, Lazy.map_force (fn thms => thms @ [thm]) thms)
   407           (Syntax.string_of_typ_global thy (Type (dtco, map TFree vs)), cos))
   407           (Syntax.string_of_typ_global thy (Type (dtco, map TFree vs)), cos))
   408       |> sort (string_ord o pairself fst)
   408       |> sort (string_ord o pairself fst)
   409   in
   409   in
   410     (Pretty.writeln o Pretty.chunks) [
   410     (Pretty.writeln o Pretty.chunks) [
   411       Pretty.block (
   411       Pretty.block (
   412         Pretty.str "defining equations:"
   412         Pretty.str "code equations:"
   413         :: Pretty.fbrk
   413         :: Pretty.fbrk
   414         :: (Pretty.fbreaks o map pretty_eqn) eqns
   414         :: (Pretty.fbreaks o map pretty_eqn) eqns
   415       ),
   415       ),
   416       Pretty.block [
   416       Pretty.block [
   417         Pretty.str "preprocessing simpset:",
   417         Pretty.str "preprocessing simpset:",
   450           in (thm', max') end;
   450           in (thm', max') end;
   451         val (thms', maxidx) = fold_map incr_thm thms 0;
   451         val (thms', maxidx) = fold_map incr_thm thms 0;
   452         val ty1 :: tys = map (snd o Code_Unit.const_typ_eqn) thms';
   452         val ty1 :: tys = map (snd o Code_Unit.const_typ_eqn) thms';
   453         fun unify ty env = Sign.typ_unify thy (ty1, ty) env
   453         fun unify ty env = Sign.typ_unify thy (ty1, ty) env
   454           handle Type.TUNIFY =>
   454           handle Type.TUNIFY =>
   455             error ("Type unificaton failed, while unifying defining equations\n"
   455             error ("Type unificaton failed, while unifying code equations\n"
   456             ^ (cat_lines o map Display.string_of_thm) thms
   456             ^ (cat_lines o map Display.string_of_thm) thms
   457             ^ "\nwith types\n"
   457             ^ "\nwith types\n"
   458             ^ (cat_lines o map (Code_Unit.string_of_typ thy)) (ty1 :: tys));
   458             ^ (cat_lines o map (Code_Unit.string_of_typ thy)) (ty1 :: tys));
   459         val (env, _) = fold unify tys (Vartab.empty, maxidx)
   459         val (env, _) = fold unify tys (Vartab.empty, maxidx)
   460         val instT = Vartab.fold (fn (x_i, (sort, ty)) =>
   460         val instT = Vartab.fold (fn (x_i, (sort, ty)) =>
   461           cons (Thm.ctyp_of thy (TVar (x_i, sort)), Thm.ctyp_of thy ty)) env [];
   461           cons (Thm.ctyp_of thy (TVar (x_i, sort)), Thm.ctyp_of thy ty)) env [];
   462       in map (Thm.instantiate (instT, [])) thms' end;
   462       in map (Thm.instantiate (instT, [])) thms' end;
   463 
   463 
   464 fun check_linear (eqn as (thm, linear)) =
   464 fun check_linear (eqn as (thm, linear)) =
   465   if linear then eqn else Code_Unit.bad_thm
   465   if linear then eqn else Code_Unit.bad_thm
   466     ("Duplicate variables on left hand side of defining equation:\n"
   466     ("Duplicate variables on left hand side of code equation:\n"
   467       ^ Display.string_of_thm thm);
   467       ^ Display.string_of_thm thm);
   468 
   468 
   469 fun mk_eqn thy linear =
   469 fun mk_eqn thy linear =
   470   Code_Unit.error_thm ((if linear then check_linear else I) o Code_Unit.mk_eqn thy);
   470   Code_Unit.error_thm ((if linear then check_linear else I) o Code_Unit.mk_eqn thy);
   471 fun mk_syntactic_eqn thy = Code_Unit.warning_thm (Code_Unit.mk_eqn thy);
   471 fun mk_syntactic_eqn thy = Code_Unit.warning_thm (Code_Unit.mk_eqn thy);
   523   case (snd o strip_type o Sign.the_const_type thy) c
   523   case (snd o strip_type o Sign.the_const_type thy) c
   524    of Type (tyco, _) => if member (op =) ((map fst o snd o get_datatype thy) tyco) c
   524    of Type (tyco, _) => if member (op =) ((map fst o snd o get_datatype thy) tyco) c
   525        then SOME tyco else NONE
   525        then SOME tyco else NONE
   526     | _ => NONE;
   526     | _ => NONE;
   527 
   527 
   528 fun get_constr_typ thy c =
       
   529   case get_datatype_of_constr thy c
       
   530    of SOME tyco => let
       
   531           val (vs, cos) = get_datatype thy tyco;
       
   532           val SOME tys = AList.lookup (op =) cos c;
       
   533           val ty = tys ---> Type (tyco, map TFree vs);
       
   534         in SOME (Logic.varifyT ty) end
       
   535     | NONE => NONE;
       
   536 
       
   537 fun recheck_eqn thy = Code_Unit.error_thm
   528 fun recheck_eqn thy = Code_Unit.error_thm
   538   (Code_Unit.assert_linear (is_some o get_datatype_of_constr thy) o apfst (Code_Unit.assert_eqn thy));
   529   (Code_Unit.assert_linear (is_some o get_datatype_of_constr thy) o apfst (Code_Unit.assert_eqn thy));
   539 
   530 
   540 fun recheck_eqns_const thy c eqns =
   531 fun recheck_eqns_const thy c eqns =
   541   let
   532   let
   542     fun cert (eqn as (thm, _)) = if c = Code_Unit.const_eqn thm
   533     fun cert (eqn as (thm, _)) = if c = Code_Unit.const_eqn thm
   543       then eqn else error ("Wrong head of defining equation,\nexpected constant "
   534       then eqn else error ("Wrong head of code equation,\nexpected constant "
   544         ^ Code_Unit.string_of_const thy c ^ "\n" ^ Display.string_of_thm thm)
   535         ^ Code_Unit.string_of_const thy c ^ "\n" ^ Display.string_of_thm thm)
   545   in map (cert o recheck_eqn thy) eqns end;
   536   in map (cert o recheck_eqn thy) eqns end;
   546 
   537 
   547 fun change_eqns delete c f = (map_exec_purge (SOME [c]) o map_eqns
   538 fun change_eqns delete c f = (map_exec_purge (SOME [c]) o map_eqns
   548   o (if delete then Symtab.map_entry c else Symtab.map_default (c, ((false, (true, Lazy.value [])), [])))
   539   o (if delete then Symtab.map_entry c else Symtab.map_default (c, ((false, (true, Lazy.value [])), [])))
   552   case (if default then mk_default_eqn thy else SOME o mk_eqn thy linear) thm
   543   case (if default then mk_default_eqn thy else SOME o mk_eqn thy linear) thm
   553    of SOME (thm, _) =>
   544    of SOME (thm, _) =>
   554         let
   545         let
   555           val c = Code_Unit.const_eqn thm;
   546           val c = Code_Unit.const_eqn thm;
   556           val _ = if not default andalso (is_some o AxClass.class_of_param thy) c
   547           val _ = if not default andalso (is_some o AxClass.class_of_param thy) c
   557             then error ("Rejected polymorphic equation for overloaded constant:\n"
   548             then error ("Rejected polymorphic code equation for overloaded constant:\n"
   558               ^ Display.string_of_thm thm)
   549               ^ Display.string_of_thm thm)
   559             else ();
   550             else ();
   560           val _ = if not default andalso (is_some o get_datatype_of_constr thy) c
   551           val _ = if not default andalso (is_some o get_datatype_of_constr thy) c
   561             then error ("Rejected equation for datatype constructor:\n"
   552             then error ("Rejected code equation for datatype constructor:\n"
   562               ^ Display.string_of_thm thm)
   553               ^ Display.string_of_thm thm)
   563             else ();
   554             else ();
   564         in change_eqns false c (add_thm thy default (thm, linear)) thy end
   555         in change_eqns false c (add_thm thy default (thm, linear)) thy end
   565     | NONE => thy;
   556     | NONE => thy;
   566 
   557 
   581  of SOME (thm, _) => change_eqns true (Code_Unit.const_eqn thm) (del_thm thm) thy
   572  of SOME (thm, _) => change_eqns true (Code_Unit.const_eqn thm) (del_thm thm) thy
   582   | NONE => thy;
   573   | NONE => thy;
   583 
   574 
   584 fun del_eqns c = change_eqns true c (K (false, Lazy.value []));
   575 fun del_eqns c = change_eqns true c (K (false, Lazy.value []));
   585 
   576 
   586 fun get_case_scheme thy = Symtab.lookup ((fst o the_cases o the_exec) thy);
   577 fun get_case_scheme thy c = case Symtab.lookup ((fst o the_cases o the_exec) thy) c
       
   578  of SOME (base_case_scheme as (_, case_pats)) =>
       
   579       if forall (is_some o get_datatype_of_constr thy) case_pats
       
   580       then SOME (1 + Int.max (1, length case_pats), base_case_scheme)
       
   581       else NONE
       
   582   | NONE => NONE;
   587 
   583 
   588 val is_undefined = Symtab.defined o snd o the_cases o the_exec;
   584 val is_undefined = Symtab.defined o snd o the_cases o the_exec;
   589 
   585 
   590 structure TypeInterpretation = InterpretationFun(type T = string * serial val eq = eq_snd (op =) : T * T -> bool);
   586 structure TypeInterpretation = InterpretationFun(type T = string * serial val eq = eq_snd (op =) : T * T -> bool);
   591 
   587 
   725     |> preprocess thy functrans c
   721     |> preprocess thy functrans c
   726   end;
   722   end;
   727 
   723 
   728 fun default_typscheme thy c =
   724 fun default_typscheme thy c =
   729   let
   725   let
   730     val typscheme = curry (Code_Unit.typscheme thy) c
   726     fun the_const_typscheme c = (curry (Code_Unit.typscheme thy) c o snd o dest_Const
   731     val the_const_type = snd o dest_Const o TermSubst.zero_var_indexes
   727       o TermSubst.zero_var_indexes o curry Const "" o Sign.the_const_type thy) c;
   732       o curry Const "" o Sign.the_const_type thy;
   728     fun strip_sorts (vs, ty) = (map (fn (v, _) => (v, [])) vs, ty);
   733   in case AxClass.class_of_param thy c
   729   in case AxClass.class_of_param thy c
   734    of SOME class => the_const_type c
   730    of SOME class => ([(Name.aT, [class])], snd (the_const_typscheme c))
   735         |> Term.map_type_tvar (K (TVar ((Name.aT, 0), [class])))
   731     | NONE => if is_some (get_datatype_of_constr thy c)
   736         |> typscheme
   732         then strip_sorts (the_const_typscheme c)
   737     | NONE => (case get_constr_typ thy c
   733         else case get_eqns thy c
   738        of SOME ty => typscheme ty
   734          of (thm, _) :: _ => snd (Code_Unit.head_eqn thy (Drule.zero_var_indexes thm))
   739         | NONE => (case get_eqns thy c
   735           | [] => strip_sorts (the_const_typscheme c) end;
   740            of (thm, _) :: _ => snd (Code_Unit.head_eqn thy (Drule.zero_var_indexes thm))
       
   741             | [] => typscheme (the_const_type c))) end;
       
   742 
   736 
   743 end; (*local*)
   737 end; (*local*)
   744 
   738 
   745 end; (*struct*)
   739 end; (*struct*)
   746 
   740