csharpfftfsharpintegrationinterpolationlinear-algebramathdifferentiationmatrixnumericsrandomregressionstatisticsmathnet
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
554 lines
24 KiB
554 lines
24 KiB
// (c) Microsoft Corporation. All rights reserved
|
|
#light
|
|
|
|
module Microsoft.FSharp.Compiler.AbstractIL.Morphs
|
|
|
|
open Internal.Utilities
|
|
open Microsoft.FSharp.Compiler.AbstractIL
|
|
open Microsoft.FSharp.Compiler.AbstractIL.Internal
|
|
module Illib = Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
|
|
module Ildiag = Microsoft.FSharp.Compiler.AbstractIL.Diagnostics
|
|
module Ilx = Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types
|
|
module Il = Microsoft.FSharp.Compiler.AbstractIL.IL
|
|
open Ildiag
|
|
open Il
|
|
open Ilx
|
|
open Illib
|
|
|
|
type 'a morph = 'a -> 'a
|
|
|
|
type EnclosingTypeDefs = ILTypeDef list * ILTypeDef
|
|
|
|
let checking = false
|
|
let notlazy v = Lazy.CreateFromValue v
|
|
|
|
let mdef_code2code f md =
|
|
let code =
|
|
match dest_mbody md.mdBody with
|
|
| MethodBody_il il-> il
|
|
| _ -> failwith "mdef_code2code - method not IL"
|
|
let code' = MethodBody_il {code with ilCode = f code.ilCode}
|
|
{md with mdBody= mk_mbody code'}
|
|
|
|
let code_block2block f (c:ILCode) = check_code (f c)
|
|
|
|
let bblock_instr2instr f bb =
|
|
let instrs = bb.bblockInstrs
|
|
let len = Array.length instrs
|
|
let res = Array.zeroCreate len
|
|
for i = 0 to len - 1 do
|
|
res.[i] <- f instrs.[i]
|
|
{bb with bblockInstrs=res}
|
|
|
|
// This is quite performance critical
|
|
let nonNil x = match x with [] -> false | _ -> true
|
|
let bblock_instr2instrs f bb =
|
|
let instrs = bb.bblockInstrs
|
|
let codebuf = ref (Array.zeroCreate (Array.length instrs))
|
|
let codebuf_size = ref 0
|
|
for i = 0 to Array.length instrs - 1 do
|
|
let instr = instrs.[i]
|
|
let instrs = f instr
|
|
let curr = ref instrs
|
|
while nonNil !curr do
|
|
match !curr with
|
|
(instr'::t) ->
|
|
let sz = !codebuf_size
|
|
let old_buf_size = Array.length !codebuf
|
|
let new_size = sz + 1
|
|
if new_size > old_buf_size then begin
|
|
let old = !codebuf
|
|
let new' = Array.zeroCreate (max new_size (old_buf_size * 4))
|
|
Array.blit old 0 new' 0 sz;
|
|
codebuf := new';
|
|
end;
|
|
(!codebuf).[sz] <- instr';
|
|
incr codebuf_size;
|
|
curr := t;
|
|
| [] -> ()
|
|
done;
|
|
done;
|
|
{bb with bblockInstrs = Array.sub !codebuf 0 !codebuf_size}
|
|
|
|
(* Map each instruction in a basic block to a more complicated block that *)
|
|
(* may involve internal branching, but which will still have one entry *)
|
|
(* label and one exit label. This is used, for example, when macro-expanding *)
|
|
(* complicated high-level ILX instructions. *)
|
|
(* The morphing function is told the name of the input and output labels *)
|
|
(* that must be used for the generated block. *)
|
|
(* Optimize the case where an instruction gets mapped to a *)
|
|
(* straightline sequence of instructions by allowing the morphing *)
|
|
(* function to return a special result for this case. *)
|
|
(* *)
|
|
(* Let [i] be the instruction being morphed. If [i] is a control-flow *)
|
|
(* then instruction then [f] must return either a control-flow terminated *)
|
|
(* sequence of instructions or a block both of which must targets the same labels *)
|
|
(* (or a subset of the labels) targeted in [i]. If [i] *)
|
|
(* is not a if not a control-flow instruction then [f] *)
|
|
(* must return a block targeting the given output label. *)
|
|
let commit_acc_bblock sofar =
|
|
let sofar = List.rev sofar (* fragments pushed in reverse *)
|
|
let nres =
|
|
let len = ref 0 (* 1: make room for final branch instruction *)
|
|
List.iter (fun l -> len := !len + List.length l) sofar;
|
|
!len
|
|
let res = Array.create nres I_ret
|
|
let count = ref 0
|
|
sofar |> List.iterSquared (fun i -> res.[!count] <- i; incr count) ;
|
|
assert(!count = nres);
|
|
res
|
|
|
|
let rec bblock_loop f bb curr_bblock_inplab curri_inplab curri_outlab sofar instrs =
|
|
match instrs with
|
|
| (i::rest) ->
|
|
let res = f curri_inplab curri_outlab i
|
|
begin match res with
|
|
(* First possibility: return a sequence of instructions. No *)
|
|
(* addresses get consumed. *)
|
|
| Choice1Of2 is' ->
|
|
bblock_loop f bb curr_bblock_inplab curri_inplab curri_outlab (is' :: sofar) rest
|
|
| Choice2Of2 middle_bblock ->
|
|
let before_bblock =
|
|
let instrs = commit_acc_bblock ([I_br curri_inplab] :: sofar)
|
|
mk_bblock {bblockLabel=curr_bblock_inplab;bblockInstrs=instrs}
|
|
if checking && unique_entry_of_code middle_bblock <> curri_inplab then
|
|
dprintn ("*** warning when transforming bblock "^string_of_code_label bb.bblockLabel^": bblock2code_instr2code: input label of returned block does not match the expected label while converting an instruction to a block.");
|
|
let after_blocks =
|
|
match rest with
|
|
| [] ->
|
|
(*
|
|
if checking && List.mem curri_outlab (exits_of_code middle_bblock) then
|
|
dprintn ("*** warning when transforming bblock "^string_of_code_label bb.bblockLabel^": bblock2code_instr2code: output label of transformed control flow instruction should not use the label provided for non-control-flow instructions.");
|
|
*)
|
|
[] (* the bblock has already been transformed *)
|
|
| _ ->
|
|
(*
|
|
if checking && unique_exit_of_code middle_bblock <> curri_outlab then
|
|
dprintn ("*** warning when transforming bblock "^string_of_code_label bb.bblockLabel^": bblock2code_instr2code: output label of returned block does not match the expected label while converting an instruction to a block.");
|
|
*)
|
|
let new_curri_inlab = generate_code_label ()
|
|
let new_curri_outlab = generate_code_label ()
|
|
[ bblock_loop f bb curri_outlab new_curri_inlab new_curri_outlab [] rest ]
|
|
|
|
check_code
|
|
(mk_group_block
|
|
( curri_inplab :: (match rest with [] -> [] | _ -> [ curri_outlab ]),
|
|
before_bblock :: middle_bblock :: after_blocks))
|
|
end
|
|
| [] ->
|
|
let instrs = commit_acc_bblock sofar
|
|
mk_bblock {bblockLabel=curr_bblock_inplab;bblockInstrs=instrs}
|
|
|
|
let bblock2code_instr2code
|
|
(f:ILCodeLabel -> ILCodeLabel -> ILInstr -> Choice<ILInstr list, ILCode> )
|
|
bb =
|
|
bblock_loop f bb
|
|
bb.bblockLabel
|
|
(generate_code_label ())
|
|
(generate_code_label ()) [] (Array.to_list bb.bblockInstrs)
|
|
|
|
let rec block_bblock2code_typ2typ ((fbb,fty) as f) x =
|
|
match x with
|
|
| ILBasicBlock bblock -> fbb bblock
|
|
| GroupBlock (locs,l) -> GroupBlock(locs,List.map (code_bblock2code_typ2typ f) l)
|
|
| TryBlock (tryb,seh) ->
|
|
TryBlock (code_bblock2code_typ2typ f tryb,
|
|
begin match seh with
|
|
| FaultBlock b -> FaultBlock (code_bblock2code_typ2typ f b)
|
|
| FinallyBlock b -> FinallyBlock (code_bblock2code_typ2typ f b)
|
|
| FilterCatchBlock clsl ->
|
|
FilterCatchBlock
|
|
(List.map (fun (flt,ctch) ->
|
|
(match flt with
|
|
CodeFilter fltcode -> CodeFilter (code_bblock2code_typ2typ f fltcode)
|
|
| TypeFilter ty -> TypeFilter (fty ty)),
|
|
code_bblock2code_typ2typ f ctch) clsl)
|
|
end)
|
|
| RestrictBlock (ls,c) -> RestrictBlock (ls,code_bblock2code_typ2typ f c)
|
|
|
|
and code_bblock2code_typ2typ f (c:ILCode) = check_code (block_bblock2code_typ2typ f c)
|
|
let topcode_bblock2code_typ2typ f (c:ILCode) = code_bblock2code_typ2typ f c
|
|
|
|
let rec block_bblock2code f x =
|
|
match x with
|
|
| ILBasicBlock bblock -> f bblock
|
|
| GroupBlock (locs,l) -> GroupBlock(locs,List.map (code_bblock2code f) l)
|
|
| TryBlock (tryb,seh) ->
|
|
TryBlock (code_bblock2code f tryb,
|
|
begin match seh with
|
|
| FaultBlock b -> FaultBlock (code_bblock2code f b)
|
|
| FinallyBlock b -> FinallyBlock (code_bblock2code f b)
|
|
| FilterCatchBlock clsl ->
|
|
FilterCatchBlock
|
|
(List.map (fun (flt,ctch) ->
|
|
(match flt with
|
|
|CodeFilter fltcode -> CodeFilter (code_bblock2code f fltcode)
|
|
| TypeFilter ty -> flt),
|
|
code_bblock2code f ctch) clsl)
|
|
end)
|
|
| RestrictBlock (ls,c) -> RestrictBlock (ls,code_bblock2code f c)
|
|
|
|
and code_bblock2code f (c:ILCode) = check_code (block_bblock2code f c)
|
|
let topcode_bblock2code f (c:ILCode) = code_bblock2code f c
|
|
|
|
(* --------------------------------------------------------------------
|
|
* Standard morphisms - mapping types etc.
|
|
* -------------------------------------------------------------------- *)
|
|
|
|
let rec typ_tref2tref f x =
|
|
match x with
|
|
| Type_ptr t -> Type_ptr (typ_tref2tref f t)
|
|
| Type_fptr x ->
|
|
Type_fptr
|
|
{ callsigCallconv=x.callsigCallconv;
|
|
callsigArgs=List.map (typ_tref2tref f) x.callsigArgs;
|
|
callsigReturn=typ_tref2tref f x.callsigReturn}
|
|
| Type_byref t -> Type_byref (typ_tref2tref f t)
|
|
| Type_boxed cr -> Type_boxed (tspec_tref2tref f cr)
|
|
| Type_value ir -> Type_value (tspec_tref2tref f ir)
|
|
| Type_array (s,ty) -> Type_array (s,typ_tref2tref f ty)
|
|
| Type_tyvar v -> Type_tyvar v
|
|
| x -> x
|
|
and tspec_tref2tref f (x:ILTypeSpec) =
|
|
ILTypeSpec.Create(f x.TypeRef, List.map (typ_tref2tref f) x.GenericArgs)
|
|
|
|
|
|
let rec typ_scoref2scoref_tyvar2typ ((fscope,ftyvar) as fs)x =
|
|
match x with
|
|
| Type_ptr t -> Type_ptr (typ_scoref2scoref_tyvar2typ fs t)
|
|
| Type_fptr t -> Type_fptr (callsig_scoref2scoref_tyvar2typ fs t)
|
|
| Type_byref t -> Type_byref (typ_scoref2scoref_tyvar2typ fs t)
|
|
| Type_boxed cr -> Type_boxed (tspec_scoref2scoref_tyvar2typ fs cr)
|
|
| Type_value ir -> Type_value (tspec_scoref2scoref_tyvar2typ fs ir)
|
|
| Type_array (s,ty) -> Type_array (s,typ_scoref2scoref_tyvar2typ fs ty)
|
|
| Type_tyvar v -> ftyvar v
|
|
| x -> x
|
|
and tspec_scoref2scoref_tyvar2typ fs (x:ILTypeSpec) =
|
|
ILTypeSpec.Create(tref_scoref2scoref (fst fs) x.TypeRef,typs_scoref2scoref_tyvar2typ fs x.GenericArgs)
|
|
and callsig_scoref2scoref_tyvar2typ f x =
|
|
{ callsigCallconv=x.callsigCallconv;
|
|
callsigArgs=List.map (typ_scoref2scoref_tyvar2typ f) x.callsigArgs;
|
|
callsigReturn=typ_scoref2scoref_tyvar2typ f x.callsigReturn}
|
|
and typs_scoref2scoref_tyvar2typ f i = List.map (typ_scoref2scoref_tyvar2typ f) i
|
|
and gparams_scoref2scoref_tyvar2typ f i = List.map (gparam_scoref2scoref_tyvar2typ f) i
|
|
and gparam_scoref2scoref_tyvar2typ f i = i
|
|
and tref_scoref2scoref fscope (x:ILTypeRef) =
|
|
ILTypeRef.Create(scope=fscope x.Scope, enclosing=x.Enclosing, name = x.Name)
|
|
|
|
|
|
let callsig_typ2typ f x =
|
|
{ callsigCallconv=x.callsigCallconv;
|
|
callsigArgs=List.map f x.callsigArgs;
|
|
callsigReturn=f x.callsigReturn}
|
|
|
|
let gparam_typ2typ f gf = {gf with gpConstraints=List.map f gf.gpConstraints}
|
|
let gparams_typ2typ f gfs = List.map (gparam_typ2typ f) gfs
|
|
let typs_typ2typ f x = List.map f x
|
|
let mref_typ2typ f (x:ILMethodRef) =
|
|
ILMethodRef.Create(enclosingTypeRef=tref_of_typ (f (Type_boxed (mk_nongeneric_tspec x.EnclosingTypeRef))),
|
|
callingConv=x.CallingConv,
|
|
name=x.Name,
|
|
genericArity=x.GenericArity,
|
|
argTypes= List.map f x.ArgTypes,
|
|
returnType= f x.ReturnType)
|
|
|
|
|
|
type formal_scope_ctxt = Choice<ILMethodSpec, ILFieldSpec, IlxUnionSpec>
|
|
|
|
let mspec_typ2typ (((factualty : ILType -> ILType) , (fformalty: formal_scope_ctxt -> ILType -> ILType)) as fs) x =
|
|
let x1,x2,x3 = dest_mspec x
|
|
mk_mref_mspec_in_typ(mref_typ2typ (fformalty (Choice1Of3 x)) x1,
|
|
factualty x2,
|
|
typs_typ2typ factualty x3)
|
|
|
|
let fref_typ2typ f x =
|
|
{ x with frefParent = tref_of_typ (f (Type_boxed (mk_nongeneric_tspec x.frefParent)));
|
|
frefType= f x.frefType }
|
|
let fspec_typ2typ ((factualty,(fformalty : formal_scope_ctxt -> ILType -> ILType)) as fs) x =
|
|
{ fspecFieldRef=fref_typ2typ (fformalty (Choice2Of3 x)) x.fspecFieldRef;
|
|
fspecEnclosingType= factualty x.fspecEnclosingType }
|
|
|
|
let cattr_typ2typ f c =
|
|
{ c with customMethod = mspec_typ2typ (f, (fun _ -> f)) c.customMethod }
|
|
|
|
let cattrs_typ2typ f cs =
|
|
mk_custom_attrs (List.map (cattr_typ2typ f) (dest_custom_attrs cs))
|
|
|
|
let fdef_typ2typ ftype fd = {fd with fdType=ftype fd.fdType;
|
|
fdCustomAttrs=cattrs_typ2typ ftype fd.fdCustomAttrs}
|
|
|
|
let alts_typ2typ f alts =
|
|
Array.map (fun alt -> { alt with altFields = Array.map (fdef_typ2typ f) alt.altFields;
|
|
altCustomAttrs = cattrs_typ2typ f alt.altCustomAttrs }) alts
|
|
|
|
let curef_typ2typ f (IlxUnionRef(s,alts,nullPermitted)) =
|
|
IlxUnionRef(s,alts_typ2typ f alts,nullPermitted)
|
|
|
|
let local_typ2typ f l = {l with localType = f l.localType}
|
|
let freevar_typ2typ f l = {l with fvType = f l.fvType}
|
|
let varargs_typ2typ f varargs = Option.map (List.map f) varargs
|
|
(* REVIEW: convert varargs *)
|
|
let instr_typ2typ ((factualty,fformalty) as fs) i =
|
|
let factualty = factualty (Some i)
|
|
let conv_fspec fr = fspec_typ2typ (factualty,fformalty (Some i)) fr
|
|
let conv_mspec mr = mspec_typ2typ (factualty,fformalty (Some i)) mr
|
|
match i with
|
|
| I_calli (a,mref,varargs) -> I_calli (a,callsig_typ2typ (factualty) mref,varargs_typ2typ factualty varargs)
|
|
| I_call (a,mr,varargs) -> I_call (a,conv_mspec mr,varargs_typ2typ factualty varargs)
|
|
| I_callvirt (a,mr,varargs) -> I_callvirt (a,conv_mspec mr,varargs_typ2typ factualty varargs)
|
|
| I_callconstraint (a,ty,mr,varargs) -> I_callconstraint (a,factualty ty,conv_mspec mr,varargs_typ2typ factualty varargs)
|
|
| I_newobj (mr,varargs) -> I_newobj (conv_mspec mr,varargs_typ2typ factualty varargs)
|
|
| I_ldftn mr -> I_ldftn (conv_mspec mr)
|
|
| I_ldvirtftn mr -> I_ldvirtftn (conv_mspec mr)
|
|
| I_other e when is_ilx_ext_instr e ->
|
|
begin match (dest_ilx_ext_instr e) with
|
|
| (EI_ldftn_then_call (mr1,(a,mr2,varargs))) ->
|
|
mk_IlxInstr (EI_ldftn_then_call (conv_mspec mr1,(a, conv_mspec mr2, varargs_typ2typ factualty varargs)))
|
|
| (EI_ld_instance_ftn_then_newobj (mr1,callsig,(mr2,varargs2))) ->
|
|
mk_IlxInstr (EI_ld_instance_ftn_then_newobj
|
|
(conv_mspec mr1,
|
|
callsig_typ2typ (fformalty (Some i) (Choice1Of3 mr2)) callsig,
|
|
(conv_mspec mr2, varargs_typ2typ factualty varargs2)))
|
|
| _ -> i
|
|
end
|
|
| I_ldfld (a,b,fr) -> I_ldfld (a,b,conv_fspec fr)
|
|
| I_ldsfld (a,fr) -> I_ldsfld (a,conv_fspec fr)
|
|
| I_ldsflda (fr) -> I_ldsflda (conv_fspec fr)
|
|
| I_ldflda fr -> I_ldflda (conv_fspec fr)
|
|
| I_stfld (a,b,fr) -> I_stfld (a,b,conv_fspec fr)
|
|
| I_stsfld (a,fr) -> I_stsfld (a,conv_fspec fr)
|
|
| I_castclass typ -> I_castclass (factualty typ)
|
|
| I_isinst typ -> I_isinst (factualty typ)
|
|
| I_initobj typ -> I_initobj (factualty typ)
|
|
| I_cpobj typ -> I_cpobj (factualty typ)
|
|
| I_stobj (al,vol,typ) -> I_stobj (al,vol,factualty typ)
|
|
| I_ldobj (al,vol,typ) -> I_ldobj (al,vol,factualty typ)
|
|
| I_box typ -> I_box (factualty typ)
|
|
| I_unbox typ -> I_unbox (factualty typ)
|
|
| I_unbox_any typ -> I_unbox_any (factualty typ)
|
|
| I_ldelem_any (shape,typ) -> I_ldelem_any (shape,factualty typ)
|
|
| I_stelem_any (shape,typ) -> I_stelem_any (shape,factualty typ)
|
|
| I_newarr (shape,typ) -> I_newarr (shape,factualty typ)
|
|
| I_ldelema (ro,shape,typ) -> I_ldelema (ro,shape,factualty typ)
|
|
| I_sizeof typ -> I_sizeof (factualty typ)
|
|
| I_ldtoken tok ->
|
|
begin match tok with
|
|
Token_type typ -> I_ldtoken (Token_type (factualty typ))
|
|
| Token_method mr -> I_ldtoken (Token_method (conv_mspec mr))
|
|
| Token_field fr -> I_ldtoken (Token_field (conv_fspec fr))
|
|
end
|
|
| x -> x
|
|
|
|
let return_typ2typ f (r:ILReturnValue) = {r with returnType=f r.Type; returnCustomAttrs=cattrs_typ2typ f r.returnCustomAttrs}
|
|
let param_typ2typ f p = {p with paramType=f p.paramType; paramCustomAttrs=cattrs_typ2typ f p.paramCustomAttrs}
|
|
|
|
let mdefs_mdef2mdef f (m:ILMethodDefs) = mk_mdefs (List.map f (dest_mdefs m))
|
|
let fdefs_fdef2fdef f (m:ILFieldDefs) = mk_fdefs (List.map f (dest_fdefs m))
|
|
|
|
(* use this when the conversion produces just one type... *)
|
|
let tdefs_tdef2tdef f m = mk_tdefs (List.map f (dest_tdefs m))
|
|
|
|
let tdefs_tdef2tdefs f (m:ILTypeDefs) =
|
|
mk_tdefs (List.foldBack (fun x y -> f x @ y)(dest_tdefs m) [])
|
|
|
|
let module_tdefs2tdefs typesf m =
|
|
{m with modulTypeDefs=typesf m.modulTypeDefs}
|
|
|
|
let locals_typ2typ f ls = List.map (local_typ2typ f) ls
|
|
let freevars_typ2typ f ls = List.map (freevar_typ2typ f) ls
|
|
|
|
let ilmbody_bblock2code_typ2typ_maxstack2maxstack fs il =
|
|
let (finstr,ftype,fmaxstack) = fs
|
|
{il with ilCode=topcode_bblock2code_typ2typ (finstr,ftype) il.ilCode;
|
|
ilLocals = locals_typ2typ ftype il.ilLocals;
|
|
ilMaxStack = fmaxstack il.ilMaxStack }
|
|
|
|
let mbody_details_ilmbody2ilmbody (filmbody) x =
|
|
match x with
|
|
| MethodBody_il il -> MethodBody_il (filmbody il)
|
|
| x -> x
|
|
|
|
let mbody_ilmbody2ilmbody (filmbody) x = mk_mbody (mbody_details_ilmbody2ilmbody filmbody (dest_mbody x))
|
|
|
|
let ospec_typ2typ f (OverridesSpec(mref,ty)) =OverridesSpec(mref_typ2typ f mref, f ty)
|
|
|
|
let mdef_typ2typ_ilmbody2ilmbody fs md =
|
|
let (ftype,filmbody) = fs
|
|
let ftype' = ftype (Some md)
|
|
let body' = mbody_ilmbody2ilmbody (filmbody (Some md)) md.mdBody
|
|
{md with
|
|
mdGenericParams=gparams_typ2typ ftype' md.mdGenericParams;
|
|
mdBody= body';
|
|
mdParams = List.map (param_typ2typ ftype') md.mdParams;
|
|
mdReturn = return_typ2typ ftype' md.mdReturn;
|
|
mdCustomAttrs=cattrs_typ2typ ftype' md.mdCustomAttrs }
|
|
|
|
let fdefs_typ2typ f x = fdefs_fdef2fdef (fdef_typ2typ f) x
|
|
|
|
let mdefs_typ2typ_ilmbody2ilmbody fs x = mdefs_mdef2mdef (mdef_typ2typ_ilmbody2ilmbody fs) x
|
|
|
|
let cuinfo_typ2typ ftype cud =
|
|
{ cud with cudAlternatives = alts_typ2typ ftype cud.cudAlternatives; }
|
|
|
|
|
|
let cloinfo_typ2typ_ilmbody2ilmbody fs clo =
|
|
let (ftype,filmbody) = fs
|
|
let c' = filmbody None (Lazy.force clo.cloCode)
|
|
{ clo with cloFreeVars = freevars_typ2typ ftype clo.cloFreeVars;
|
|
cloCode=notlazy c' }
|
|
|
|
let cloinfo_ilmbody2ilmbody f clo =
|
|
let c' = f (Lazy.force clo.cloCode)
|
|
{ clo with cloCode=notlazy c' }
|
|
|
|
let mimpl_typ2typ f e =
|
|
{ e with
|
|
mimplOverrides = ospec_typ2typ f e.mimplOverrides;
|
|
mimplOverrideBy = mspec_typ2typ (f,(fun _ -> f)) e.mimplOverrideBy; }
|
|
|
|
let edef_typ2typ f e =
|
|
{ e with
|
|
eventType = Option.map f e.eventType;
|
|
eventAddOn = mref_typ2typ f e.eventAddOn;
|
|
eventRemoveOn = mref_typ2typ f e.eventRemoveOn;
|
|
eventFire = Option.map (mref_typ2typ f) e.eventFire;
|
|
eventOther = List.map (mref_typ2typ f) e.eventOther;
|
|
eventCustomAttrs = cattrs_typ2typ f e.eventCustomAttrs }
|
|
|
|
let pdef_typ2typ f p =
|
|
{ p with
|
|
propSet = Option.map (mref_typ2typ f) p.propSet;
|
|
propGet = Option.map (mref_typ2typ f) p.propGet;
|
|
propType = f p.propType;
|
|
propArgs = List.map f p.propArgs;
|
|
propCustomAttrs = cattrs_typ2typ f p.propCustomAttrs }
|
|
|
|
let pdefs_typ2typ f pdefs =
|
|
mk_properties (List.map (pdef_typ2typ f) (dest_pdefs pdefs))
|
|
let edefs_typ2typ f edefs =
|
|
mk_events (List.map (edef_typ2typ f) (dest_edefs edefs))
|
|
|
|
let mimpls_typ2typ f mimpls =
|
|
mk_mimpls (List.map (mimpl_typ2typ f) (dest_mimpls mimpls))
|
|
|
|
let rec tdef_typ2typ_ilmbody2ilmbody_mdefs2mdefs enc fs td =
|
|
let (ftype,filmbody,fmdefs) = fs
|
|
let ftype' = ftype (Some (enc,td)) None
|
|
let mdefs' = fmdefs (enc,td) td.tdMethodDefs
|
|
let fdefs' = fdefs_typ2typ ftype' td.tdFieldDefs
|
|
{td with tdImplements= List.map ftype' td.tdImplements;
|
|
tdGenericParams= gparams_typ2typ ftype' td.tdGenericParams;
|
|
tdExtends = Option.map ftype' td.tdExtends;
|
|
tdMethodDefs=mdefs';
|
|
tdNested=tdefs_typ2typ_ilmbody2ilmbody_mdefs2mdefs (enc@[td]) fs td.tdNested;
|
|
tdFieldDefs=fdefs';
|
|
tdMethodImpls = mimpls_typ2typ ftype' td.MethodImpls;
|
|
tdEvents = edefs_typ2typ ftype' td.Events;
|
|
tdProperties = pdefs_typ2typ ftype' td.Properties;
|
|
tdCustomAttrs = cattrs_typ2typ ftype' td.CustomAttrs;
|
|
tdKind =
|
|
begin match td.tdKind with
|
|
| TypeDef_other e when is_ilx_ext_type_def_kind e ->
|
|
begin match dest_ilx_ext_type_def_kind e with
|
|
| ETypeDef_closure i -> mk_IlxTypeDefKind (ETypeDef_closure (cloinfo_typ2typ_ilmbody2ilmbody (ftype',filmbody (enc,td)) i))
|
|
| ETypeDef_classunion i -> mk_IlxTypeDefKind (ETypeDef_classunion (cuinfo_typ2typ ftype' i))
|
|
end
|
|
| _ -> td.tdKind
|
|
end
|
|
}
|
|
|
|
and tdefs_typ2typ_ilmbody2ilmbody_mdefs2mdefs enc fs tdefs =
|
|
tdefs_tdef2tdef (tdef_typ2typ_ilmbody2ilmbody_mdefs2mdefs enc fs) tdefs
|
|
|
|
(* --------------------------------------------------------------------
|
|
* Derived versions of the above, e.g. with defaults added
|
|
* -------------------------------------------------------------------- *)
|
|
|
|
let manifest_typ2typ f m =
|
|
{ m with
|
|
manifestCustomAttrs = cattrs_typ2typ f m.manifestCustomAttrs }
|
|
|
|
let module_typ2typ_ilmbody2ilmbody_mdefs2mdefs
|
|
((ftype: ILModuleDef -> (ILTypeDef list * ILTypeDef) option -> ILMethodDef option -> ILType -> ILType),
|
|
(filmbody: ILModuleDef -> ILTypeDef list * ILTypeDef -> ILMethodDef option -> ILMethodBody -> ILMethodBody),
|
|
fmdefs) m =
|
|
let ftdefs =
|
|
tdefs_typ2typ_ilmbody2ilmbody_mdefs2mdefs []
|
|
(ftype m,
|
|
filmbody m,
|
|
fmdefs m)
|
|
{ m with modulTypeDefs=ftdefs m.modulTypeDefs;
|
|
modulCustomAttrs=cattrs_typ2typ (ftype m None None) m.modulCustomAttrs;
|
|
modulManifest=Option.map (manifest_typ2typ (ftype m None None)) m.modulManifest }
|
|
|
|
let module_bblock2code_typ2typ_maxstack2maxstack fs x =
|
|
let (fbblock,ftype,fmaxstack) = fs
|
|
let filmbody mod_ctxt tdef_ctxt mdef_ctxt =
|
|
ilmbody_bblock2code_typ2typ_maxstack2maxstack
|
|
(fbblock mod_ctxt tdef_ctxt mdef_ctxt,
|
|
ftype mod_ctxt (Some tdef_ctxt) mdef_ctxt,
|
|
fmaxstack mod_ctxt tdef_ctxt mdef_ctxt)
|
|
let fmdefs mod_ctxt tdef_ctxt =
|
|
mdefs_typ2typ_ilmbody2ilmbody
|
|
(ftype mod_ctxt (Some tdef_ctxt),
|
|
filmbody mod_ctxt tdef_ctxt)
|
|
module_typ2typ_ilmbody2ilmbody_mdefs2mdefs
|
|
(ftype,
|
|
filmbody,
|
|
fmdefs)
|
|
x
|
|
|
|
let module_bblock2code f x =
|
|
module_bblock2code_typ2typ_maxstack2maxstack
|
|
(f,
|
|
(fun mod_ctxt tdef_ctxt mdef_ctxt x -> x),
|
|
(fun mod_ctxt tdef_ctxt mdef_ctxt x -> x)) x
|
|
let module_bblock2code_typ2typ (f1,f2) x =
|
|
module_bblock2code_typ2typ_maxstack2maxstack
|
|
(f1,
|
|
f2,
|
|
(fun mod_ctxt tdef_ctxt mdef_ctxt x -> x)) x
|
|
let module_bblock2code_maxstack2maxstack (f1,f2) x =
|
|
module_bblock2code_typ2typ_maxstack2maxstack
|
|
(f1,
|
|
(fun mod_ctxt tdef_ctxt mdef_ctxt x -> x),
|
|
f2)
|
|
x
|
|
let module_instr2instr_typ2typ (f1,f2) x =
|
|
module_bblock2code_typ2typ
|
|
((fun mod_ctxt tdef_ctxt mdef_ctxt i -> mk_bblock (bblock_instr2instr (f1 mod_ctxt tdef_ctxt mdef_ctxt) i)),
|
|
f2)
|
|
x
|
|
|
|
let topcode_instr2instrs f x =
|
|
topcode_bblock2code
|
|
(fun i -> mk_bblock (bblock_instr2instrs f i))
|
|
x
|
|
let topcode_instr2code f x =
|
|
topcode_bblock2code (bblock2code_instr2code f) x
|
|
|
|
let module_typ2typ ftype y =
|
|
let finstr mod_ctxt tdef_ctxt mdef_ctxt =
|
|
let fty = ftype mod_ctxt (Some tdef_ctxt) mdef_ctxt
|
|
instr_typ2typ ((fun instr_ctxt -> fty), (fun instr_ctxt formal_ctxt -> fty))
|
|
module_instr2instr_typ2typ (finstr,ftype) y
|
|
|
|
|
|
let rec tdef_tdef2tdef f enc td =
|
|
let td' = f enc td
|
|
{td' with tdNested = all_tdefs_tdef2tdef f (enc@[td]) td'.tdNested }
|
|
and all_tdefs_tdef2tdef f enc tds = mk_tdefs (List.map (tdef_tdef2tdef f enc) (dest_tdefs tds))
|
|
|
|
let module_tdef2tdef f m = module_tdefs2tdefs (all_tdefs_tdef2tdef f []) m
|
|
|
|
let module_tref2tref_memoized f modul =
|
|
let fty = memoize (typ_tref2tref f)
|
|
module_typ2typ (fun _ _ _ ty -> fty ty) modul
|
|
|
|
let module_scoref2scoref_memoized f modul =
|
|
module_tref2tref_memoized (tref_scoref2scoref f) modul
|
|
|
|
|
|
|
|
|
|
|
|
|