src/Tools/Code/code_thingol.ML
changeset 77233 6bdd125d932b
parent 77232 6cad6ed2700a
child 77700 86b9a405b0cc
equal deleted inserted replaced
77232:6cad6ed2700a 77233:6bdd125d932b
    23     | Dict_Var of { var: vname, index: int, length: int, class: class, unique: bool };
    23     | Dict_Var of { var: vname, index: int, length: int, class: class, unique: bool };
    24   datatype itype =
    24   datatype itype =
    25       `%% of string * itype list
    25       `%% of string * itype list
    26     | ITyVar of vname;
    26     | ITyVar of vname;
    27   type const = { sym: Code_Symbol.T, typargs: itype list, dicts: dict list list,
    27   type const = { sym: Code_Symbol.T, typargs: itype list, dicts: dict list list,
    28     dom: itype list, annotation: itype option };
    28     dom: itype list, range: itype, annotation: itype option };
    29   datatype iterm =
    29   datatype iterm =
    30       IConst of const
    30       IConst of const
    31     | IVar of vname option
    31     | IVar of vname option
    32     | `$ of iterm * iterm
    32     | `$ of iterm * iterm
    33     | `|=> of (vname option * itype) * iterm
    33     | `|=> of (vname option * itype) * (iterm * itype)
    34     | ICase of { term: iterm, typ: itype, clauses: (iterm * iterm) list, primitive: iterm };
    34     | ICase of { term: iterm, typ: itype, clauses: (iterm * iterm) list, primitive: iterm };
    35   val `-> : itype * itype -> itype;
    35   val `-> : itype * itype -> itype;
    36   val `--> : itype list * itype -> itype;
    36   val `--> : itype list * itype -> itype;
    37   val `$$ : iterm * iterm list -> iterm;
    37   val `$$ : iterm * iterm list -> iterm;
    38   val `|==> : (vname option * itype) list * iterm -> iterm;
    38   val `|==> : (vname option * itype) list * (iterm * itype) -> iterm;
    39   type typscheme = (vname * sort) list * itype;
    39   type typscheme = (vname * sort) list * itype;
    40 end;
    40 end;
    41 
    41 
    42 signature CODE_THINGOL =
    42 signature CODE_THINGOL =
    43 sig
    43 sig
    46   val unfoldr: ('a -> ('b * 'a) option) -> 'a -> 'b list * 'a
    46   val unfoldr: ('a -> ('b * 'a) option) -> 'a -> 'b list * 'a
    47   val unfold_fun: itype -> itype list * itype
    47   val unfold_fun: itype -> itype list * itype
    48   val unfold_fun_n: int -> itype -> itype list * itype
    48   val unfold_fun_n: int -> itype -> itype list * itype
    49   val unfold_app: iterm -> iterm * iterm list
    49   val unfold_app: iterm -> iterm * iterm list
    50   val unfold_abs: iterm -> (vname option * itype) list * iterm
    50   val unfold_abs: iterm -> (vname option * itype) list * iterm
       
    51   val unfold_abs_typed: iterm -> ((vname option * itype) list * (iterm * itype)) option
    51   val split_let: iterm -> (((iterm * itype) * iterm) * iterm) option
    52   val split_let: iterm -> (((iterm * itype) * iterm) * iterm) option
    52   val split_let_no_pat: iterm -> (((string option * itype) * iterm) * iterm) option
    53   val split_let_no_pat: iterm -> (((string option * itype) * iterm) * iterm) option
    53   val unfold_let: iterm -> ((iterm * itype) * iterm) list * iterm
    54   val unfold_let: iterm -> ((iterm * itype) * iterm) list * iterm
    54   val unfold_let_no_pat: iterm -> ((string option * itype) * iterm) list * iterm
    55   val unfold_let_no_pat: iterm -> ((string option * itype) * iterm) list * iterm
    55   val split_pat_abs: iterm -> ((iterm * itype) * iterm) option
    56   val split_pat_abs: iterm -> ((iterm * itype) * iterm) option
   156     val (tys1, ty1) = unfold_fun ty;
   157     val (tys1, ty1) = unfold_fun ty;
   157     val (tys3, tys2) = chop n tys1;
   158     val (tys3, tys2) = chop n tys1;
   158   in (tys3, tys2 `--> ty1) end;
   159   in (tys3, tys2 `--> ty1) end;
   159 
   160 
   160 type const = { sym: Code_Symbol.T, typargs: itype list, dicts: dict list list,
   161 type const = { sym: Code_Symbol.T, typargs: itype list, dicts: dict list list,
   161   dom: itype list, annotation: itype option };
   162   dom: itype list, range: itype, annotation: itype option };
   162 
   163 
   163 datatype iterm =
   164 datatype iterm =
   164     IConst of const
   165     IConst of const
   165   | IVar of vname option
   166   | IVar of vname option
   166   | `$ of iterm * iterm
   167   | `$ of iterm * iterm
   167   | `|=> of (vname option * itype) * iterm
   168   | `|=> of (vname option * itype) * (iterm * itype)
   168   | ICase of { term: iterm, typ: itype, clauses: (iterm * iterm) list, primitive: iterm };
   169   | ICase of { term: iterm, typ: itype, clauses: (iterm * iterm) list, primitive: iterm };
   169     (*see also signature*)
   170     (*see also signature*)
   170 
   171 
   171 fun is_IVar (IVar _) = true
   172 fun is_IVar (IVar _) = true
   172   | is_IVar _ = false;
   173   | is_IVar _ = false;
   173 
   174 
   174 fun is_IAbs (_ `|=> _) = true
   175 fun is_IAbs (_ `|=> _) = true
   175   | is_IAbs _ = false;
   176   | is_IAbs _ = false;
   176 
   177 
   177 val op `$$ = Library.foldl (op `$);
   178 val op `$$ = Library.foldl (op `$);
   178 val op `|==> = Library.foldr (op `|=>);
   179 fun vs_tys `|==> body = Library.foldr
       
   180   (fn (v_ty as (_, ty), body as (_, rty)) => (v_ty `|=> body, ty `-> rty)) (vs_tys, body)
       
   181   |> fst;
   179 
   182 
   180 val unfold_app = unfoldl
   183 val unfold_app = unfoldl
   181   (fn op `$ t_t => SOME t_t
   184   (fn op `$ t_t => SOME t_t
   182     | _ => NONE);
   185     | _ => NONE);
   183 
   186 
   184 val unfold_abs = unfoldr
   187 val unfold_abs = unfoldr
   185   (fn op `|=> v_t => SOME v_t
   188   (fn (v `|=> (t, _)) => SOME (v, t)
   186     | _ => NONE);
   189     | _ => NONE);
       
   190 
       
   191 fun unfold_abs_typed (v_ty `|=> body) =
       
   192       unfoldr
       
   193         (fn (v_ty `|=> body, _) => SOME (v_ty, body)
       
   194           | _ => NONE) body
       
   195       |> apfst (cons v_ty)
       
   196       |> SOME
       
   197   | unfold_abs_typed _ = NONE
   187 
   198 
   188 fun split_let (ICase { term = t, typ = ty, clauses = [(p, body)], ... }) =
   199 fun split_let (ICase { term = t, typ = ty, clauses = [(p, body)], ... }) =
   189       SOME (((p, ty), t), body)
   200       SOME (((p, ty), t), body)
   190   | split_let _ = NONE;
   201   | split_let _ = NONE;
   191 
   202 
   205 fun fold_constexprs f =
   216 fun fold_constexprs f =
   206   let
   217   let
   207     fun fold' (IConst c) = f c
   218     fun fold' (IConst c) = f c
   208       | fold' (IVar _) = I
   219       | fold' (IVar _) = I
   209       | fold' (t1 `$ t2) = fold' t1 #> fold' t2
   220       | fold' (t1 `$ t2) = fold' t1 #> fold' t2
   210       | fold' (_ `|=> t) = fold' t
   221       | fold' (_ `|=> (t, _)) = fold' t
   211       | fold' (ICase { term = t, clauses = clauses, ... }) =
   222       | fold' (ICase { term = t, clauses = clauses, ... }) =
   212           fold' t #> fold (fn (p, body) => fold' p #> fold' body) clauses
   223           fold' t #> fold (fn (p, body) => fold' p #> fold' body) clauses
   213   in fold' end;
   224   in fold' end;
   214 
   225 
   215 val add_constsyms = fold_constexprs (fn { sym, ... } => insert (op =) sym);
   226 val add_constsyms = fold_constexprs (fn { sym, ... } => insert (op =) sym);
   225       let
   236       let
   226         fun fold_term _ (IConst _) = I
   237         fun fold_term _ (IConst _) = I
   227           | fold_term vs (IVar (SOME v)) = if member (op =) vs v then I else f v
   238           | fold_term vs (IVar (SOME v)) = if member (op =) vs v then I else f v
   228           | fold_term _ (IVar NONE) = I
   239           | fold_term _ (IVar NONE) = I
   229           | fold_term vs (t1 `$ t2) = fold_term vs t1 #> fold_term vs t2
   240           | fold_term vs (t1 `$ t2) = fold_term vs t1 #> fold_term vs t2
   230           | fold_term vs ((SOME v, _) `|=> t) = fold_term (insert (op =) v vs) t
   241           | fold_term vs ((SOME v, _) `|=> (t, _)) = fold_term (insert (op =) v vs) t
   231           | fold_term vs ((NONE, _) `|=> t) = fold_term vs t
   242           | fold_term vs ((NONE, _) `|=> (t, _)) = fold_term vs t
   232           | fold_term vs (ICase { term = t, clauses = clauses, ... }) =
   243           | fold_term vs (ICase { term = t, clauses = clauses, ... }) =
   233               fold_term vs t #> fold (fold_clause vs) clauses
   244               fold_term vs t #> fold (fold_clause vs) clauses
   234         and fold_clause vs (p, t) = fold_term (add_vars p vs) t;
   245         and fold_clause vs (p, t) = fold_term (add_vars p vs) t;
   235       in fold_term [] end
   246       in fold_term [] end
   236     fun add_vars t = fold_aux add_vars (insert (op =)) t;
   247     fun add_vars t = fold_aux add_vars (insert (op =)) t;
   243 fun exists_var t v = fold_varnames (fn w => fn b => v = w orelse b) t false;
   254 fun exists_var t v = fold_varnames (fn w => fn b => v = w orelse b) t false;
   244 
   255 
   245 fun invent_params used tys =
   256 fun invent_params used tys =
   246   (map o apfst) SOME (Name.invent_names (Name.build_context used) "a" tys);
   257   (map o apfst) SOME (Name.invent_names (Name.build_context used) "a" tys);
   247 
   258 
   248 fun split_pat_abs ((NONE, ty) `|=> t) = SOME ((IVar NONE, ty), t)
   259 fun split_pat_abs ((NONE, ty) `|=> (t, _)) = SOME ((IVar NONE, ty), t)
   249   | split_pat_abs ((SOME v, ty) `|=> t) = SOME (case t
   260   | split_pat_abs ((SOME v, ty) `|=> (t, _)) = SOME (case t
   250      of ICase { term = IVar (SOME w), clauses = [(p, body)], ... } =>
   261      of ICase { term = IVar (SOME w), clauses = [(p, body)], ... } =>
   251           if v = w andalso (exists_var p v orelse not (exists_var body v))
   262           if v = w andalso (exists_var p v orelse not (exists_var body v))
   252           then ((p, ty), body)
   263           then ((p, ty), body)
   253           else ((IVar (SOME v), ty), t)
   264           else ((IVar (SOME v), ty), t)
   254       | _ => ((IVar (SOME v), ty), t))
   265       | _ => ((IVar (SOME v), ty), t))
   255   | split_pat_abs _ = NONE;
   266   | split_pat_abs _ = NONE;
   256 
   267 
   257 val unfold_pat_abs = unfoldr split_pat_abs;
   268 val unfold_pat_abs = unfoldr split_pat_abs;
   258 
   269 
   259 fun unfold_abs_eta [] t = ([], t)
   270 fun unfold_abs_eta [] t = ([], t)
   260   | unfold_abs_eta (_ :: tys) ((v, _) `|=> t) =
   271   | unfold_abs_eta (_ :: tys) ((v, _) `|=> (t, _)) =
   261       let
   272       let
   262         val (vs, t') = unfold_abs_eta tys t;
   273         val (vs, t') = unfold_abs_eta tys t;
   263       in (v :: vs, t') end
   274       in (v :: vs, t') end
   264   | unfold_abs_eta tys t =
   275   | unfold_abs_eta tys t =
   265       let
   276       let
   266         val vs = map fst (invent_params (declare_varnames t) tys);
   277         val vs = map fst (invent_params (declare_varnames t) tys);
   267       in (vs, t `$$ map IVar vs) end;
   278       in (vs, t `$$ map IVar vs) end;
   268 
   279 
   269 fun satisfied_application wanted (const as { dom = tys, ... }, ts) =
   280 fun satisfied_application wanted (const as { dom, range, ... }, ts) =
   270   let
   281   let
   271     val given = length ts;
   282     val given = length ts;
   272     val delta = wanted - given;
   283     val delta = wanted - given;
   273     val vs_tys = invent_params (fold declare_varnames ts)
   284     val vs_tys = invent_params (fold declare_varnames ts)
   274       (((take delta o drop given) tys));
   285       (((take delta o drop given) dom));
   275   in vs_tys `|==> IConst const `$$ ts @ map (IVar o fst) vs_tys end;
   286     val (_, rty) = unfold_fun_n wanted range;
       
   287   in vs_tys `|==> (IConst const `$$ ts @ map (IVar o fst) vs_tys, rty) end;
   276 
   288 
   277 fun map_terms_bottom_up f (t as IConst _) = f t
   289 fun map_terms_bottom_up f (t as IConst _) = f t
   278   | map_terms_bottom_up f (t as IVar _) = f t
   290   | map_terms_bottom_up f (t as IVar _) = f t
   279   | map_terms_bottom_up f (t1 `$ t2) = f
   291   | map_terms_bottom_up f (t1 `$ t2) = f
   280       (map_terms_bottom_up f t1 `$ map_terms_bottom_up f t2)
   292       (map_terms_bottom_up f t1 `$ map_terms_bottom_up f t2)
   281   | map_terms_bottom_up f ((v, ty) `|=> t) = f
   293   | map_terms_bottom_up f ((v, ty) `|=> (t, rty)) = f
   282       ((v, ty) `|=> map_terms_bottom_up f t)
   294       ((v, ty) `|=> (map_terms_bottom_up f t, rty))
   283   | map_terms_bottom_up f (ICase { term = t, typ = ty, clauses = clauses, primitive = t0 }) = f
   295   | map_terms_bottom_up f (ICase { term = t, typ = ty, clauses = clauses, primitive = t0 }) = f
   284       (ICase { term = map_terms_bottom_up f t, typ = ty,
   296       (ICase { term = map_terms_bottom_up f t, typ = ty,
   285         clauses = (map o apply2) (map_terms_bottom_up f) clauses,
   297         clauses = (map o apply2) (map_terms_bottom_up f) clauses,
   286         primitive = map_terms_bottom_up f t0 });
   298         primitive = map_terms_bottom_up f t0 });
   287 
   299 
   328 and exists_dictss_var f dss = (exists o exists) (exists_dict_var f) dss;
   340 and exists_dictss_var f dss = (exists o exists) (exists_dict_var f) dss;
   329 
   341 
   330 fun contains_dict_var (IConst { dicts = dss, ... }) = exists_dictss_var (K true) dss
   342 fun contains_dict_var (IConst { dicts = dss, ... }) = exists_dictss_var (K true) dss
   331   | contains_dict_var (IVar _) = false
   343   | contains_dict_var (IVar _) = false
   332   | contains_dict_var (t1 `$ t2) = contains_dict_var t1 orelse contains_dict_var t2
   344   | contains_dict_var (t1 `$ t2) = contains_dict_var t1 orelse contains_dict_var t2
   333   | contains_dict_var (_ `|=> t) = contains_dict_var t
   345   | contains_dict_var (_ `|=> (t, _)) = contains_dict_var t
   334   | contains_dict_var (ICase { primitive = t, ... }) = contains_dict_var t;
   346   | contains_dict_var (ICase { primitive = t, ... }) = contains_dict_var t;
   335 
   347 
   336 val unambiguous_dictss = not o exists_dictss_var (fn { unique, ... } => not unique);
   348 val unambiguous_dictss = not o exists_dictss_var (fn { unique, ... } => not unique);
   337 
   349 
   338 
   350 
   671       pair (IVar (SOME v))
   683       pair (IVar (SOME v))
   672   | translate_term ctxt algbr eqngr permissive some_thm (Abs (v, ty, t), some_abs) =
   684   | translate_term ctxt algbr eqngr permissive some_thm (Abs (v, ty, t), some_abs) =
   673       let
   685       let
   674         val ((v', _), t') = Term.dest_abs_global (Abs (Name.desymbolize (SOME false) v, ty, t));
   686         val ((v', _), t') = Term.dest_abs_global (Abs (Name.desymbolize (SOME false) v, ty, t));
   675         val v'' = if Term.used_free v' t' then SOME v' else NONE
   687         val v'' = if Term.used_free v' t' then SOME v' else NONE
       
   688         val rty = fastype_of_tagged_term t'
   676       in
   689       in
   677         translate_typ ctxt algbr eqngr permissive ty
   690         translate_typ ctxt algbr eqngr permissive ty
       
   691         ##>> translate_typ ctxt algbr eqngr permissive rty
   678         ##>> translate_term ctxt algbr eqngr permissive some_thm (t', some_abs)
   692         ##>> translate_term ctxt algbr eqngr permissive some_thm (t', some_abs)
   679         #>> (fn (ty, t) => (v'', ty) `|=> t)
   693         #>> (fn ((ty, rty), t) => (v'', ty) `|=> (t, rty))
   680       end
   694       end
   681   | translate_term ctxt algbr eqngr permissive some_thm (t as _ $ _, some_abs) =
   695   | translate_term ctxt algbr eqngr permissive some_thm (t as _ $ _, some_abs) =
   682       case strip_comb t
   696       case strip_comb t
   683        of (Const (c, ty), ts) =>
   697        of (Const (c, ty), ts) =>
   684             translate_app ctxt algbr eqngr permissive some_thm (((c, ty), ts), some_abs)
   698             translate_app ctxt algbr eqngr permissive some_thm (((c, ty), ts), some_abs)
   710     val (dom, range) = Term.strip_type ty';
   724     val (dom, range) = Term.strip_type ty';
   711   in
   725   in
   712     ensure_const ctxt algbr eqngr permissive c
   726     ensure_const ctxt algbr eqngr permissive c
   713     ##>> fold_map (translate_typ ctxt algbr eqngr permissive) typargs
   727     ##>> fold_map (translate_typ ctxt algbr eqngr permissive) typargs
   714     ##>> fold_map (translate_dicts ctxt algbr eqngr permissive some_thm) (typargs ~~ sorts)
   728     ##>> fold_map (translate_dicts ctxt algbr eqngr permissive some_thm) (typargs ~~ sorts)
   715     ##>> fold_map (translate_typ ctxt algbr eqngr permissive) (ty' :: dom)
   729     ##>> fold_map (translate_typ ctxt algbr eqngr permissive) (range :: dom)
   716     #>> (fn (((c, typargs), dss), annotation :: dom) =>
   730     #>> (fn (((c, typargs), dss), range :: dom) =>
   717       IConst { sym = Constant c, typargs = typargs, dicts = dss,
   731       IConst { sym = Constant c, typargs = typargs, dicts = dss,
   718         dom = dom, annotation =
   732         dom = dom, range = range, annotation =
   719           if annotate then SOME annotation else NONE })
   733           if annotate then SOME (dom `--> range) else NONE })
   720   end
   734   end
   721 and translate_app_const ctxt algbr eqngr permissive some_thm ((c_ty, ts), some_abs) =
   735 and translate_app_const ctxt algbr eqngr permissive some_thm ((c_ty, ts), some_abs) =
   722   translate_const ctxt algbr eqngr permissive some_thm (c_ty, some_abs)
   736   translate_const ctxt algbr eqngr permissive some_thm (c_ty, some_abs)
   723   ##>> fold_map (translate_term ctxt algbr eqngr permissive some_thm o rpair NONE) ts
   737   ##>> fold_map (translate_term ctxt algbr eqngr permissive some_thm o rpair NONE) ts
   724   #>> (fn (t, ts) => t `$$ ts)
   738   #>> (fn (t, ts) => t `$$ ts)
   772       val given = length ts;
   786       val given = length ts;
   773       val delta = wanted - given;
   787       val delta = wanted - given;
   774       val tys = (take delta o drop given o binder_types) ty;
   788       val tys = (take delta o drop given o binder_types) ty;
   775       val used = Name.build_context ((fold o fold_aterms) Term.declare_term_frees ts);
   789       val used = Name.build_context ((fold o fold_aterms) Term.declare_term_frees ts);
   776       val vs_tys = Name.invent_names used "a" tys;
   790       val vs_tys = Name.invent_names used "a" tys;
       
   791       val rty = (drop delta o binder_types) ty ---> body_type ty;
   777     in
   792     in
   778       fold_map (translate_typ ctxt algbr eqngr permissive) tys
   793       fold_map (translate_typ ctxt algbr eqngr permissive) tys
   779       ##>> translate_case ctxt algbr eqngr permissive some_thm pattern_schema ((c, ty), ts @ map Free vs_tys)
   794       ##>> translate_case ctxt algbr eqngr permissive some_thm pattern_schema ((c, ty), ts @ map Free vs_tys)
   780       #>> (fn (tys, t) => map2 (fn (v, _) => pair (SOME v)) vs_tys tys `|==> t)
   795       ##>> translate_typ ctxt algbr eqngr permissive rty
       
   796       #>> (fn ((tys, t), rty) => map2 (fn (v, _) => pair (SOME v)) vs_tys tys `|==> (t, rty))
   781     end
   797     end
   782   else if length ts > wanted then
   798   else if length ts > wanted then
   783     translate_case ctxt algbr eqngr permissive some_thm pattern_schema ((c, ty), take wanted ts)
   799     translate_case ctxt algbr eqngr permissive some_thm pattern_schema ((c, ty), take wanted ts)
   784     ##>> fold_map (translate_term ctxt algbr eqngr permissive some_thm o rpair NONE) (drop wanted ts)
   800     ##>> fold_map (translate_term ctxt algbr eqngr permissive some_thm o rpair NONE) (drop wanted ts)
   785     #>> (fn (t, ts) => t `$$ ts)
   801     #>> (fn (t, ts) => t `$$ ts)