Math.NET Numerics
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.
 
 
 

3027 lines
136 KiB

// (c) Microsoft Corporation. All rights reserved
#light
#if STANDALONE_METADATA
module (* internal *) FSharp.PowerPack.Metadata.Reader.Internal.Tast
open System.Collections.Generic
open FSharp.PowerPack.Metadata.Reader.Internal.AbstractIL.IL
open FSharp.PowerPack.Metadata.Reader.Internal.PrettyNaming
open FSharp.PowerPack.Metadata.Reader.Internal.Prelude
#else
module (* internal *) Microsoft.FSharp.Compiler.Tast
open System.Collections.Generic
open Internal.Utilities
open Internal.Utilities.Pervasives
open Microsoft.FSharp.Compiler.AbstractIL
open Microsoft.FSharp.Compiler.AbstractIL.IL
open Microsoft.FSharp.Compiler.AbstractIL.Internal
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics
open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.ErrorLogger
open Microsoft.FSharp.Compiler.Lib
open Microsoft.FSharp.Compiler.PrettyNaming
open Microsoft.FSharp.Compiler.Sreflect
open Microsoft.FSharp.Text.Printf
#endif
///verboseStamps: print #stamp on each id -- very verbose - but sometimes useful. Turn on using '--stamps'
let verboseStamps = ref false
/// Unique name generator for stamps attached to lambdas and object expressions
type uniq = int64
let new_uniq = let i = ref 0L in fun () -> i := !i + 1L; !i
type stamp = int64
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
let new_stamp = let i = ref 0L in fun () -> i := !i + 1L; !i
//-------------------------------------------------------------------------
// Flags
type ValInlineInfo =
/// Indicates the value must always be inlined
| PseudoValue
/// Indictes the value is inlined but the code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined
| AlwaysInline
| OptionalInline
| NeverInline
let mustinline = function PseudoValue | AlwaysInline -> true | OptionalInline | NeverInline -> false
type ValRecursiveScopeInfo =
/// Set while the value is within its recursive scope. The flag indicates if the value has been eagerly generalized and accepts generic-recursive calls
| ValInRecScope of bool
/// The normal value for this flag when the value is not within its recursive scope
| ValNotInRecScope
type ValMutability =
| Immutable
| Mutable
type TyparDynamicReq =
/// Indicates the type parameter is not needed at runtime and may be eliminated
| NoDynamicReq
/// Indicates the type parameter is needed at runtime and may not be eliminated
| DynamicReq
type ValBaseOrThisInfo =
| CtorThisVal
| BaseVal
| NormalVal
| MemberThisVal
//---------------------------------------------------------------------------
// Flags on values
//---------------------------------------------------------------------------
module ValFlags = begin
let base_of_vflags x =
match (x &&& 0b0000000000000110L) with
| 0b0000000000000000L -> BaseVal
| 0b0000000000000010L -> CtorThisVal
| 0b0000000000000100L -> NormalVal
| 0b0000000000000110L -> MemberThisVal
| _ -> failwith "base_of_vflags"
let encode_base_of_vflags x val_flags =
(val_flags &&& ~~~0b0000000000000110L)
||| (match x with
| BaseVal -> 0b0000000000000000L
| CtorThisVal -> 0b0000000000000010L
| NormalVal -> 0b0000000000000100L
| MemberThisVal -> 0b0000000000000110L)
let is_compgen_of_vflags x = (x &&& 0b0000000000001000L) <> 0x0L
let encode_compgen_of_vflags b val_flags =
if b then ( val_flags ||| 0b0000000000001000L)
else ( val_flags &&& ~~~ 0b0000000000001000L)
let inline_info_of_vflags x =
match (x &&& 0b0000000000110000L) with
| 0b0000000000000000L -> PseudoValue
| 0b0000000000010000L -> AlwaysInline
| 0b0000000000100000L -> OptionalInline
| 0b0000000000110000L -> NeverInline
| _ -> failwith "inline_info_of_vflags"
let encode_mustinline_of_vflags x val_flags =
(val_flags &&& ~~~0b0000000000110000L)
||| (match x with
| PseudoValue -> 0b0000000000000000L
| AlwaysInline -> 0b0000000000010000L
| OptionalInline -> 0b0000000000100000L
| NeverInline -> 0b0000000000110000L)
let mutability_of_vflags x =
match (x &&& 0b0000000001000000L) with
| 0b0000000000000000L -> Immutable
| 0b0000000001000000L -> Mutable
| _ -> failwith "mutability_of_vflags"
let encode_mutability_of_vflags x val_flags =
(val_flags &&& ~~~0b0000000001000000L)
||| (match x with
| Immutable -> 0b0000000000000000L
| Mutable -> 0b0000000001000000L)
let is_topbind_of_vflags x =
match (x &&& 0b0000000010000000L) with
| 0b0000000000000000L -> false
| 0b0000000010000000L -> true
| _ -> failwith "is_topbind_of_vflags"
let encode_is_topbind_of_vflags x val_flags =
(val_flags &&& ~~~0b0000000010000000L)
||| (match x with
| false -> 0b0000000000000000L
| true -> 0b0000000010000000L)
let is_extension_member_of_vflags x =
match (x &&& 0b0000000100000000L) with
| 0b0000000000000000L -> false
| 0b0000000100000000L -> true
| _ -> failwith "is_extension_member_of_vflags"
let encode_isext_of_vflags x val_flags =
(val_flags &&& ~~~0b0000000100000000L)
||| (match x with
| false -> 0b0000000000000000L
| true -> 0b0000000100000000L)
let is_incr_class_of_vflags x =
match (x &&& 0b0000001000000000L) with
| 0b0000000000000000L -> false
| 0b0000001000000000L -> true
| _ -> failwith "is_incr_class_of_vflags"
let encode_is_incr_class_of_vflags x val_flags =
(val_flags &&& ~~~0b0000001000000000L)
||| (match x with
| false -> 0b0000000000000000L
| true -> 0b0000001000000000L)
let is_tyfunc_of_vflags x =
match (x &&& 0b0000010000000000L) with
| 0b0000000000000000L -> false
| 0b0000010000000000L -> true
| _ -> failwith "is_incr_class_of_vflags"
let encode_is_tyfunc_of_vflags x val_flags =
(val_flags &&& ~~~0b0000010000000000L)
||| (match x with
| false -> 0b0000000000000000L
| true -> 0b0000010000000000L)
let vrec_of_vflags x = match (x &&& 0b0001100000000000L) with
| 0b0000000000000000L -> ValNotInRecScope
| 0b0000100000000000L -> ValInRecScope(true)
| 0b0001000000000000L -> ValInRecScope(false)
| _ -> failwith "vrec_of_vflags"
let encode_vrec_of_vflags x val_flags =
(val_flags &&& ~~~0b0001100000000000L)
||| (match x with
| ValNotInRecScope -> 0b0000000000000000L
| ValInRecScope(true) -> 0b0000100000000000L
| ValInRecScope(false) -> 0b0001000000000000L)
let is_notailcall_hint_of_vflags x =
match (x &&& 0b0010000000000000L) with
| 0b0000000000000000L -> false
| 0b0010000000000000L -> true
| _ -> failwith "is_notailcall_hint_of_vflags"
let encode_notailcall_hint_of_vflags x val_flags =
(val_flags &&& ~~~0b0010000000000000L)
||| (match x with
| false -> 0b0000000000000000L
| true -> 0b0010000000000000L)
let encode (vrec,baseOrThis,isCompGen,mustinline,isMutable,isTopBinding,isExtensionMember,isImplicitCtor,isTyFunc) =
0L |> encode_vrec_of_vflags vrec
|> encode_base_of_vflags baseOrThis
|> encode_compgen_of_vflags isCompGen
|> encode_mustinline_of_vflags mustinline
|> encode_mutability_of_vflags isMutable
|> encode_is_topbind_of_vflags isTopBinding
|> encode_isext_of_vflags isExtensionMember
|> encode_is_incr_class_of_vflags isImplicitCtor
|> encode_is_tyfunc_of_vflags isTyFunc
end
type TyparKind =
| KindType
| KindMeasure
member x.AttrName =
match x with
| KindType -> None
| KindMeasure -> Some "Measure"
override x.ToString() =
match x with
| KindType -> "type"
| KindMeasure -> "measure"
type TyparRigidity =
/// Indicates the type parameter can't be solved
| TyparRigid
/// Indicates we give a warning if the type parameter is ever solved
| TyparWarnIfNotRigid
/// Indicates the type parameter is an inference variable may be solved
| TyparFlexible
/// Indicates the type parameter derives from an '_' anonymous type
/// For units-of-measure, we give a warning if this gets solved to '1'
| TyparAnon
module TyparFlags = begin
(* encode typar flags into a bit field *)
let from_error_of_tpflags x = (x &&& 0b00000000010) <> 0x0
let encode_from_error_of_tpflags b typar_flags =
if b then ( typar_flags ||| 0b00000000010)
else ( typar_flags &&& ~~~ 0b00000000010)
let compgen_of_tpflags x = (x &&& 0b00000000100) <> 0x0
let encode_compgen_of_tpflags b typar_flags =
if b then ( typar_flags ||| 0b00000000100)
else ( typar_flags &&& ~~~ 0b00000000100)
let static_req_of_tpflags x =
match (x &&& 0b00000001000) with
| 0b00000000000 -> NoStaticReq
| 0b00000001000 -> HeadTypeStaticReq
| _ -> failwith "static_req_of_tpflags"
let encode_static_req_of_tpflags x typar_flags =
(typar_flags &&& ~~~0b00000001000)
||| (match x with
| NoStaticReq -> 0b00000000000
| HeadTypeStaticReq -> 0b00000001000)
let rigid_of_tpflags x =
match (x &&& 0b00001100000) with
| 0b00000000000 -> TyparRigid
| 0b00000100000 -> TyparWarnIfNotRigid
| 0b00001000000 -> TyparFlexible
| 0b00001100000 -> TyparAnon
| _ -> failwith "rigid_of_tpflags"
let encode_rigid_of_tpflags x typar_flags =
(typar_flags &&& ~~~0b00001100000)
||| (match x with
| TyparRigid -> 0b00000000000
| TyparWarnIfNotRigid -> 0b00000100000
| TyparFlexible -> 0b00001000000
| TyparAnon -> 0b00001100000)
let kind_of_tpflags x =
match (x &&& 0b00010000000) with
| 0b00000000000 -> KindType
| 0b00010000000 -> KindMeasure
| _ -> failwith "kind_of_tpflags"
let encode_kind_of_tpflags x typar_flags =
(typar_flags &&& ~~~0b00010000000)
||| (match x with
| KindType -> 0b00000000000
| KindMeasure -> 0b00010000000)
let dynamic_req_of_tpflags x =
match (x &&& 0b01000000000) with
| 0b00000000000 -> NoDynamicReq
| 0b01000000000 -> DynamicReq
| _ -> failwith "dynamic_req_of_tpflags"
let encode_dynamic_req_of_tpflags x typar_flags =
(typar_flags &&& ~~~0b01000000000)
||| (match x with
| NoDynamicReq -> 0b00000000000
| DynamicReq -> 0b01000000000)
let encode (kind,rigid,isFromError,isCompGen,staticReq,dynamicReq) =
0 |> encode_kind_of_tpflags kind
|> encode_rigid_of_tpflags rigid
|> encode_from_error_of_tpflags isFromError
|> encode_compgen_of_tpflags isCompGen
|> encode_static_req_of_tpflags staticReq
|> encode_dynamic_req_of_tpflags dynamicReq
end
let unassignedTyparName = "?"
exception UndefinedName of int * string * ident * string list
exception InternalUndefinedItemRef of string * string * string * string
// Type definitions, exception definitions, module definitions and
// namespace definitions are all 'entities'. These have too much in common to make it
// worth factoring them out as separate types.
//
// Tycons, exncs and moduls are all modelled via tycon_specs,
// they have different name-resolution logic.
// For example, an excon ABC really correspond to a type called
// ABCException with a union case ABC. At the moment they are
// simply indexed in the excon table as the discriminator constructor ABC.
type Entity =
{ mutable Data: EntityData; }
member x.MangledName = x.Data.entity_name
member x.DisplayName = DemangleGenericTypeName x.Data.entity_name
member x.DisplayNameWithUnderscoreTypars =
let nm = x.DisplayName
match x.Typars(x.Range) with
| [] -> x.DisplayName
| tps -> x.DisplayName + "<" + String.concat "," (Array.create tps.Length "_") + ">"
member x.Range = x.Data.entity_range
member x.Stamp = x.Data.entity_stamp
member x.Attribs = x.Data.entity_attribs
member x.XmlDoc = x.Data.entity_xmldoc
member x.ModuleOrNamespaceType = x.Data.entity_modul_contents.Force()
member x.TypeContents = x.Data.entity_tycon_tcaug
member x.TypeOrMeasureKind = x.Data.entity_kind
member x.Id = ident(x.MangledName, x.Range)
member x.TypeReprInfo = x.Data.entity_tycon_repr
member x.ExceptionInfo = x.Data.entity_exn_info
member x.IsExceptionDecl = match x.ExceptionInfo with TExnNone -> false | _ -> true
member x.DemangledExceptionName =
let nm = x.MangledName
if x.IsExceptionDecl then DemangleExceptionName nm else nm
member x.Typars(m) = x.Data.entity_typars.Force(m) // lazy because it may read metadata, must provide a context "range" in case error occurs reading metadata
member x.TyparsNoRange = x.Typars(x.Range)
member x.TypeAbbrev = x.Data.entity_tycon_abbrev
member x.IsTypeAbbrev = x.TypeAbbrev.IsSome
member x.TypeReprAccessibility = x.Data.entity_tycon_repr_accessibility
member x.CompiledReprCache = x.Data.entity_il_repr_cache
member x.PublicPath = x.Data.entity_pubpath
member x.Accessibility = x.Data.entity_accessiblity
member x.IsPrefixDisplay = x.Data.entity_uses_prefix_display
member x.IsModuleOrNamespace = x.Data.entity_is_modul_or_namespace
member x.IsNamespace = x.IsModuleOrNamespace && (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace -> true | _ -> false)
member x.IsModule = x.IsModuleOrNamespace && (match x.ModuleOrNamespaceType.ModuleOrNamespaceKind with Namespace -> false | _ -> true)
member x.CompilationPathOpt = x.Data.entity_cpath
member x.CompilationPath = match x.CompilationPathOpt with Some cpath -> cpath | None -> error(Error("type/module "^x.MangledName^" is not a concrete module or type",x.Range))
member x.AllFieldTable =
match x.TypeReprInfo with
| Some (TRecdRepr x | TFsObjModelRepr {fsobjmodel_rfields=x}) -> x
| _ ->
match x.ExceptionInfo with
| TExnFresh x -> x
| _ ->
{ rfields_by_index = [| |];
rfields_by_name = NameMap.empty }
member x.AllFieldsArray = x.AllFieldTable.rfields_by_index
member x.AllFieldsAsList = x.AllFieldsArray |> Array.to_list
// NOTE: This method is over-used...
member x.AllInstanceFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsStatic)
member x.TrueFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsCompilerGenerated)
member x.TrueInstanceFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsStatic && not f.IsCompilerGenerated)
member x.GetFieldByIndex(n) = x.AllFieldTable.FieldByIndex(n)
member x.GetFieldByName(n) = x.AllFieldTable.FieldByName(n)
member x.UnionTypeInfo =
match x.Data.entity_tycon_repr with
| Some (TFiniteUnionRepr x) -> Some x
| _ -> None
member x.UnionCasesArray =
match x.UnionTypeInfo with
| Some x -> x.funion_ucases.ucases_by_index
| None -> [| |]
member x.UnionCasesAsList = x.UnionCasesArray |> Array.to_list
member x.GetUnionCaseByName(n) =
match x.UnionTypeInfo with
| Some x -> NameMap.tryfind n x.funion_ucases.ucases_by_name
| None -> None
// OSGN support
static member NewUnlinked() : Entity = { Data = nullable_slot_empty() }
static member New reason data : Entity =
if !verboseStamps then
dprintf "entity %s#%d (%s)\n" data.entity_name data.entity_stamp reason;
{ Data = data }
member x.Link(tg) = x.Data <- nullable_slot_full(tg)
member x.IsLinked = match box x.Data with null -> false | _ -> true
override x.ToString() = x.MangledName
member x.FSharpObjectModelTypeInfo =
match x.Data.entity_tycon_repr with
| Some (TFsObjModelRepr x) -> x
| _ -> failwith "not an F# object model type definition"
member x.IsILTycon = match x.TypeReprInfo with | Some (TILObjModelRepr _) -> true | _ -> false
member x.ILTyconInfo = match x.TypeReprInfo with | Some (TILObjModelRepr (a,b,c)) -> (a,b,c) | _ -> failwith "not a .NET type definition"
member x.ILTyconRawMetadata = let _,_,td = x.ILTyconInfo in td
member x.IsUnionTycon = match x.TypeReprInfo with | Some (TFiniteUnionRepr _) -> true | _ -> false
member x.UnionInfo = match x.TypeReprInfo with | Some (TFiniteUnionRepr x) -> Some x | _ -> None
member x.IsRecordTycon = match x.TypeReprInfo with | Some (TRecdRepr _) -> true | _ -> false
member x.IsFSharpObjectModelTycon = match x.TypeReprInfo with | Some (TFsObjModelRepr _) -> true | _ -> false
member x.IsAsmReprTycon = match x.TypeReprInfo with | Some (TAsmRepr _) -> true | _ -> false
member x.IsMeasureableReprTycon = match x.TypeReprInfo with | Some (TMeasureableRepr _) -> true | _ -> false
member x.IsHiddenReprTycon = match x.TypeAbbrev,x.TypeReprInfo with | None,None -> true | _ -> false
member x.IsFSharpInterfaceTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconInterface -> true | _ -> false
member x.IsFSharpDelegateTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconDelegate _ -> true | _ -> false
member x.IsFSharpEnumTycon = x.IsFSharpObjectModelTycon && match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with TTyconEnum -> true | _ -> false
member x.IsFSharpStructTycon =
x.IsFSharpObjectModelTycon &&
match x.FSharpObjectModelTypeInfo.fsobjmodel_kind with
| TTyconClass | TTyconInterface | TTyconDelegate _ -> false
| TTyconStruct | TTyconEnum -> true
member x.IsILStructTycon =
x.IsILTycon &&
let tdef = x.ILTyconRawMetadata
match tdef.tdKind with
| TypeDef_valuetype | TypeDef_enum -> true
| _ -> false
member x.IsStructTycon =
x.IsILStructTycon || x.IsFSharpStructTycon
/// From TAST TyconRef to IL ILTypeRef
member x.CompiledRepresentation =
let il_tref_for_cpath (CompPath(sref,p)) item =
let rec top racc p =
match p with
| [] -> ILTypeRef.Create(sref,[],text_of_path (List.rev (item::racc)))
| (h,istype)::t ->
match istype with
| FSharpModuleWithSuffix | FSharpModule ->
let outerTypeName = (text_of_path (List.rev (h::racc)))
ILTypeRef.Create(sref, (outerTypeName :: List.map (fun (nm,_) -> nm) t),item)
| _ ->
top (h::racc) t
top [] p
assert(not x.IsTypeAbbrev);
cached x.CompiledReprCache (fun () ->
match x.ExceptionInfo with
| TExnAbbrevRepr ecref2 -> ecref2.CompiledRepresentation
| TExnAsmRepr tref -> TyrepNamed(tref,AsObject)
| _ ->
match x.TypeReprInfo with
| Some (TAsmRepr typ) -> TyrepOpen typ
| _ ->
let boxity = if x.IsStructTycon then AsValue else AsObject
TyrepNamed (il_tref_for_cpath x.CompilationPath x.MangledName,boxity))
member x.CompiledRepresentationForTyrepNamed =
match x.CompiledRepresentation with
| TyrepNamed(tref,_) -> tref
| TyrepOpen _ -> invalidOp (sprintf "the type %s has an assembly code representation" x.DisplayNameWithUnderscoreTypars)
and
[<StructuralEquality(false); StructuralComparison(false)>]
EntityData =
{ /// The declared type parameters of the type
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_typars: LazyWithContext<typars,range>;
// MUTABILITY; used only when establishing tycons.
// REVIEW: remove this use of mutabilty
mutable entity_kind : TyparKind;
/// The unique stamp of the "tycon blob". Note the same tycon in signature and implementation get different stamps
entity_stamp: stamp;
/// The name of the type, possibly with `n mangling
entity_name: string;
/// The declaration location for the type constructor
entity_range: range;
/// Indicates the type prefers the "tycon<a,b>" syntax for display etc.
entity_uses_prefix_display: bool;
/// Indicates the "tycon blob" is actually a module
entity_is_modul_or_namespace : bool;
/// The declared accessibility of the representation, not taking signatures into account
entity_tycon_repr_accessibility: Accessibility;
/// The declared attributes for the type
(* MUTABILITY; used only during creation and remapping of tycons *)
mutable entity_attribs: Attribs;
/// The declared representation of the type, i.e. record, union, class etc.
//
// REVIEW: the 'None' value here has two meanings
// - it indicates 'not yet known' during the first 2 phases of establishing type definitions
// - it indicated 'no representation' at all other times, i.e.
// type X
// in signatures
// It would be better to separate these two cases out, by just adding two cases
// to TyconRepresentation and removing the use of 'option'
//
// MUTABILITY; used only during creation and remapping of tycons
mutable entity_tycon_repr: TyconRepresentation option;
/// If non-None, indicates the type is an abbreviation for another type.
mutable entity_tycon_abbrev: typ option; (* MUTABILITY; used only during creation and remapping of tycons *)
/// The methods and properties of the type
mutable entity_tycon_tcaug: TyconAugmentation; (* MUTABILITY; used only during creation and remapping of tycons *)
/// Field used when the 'tycon' is really an exception definition
(* MUTABILITY; used only during creation and remapping of tycons *)
mutable entity_exn_info: ExceptionInfo;
/// This field is used when the 'tycon' is really a module definition. It holds statically nested type definitions and nested modules
(* MUTABILITY: only used during creation and remapping of tycons and *)
(* when compiling fslib to fixup compiler forward references to internal items *)
mutable entity_modul_contents: Lazy<ModuleOrNamespaceType>;
/// The declared documentation for the type or module
entity_xmldoc : XmlDoc;
/// The stable path to the type, e.g. Microsoft.FSharp.Core.FastFunc`2
(* REVIEW: it looks like entity_cpath subsumes this *)
entity_pubpath : PublicPath option; (* where does this live? *)
mutable entity_accessiblity: Accessibility; (* how visible is this? *) (* MUTABILITY; used only during creation and remapping of tycons *)
/// The stable path to the type, e.g. Microsoft.FSharp.Core.FastFunc`2
entity_cpath : CompilationPath option;
/// Used during codegen to hold the ILX representation indicating how to access the type
entity_il_repr_cache : CompiledTypeRepr cache; (* MUTABILITY; *)
}
and ParentRef =
| Parent of TyconRef
| ParentNone
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconAugmentation =
{ /// This is the value implementing the auto-generated comparison
/// semantics if any. It is not present if the type defines its own implementation
/// of IComparable or if the type doesn't implement IComparable implicitly.
mutable tcaug_compare : (ValRef * ValRef) option;
/// This is the value implementing the auto-generated comparison
/// semantics if any. It is not present if the type defines its own implementation
/// of IStructuralComparable or if the type doesn't implement IComparable implicitly.
mutable tcaug_compare_withc : ValRef option;
/// This is the value implementing the auto-generated equality
/// semantics if any. It is not present if the type defines its own implementation
/// of Object.Equals or if the type doesn't override Object.Equals implicitly.
mutable tcaug_equals : (ValRef * ValRef) option;
/// This is the value implementing the auto-generated comparison
/// semantics if any. It is not present if the type defines its own implementation
/// of IStructuralEquatable or if the type doesn't implement IComparable implicitly.
mutable tcaug_hash_and_equals_withc : (ValRef * ValRef) option;
/// True if the type defined an Object.GetHashCode method. In this
/// case we give a warning if we auto-generate a hash method since the semantics may not match up
mutable tcaug_hasObjectGetHashCode : bool;
/// Likewise IStructuralHash::GetHashCode
mutable tcaug_structural_hash: ValRef option;
/// Properties, methods etc.
mutable tcaug_adhoc : (ValRef list) NameMap;
/// Interface implementations - boolean indicates compiler-generated
mutable tcaug_implements : (typ * bool * range) list;
/// Super type, if any
mutable tcaug_super : typ option;
/// Set to true at the end of the scope where proper augmentations are allowed
mutable tcaug_closed : bool;
/// Set to true if the type is determined to be abstract
mutable tcaug_abstract : bool;
}
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconRepresentation =
/// Indicates the type is a class, struct, enum, delegate or interface
| TFsObjModelRepr of TyconObjModelData
/// Indicates the type is a record
| TRecdRepr of TyconRecdFields
/// Indicates the type is a discriminated union
| TFiniteUnionRepr of TyconUnionData
/// Indicates the type is a .NET type
| TILObjModelRepr of
// scope:
ILScopeRef *
// nesting:
ILTypeDef list *
// definition:
ILTypeDef
/// Indicates the type is implemented as IL assembly code using the given closed Abstract IL type
| TAsmRepr of ILType
/// Indicates the type is parameterized on a measure (e.g. float<_>) but erases to some other type (e.g. float)
| TMeasureableRepr of typ
and
TyconObjModelKind =
/// Indicates the type is a class (also used for units-of-measure)
| TTyconClass
/// Indicates the type is an interface
| TTyconInterface
/// Indicates the type is a struct
| TTyconStruct
/// Indicates the type is a delegate with the given Invoke signature
| TTyconDelegate of SlotSig
/// Indicates the type is an enumeration
| TTyconEnum
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconObjModelData =
{ /// Indicates whether the type declaration is a class, interface, enum, delegate or struct
fsobjmodel_kind: TyconObjModelKind;
/// The declared abstract slots of the class, interface or struct
fsobjmodel_vslots: ValRef list;
/// The fields of the class, struct or enum
fsobjmodel_rfields: TyconRecdFields }
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconRecdFields =
{ /// The fields of the record, in declaration order.
rfields_by_index: RecdField array;
/// The fields of the record, indexed by name.
rfields_by_name : RecdField NameMap }
member x.FieldByIndex(n) =
if n >= 0 && n < Array.length x.rfields_by_index then x.rfields_by_index.[n]
else failwith "FieldByIndex"
member x.FieldByName(n) = x.rfields_by_name.TryFind(n)
member x.AllFieldsAsList = x.rfields_by_index |> Array.to_list
member x.TrueFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsCompilerGenerated)
member x.TrueInstanceFieldsAsList = x.AllFieldsAsList |> List.filter (fun f -> not f.IsStatic && not f.IsCompilerGenerated)
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconUnionCases =
{ /// The cases of the discriminated union, in declaration order.
ucases_by_index: UnionCase array;
/// The cases of the discriminated union, indexed by name.
ucases_by_name : UnionCase NameMap
}
member x.GetUnionCaseByIndex(n) =
if n >= 0 && n < x.ucases_by_index.Length then x.ucases_by_index.[n]
else invalidArg "n" "GetUnionCaseByIndex"
member x.UnionCasesAsList = x.ucases_by_index |> Array.to_list
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyconUnionData =
{ /// The cases contained in the discriminated union.
funion_ucases: TyconUnionCases;
/// The ILX data structure representing the discriminated union.
#if STANDALONE_METADATA
#else
funion_ilx_repr: IlxUnionRef cache;
#endif
}
member x.UnionCasesAsList = x.funion_ucases.ucases_by_index |> Array.to_list
and
[<StructuralEquality(false); StructuralComparison(false)>]
UnionCase =
{ /// Data carried by the case.
ucase_rfields: TyconRecdFields;
/// Return type constructed by the case. Normally exactly the type of the enclosing type, sometimes an abbreviation of it
ucase_rty: typ;
/// Name of the case in generated IL code
ucase_il_name: string;
/// Documentation for the case
ucase_xmldoc : XmlDoc;
/// Name/range of the case
ucase_id: ident;
/// Indicates the declared visibility of the union constructor, not taking signatures into account
ucase_access: Accessibility;
/// Attributes, attached to the generated static method to make instances of the case
ucase_attribs: Attribs; }
member uc.Attribs = uc.ucase_attribs
member uc.Range = uc.ucase_id.idRange
member uc.Id = uc.ucase_id
member uc.Accessibility = uc.ucase_access
member uc.DisplayName = uc.Id.idText
member uc.RecdFieldsArray = uc.ucase_rfields.rfields_by_index
member uc.RecdFields = uc.ucase_rfields.rfields_by_index |> Array.to_list
member uc.GetFieldByName nm = uc.ucase_rfields.FieldByName nm
member uc.IsNullary = (uc.ucase_rfields.rfields_by_index.Length = 0)
and
[<StructuralEquality(false); StructuralComparison(false)>]
RecdField =
{ /// Is the field declared mutable in F#?
rfield_mutable: bool;
/// Documentation for the field
rfield_xmldoc : XmlDoc;
/// The type of the field, w.r.t. the generic parameters of the enclosing type constructor
rfield_type: typ;
/// Indicates a static field
rfield_static: bool;
/// Indicates a compiler generated field, not visible to Intellisense or name resolution
rfield_secret: bool;
/// The default initialization info, for static literals
rfield_const: Constant option;
/// Indicates the declared visibility of the field, not taking signatures into account
rfield_access: Accessibility;
/// Attributes attached to generated property
rfield_pattribs: Attribs;
/// Attributes attached to generated field
rfield_fattribs: Attribs;
/// Name/declaration-location of the field
rfield_id: ident; }
member v.Accessibility = v.rfield_access
member v.PropertyAttribs = v.rfield_pattribs
member v.FieldAttribs = v.rfield_fattribs
member v.Range = v.rfield_id.idRange
member v.Id = v.rfield_id
member v.Name = v.rfield_id.idText
member v.IsCompilerGenerated = v.rfield_secret
member v.IsMutable = v.rfield_mutable
member v.IsStatic = v.rfield_static
member v.FormalType = v.rfield_type
member v.LiteralValue =
match v.rfield_const with
| None -> None
| Some(TConst_zero) -> None
| Some(k) -> Some(k)
member v.IsZeroInit =
match v.rfield_const with
| None -> false
| Some(TConst_zero) -> true
| _ -> false
and ExceptionInfo =
/// Indicates that an exception is an abbreviation for the given exception
| TExnAbbrevRepr of TyconRef
/// Indicates that an exception is shorthand for the given .NET exception type
| TExnAsmRepr of ILTypeRef
/// Indicates that an exception carries the given record of values
| TExnFresh of TyconRecdFields
/// Indicates that an exception is abstract, i.e. is in a signature file, and we do not know the representation
| TExnNone
and ModuleOrNamespaceKind =
/// Indicates that a module is compiled to a class with the "Module" suffix added.
| FSharpModuleWithSuffix
/// Indicates that a module is compiled to a class with the same name as the original module
| FSharpModule
/// Indicates that a 'module' is really a namespace
| Namespace
and
[<Sealed>]
ModuleOrNamespaceType(kind: ModuleOrNamespaceKind, vals: Val NameMap, entities: Entity NameMap) =
let mutable entities = entities
/// Lookup tables keyed the way various clients expect them to be keyed.
/// We attach them here so we don't need to store lookup tables via any other technique
let apref_cache : ActivePatternElemRef NameMap option ref = ref None
let modulesByDemangledName_cache : ModuleOrNamespace NameMap option ref = ref None
let exconsByDemangledName_cache : Tycon NameMap option ref = ref None
let tyconsByDemangledNameAndArity_cache: (Map<NameArityPair, Tycon>) option ref= ref None
let tyconsByAccessNames_cache : NameMultiMap<Tycon> option ref = ref None
let tyconsByMangledName_cache : Tycon NameMap option ref = ref None
/// Namespace or module-compiled-as-type?
member mtyp.ModuleOrNamespaceKind = kind
/// Values, including members in F# types in this module-or-namespace-fragment.
member mtyp.AllValuesAndMembers = vals
/// Type, mapping mangled name to Tycon, e.g.
//// "Dictionary`2" --> Tycon
//// "ListModule" --> Tycon with module info
//// "FooException" --> Tycon with exception info
member mtyp.AllEntities = entities
/// Mutation used during compilation of FSharp.Core.dll
member mtyp.AddModuleOrNamespaceByMutation(modul:ModuleOrNamespace) =
entities <- Map.add modul.MangledName modul entities;
modulesByDemangledName_cache := None
member mtyp.AddEntity(tycon:Tycon) =
new ModuleOrNamespaceType(mtyp.ModuleOrNamespaceKind, mtyp.AllValuesAndMembers, Map.add tycon.MangledName tycon mtyp.AllEntities)
member mtyp.AddVal(vspec:Val) =
new ModuleOrNamespaceType(mtyp.ModuleOrNamespaceKind, Map.add vspec.MangledName vspec mtyp.AllValuesAndMembers, mtyp.AllEntities)
/// Lookup tables keyed the way various clients expect them to be keyed.
/// We attach them here so we don't need to store lookup tables via any other technique
member mtyp.ActivePatternsLookupTable = apref_cache
member mtyp.ModulesAndNamespacesLookupTable = modulesByDemangledName_cache
member mtyp.FSharpExceptionsLookupTable = exconsByDemangledName_cache
member mtyp.TypesByDemangledNameAndArityLookupTable = tyconsByDemangledNameAndArity_cache
member mtyp.TypesByAccessNamesLookupTable = tyconsByAccessNames_cache
member mtyp.TypesByMangledNameLookupTable = tyconsByMangledName_cache
and ModuleOrNamespace = Entity
and Tycon = Entity
and Accessibility =
/// TAccess(...,path,...) indicates the construct can only be accessed from any code in the given type constructor, module or assembly. [] indicates global scope.
| TAccess of CompilationPath list
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyparData =
{ mutable typar_id: ident; (* MUTABILITY: we set the names of generalized inference type parameters to make the look nice for IL code generation *)
mutable typar_flags: int32;
(*
FLAGS ARE LOGICALLY:
(* MUTABILITY CLEANUP: could create fresh rigid variables and equate these to them. *)
mutable typar_rigid: bool; (* cannot unify: quantified. Mutated when inference decides to generalize. *)
typar_from_error: bool; (* typar was generated as part of error recovery *)
typar_compgen: bool;
mutable typar_static_req: TyparStaticReq; (* true for $a types or any tyvars in types equated with $a types - these may not be generalized *)
*)
/// The unique stamp of the typar blob.
typar_stamp: stamp;
/// The documentation for the type parameter. Empty for type inference variables.
typar_xmldoc : XmlDoc;
/// The declared attributes of the type parameter. Empty for type inference variables.
mutable typar_attribs: Attribs;
/// An inferred equivalence for a type inference variable.
(* Note: this is the most important mutable state in all of F#! *)
mutable typar_solution: typ option;
/// The inferred constraints for the type inference variable
(* Note: along with typar_solution, this is the most important mutable state in all of F#! *)
mutable typar_constraints: TyparConstraint list;
}
and
[<ReferenceEquality(true)>]
Typar =
{ mutable Data: TyparData;
mutable AsType: typ }
member x.Name = x.Data.typar_id.idText
member x.Range = x.Data.typar_id.idRange
member x.Id = x.Data.typar_id
member x.Stamp = x.Data.typar_stamp
member x.Solution = x.Data.typar_solution
member x.Constraints = x.Data.typar_constraints
member x.IsCompilerGenerated = x.Data.typar_flags |> TyparFlags.compgen_of_tpflags
member x.Rigidity = x.Data.typar_flags |> TyparFlags.rigid_of_tpflags
member x.DynamicReq = x.Data.typar_flags |> TyparFlags.dynamic_req_of_tpflags
member x.StaticReq = x.Data.typar_flags |> TyparFlags.static_req_of_tpflags
member x.IsFromError = x.Data.typar_flags |> TyparFlags.from_error_of_tpflags
member x.Kind = x.Data.typar_flags |> TyparFlags.kind_of_tpflags
member x.IsErased = match x.Kind with KindType -> false | _ -> true
member x.Attribs = x.Data.typar_attribs
member x.DisplayName = let nm = x.Name in if nm = "?" then "?"^string x.Stamp else nm
// OSGN support
static member NewUnlinked() : Typar =
let res = { Data = nullable_slot_empty(); AsType=Unchecked.defaultof<_> }
res.AsType <- TType_var res
res
static member New(data) : Typar =
let res = { Data = data; AsType=Unchecked.defaultof<_> }
res.AsType <- TType_var res
res
member x.Link(tg) = x.Data <- nullable_slot_full(tg)
member x.IsLinked = match box x.Data with null -> false | _ -> true
override x.ToString() = x.Name
and
[<StructuralEquality(false); StructuralComparison(false)>]
TyparConstraint =
/// Indicates a constraint that a type is a subtype of the given type
| TTyparCoercesToType of typ * range
/// Indicates a default value for an inference type variable should it be netiher generalized nor solved
| TTyparDefaultsToType of int * typ * range
/// Indicates a constraint that a type has a 'null' value
| TTyparSupportsNull of range
/// Indicates a constraint that a type has a member with the given signature
| TTyparMayResolveMemberConstraint of TraitConstraintInfo * range
/// Indicates a constraint that a type is a non-Nullable value type
/// These are part of .NET's model of generic constraints, and in order to
/// generate verifiable code we must attach them to F# generalzied type variables as well.
| TTyparIsNotNullableValueType of range
/// Indicates a constraint that a type is a reference type
| TTyparIsReferenceType of range
/// Indicates a constraint that a type is a simple choice between one of the given ground types. See format.ml
| TTyparSimpleChoice of typ list * range
/// Indicates a constraint that a type has a parameterless constructor
| TTyparRequiresDefaultConstructor of range
/// Indicates a constraint that a type is an enum with the given underlying
| TTyparIsEnum of typ * range
/// Indicates a constraint that a type is a delegate from the given tuple of args to the given return type *)
| TTyparIsDelegate of typ * typ * range
/// The specification of a member constraint that must be solved
and TraitConstraintInfo =
/// Indicates the signature of a member constraint
| TTrait of typ list * string * MemberFlags * typ list * typ option * (* solution: *) TraitConstraintSln option ref
member x.MemberName = (let (TTrait(_,nm,_,_,_,_)) = x in nm)
member x.ReturnType = (let (TTrait(_,_,_,_,ty,_)) = x in ty)
member x.Solution
with get() = (let (TTrait(_,_,_,_,ty,sln)) = x in sln.Value)
and set(v) = (let (TTrait(_,_,_,_,ty,sln)) = x in sln.Value <- v)
and TraitConstraintSln =
| FSMethSln of
typ * // the type and its instantiation
ValRef * // the method
tinst // the generic method instantiation
| ILMethSln of
typ *
ILTypeRef option (* extension? *) *
ILMethodRef *
// typars * // the uninstantiated generic method args
tinst // the generic method instantiation
| BuiltInSln
//| DefaultStructCtorSln of typ
and Val =
{ mutable Data: ValData; }
/// The internal name the value.
member x.MangledName = x.Data.val_name
/// The place where the value was defined.
member x.Range = x.Data.val_range
/// A unique stamp within the context of this invocation of the compiler process
member x.Stamp = x.Data.val_stamp
/// The type of the value.
/// May be a Type_forall for a generic value.
/// May be a type variable or type containing type variables during type inference.
// Mutability used in inference by adjustAllUsesOfRecValue.
// This replaces the recursively inferred type with a schema.
// MUTABILITY CLEANUP: find a way to do this using type unification alone.
member x.Type = x.Data.val_type
member x.Accessibility = x.Data.val_access
/// Range of the definition (implementation) of the value, used by Visual Studio
/// Updated by mutation when the implementation is matched against the signature.
member x.DefinitionRange = x.Data.val_defn_range
/// The value of a value or member marked with [&lt;LiteralAttribute&gt;]
member x.LiteralValue = x.Data.val_const
member x.Id = ident(x.MangledName,x.Range)
/// Is this represented as a "top level" static binding (i.e. a static field, static member,
/// instance member), rather than an "inner" binding that may result in a closure.
///
/// This is implied by IsMemberOrModuleBinding, however not vice versa, for two reasons.
/// Some optimizations mutate this value when they decide to change the representation of a
/// binding to be IsCompiledAsTopLevel. Second, even immediately after type checking we expect
/// some non-module, non-member bindings to be marked IsCompiledAsTopLevel, e.g. 'y' in
/// 'let x = let y = 1 in y + y' (NOTE: check this, don't take it as gospel)
member x.IsCompiledAsTopLevel = x.Data.val_top_repr_info.IsSome
member x.UniqueCompiledName =
#if STANDALONE_METADATA
#else
// These cases must get stable unique names for their static field & static property. This name
// must be stable across quotation generation and IL code generation (quotations can refer to the
// properties implicit in these)
//
// Variable 'x' here, which is compiled as a top level static:
// do let x = expr in ... // IsMemberOrModuleBinding = false, IsCompiledAsTopLevel = true, IsMember = false, CompilerGenerated=false
//
// The implicit 'patternInput' variable here:
// let [x] = expr in ... // IsMemberOrModuleBinding = true, IsCompiledAsTopLevel = true, IsMember = false, CompilerGenerated=true
//
// The implicit 'copyOfStruct' variables here:
// let dt = System.DateTime.Now - System.DateTime.Now // IsMemberOrModuleBinding = false, IsCompiledAsTopLevel = true, IsMember = false, CompilerGenerated=true
//
// However we don't need this for CompilerGenerated members such as the imlpementations of IComparable
if x.IsCompiledAsTopLevel && not x.IsMember && (x.IsCompilerGenerated || not x.IsMemberOrModuleBinding) then
globalStableNameGenerator.GetUniqueCompilerGeneratedName(x.MangledName,x.Range,x.Stamp)
else
#endif
x.MangledName
/// What is the public path to the value, if any? Should be set if and only if
/// IsMemberOrModuleBinding is set.
//
// Note: this is a somewhat strange field to be storing since the information
// is imprecise (it doesn't indicate if the path is made of namespaces or types, hence
// it's not enough to rebuild a compiled reference to the value. However it is enough to
// build an F# cross-module reference to the value)
//
// Also, this is recoverable from the parent
//
// We use it here:
// - in opt.ml : when compiling fslib, we bind an entry for the value in a global table (see bind_escaping_local_vspec)
// - in ilxgen.ml: when compiling fslib, we bind an entry for the value in a global table (see bind_escaping_local_vspec)
// - in opt.ml : (full_display_text_of_vref) for error reporting of non-inlinable values
// - in service.ml (boutput_item_description): to display the full text of a value's binding location
// - in check.ml: as a boolean to detect public values for saving quotations
// - in ilxgen.ml: as a boolean to detect public values for saving quotations
// - in MakeExportRemapping, to build non-local references for values
member x.PublicPath = x.Data.val_pubpath
/// Is this a member definition or module definition?
member x.IsMemberOrModuleBinding = x.Data.val_flags |> ValFlags.is_topbind_of_vflags
member x.IsExtensionMember = x.Data.val_flags |> ValFlags.is_extension_member_of_vflags
member x.ReflectedDefinition = x.Data.val_defn
/// Is this a member, if so some more data about the member.
///
/// Note, the value may still be (a) an extension member or (b) and abtract slot without
/// a true body.
member x.MemberInfo = x.Data.val_member_info
member x.IsMember = x.MemberInfo.IsSome
member x.IsNonExtensionMember = x.IsMember && not x.IsExtensionMember
member x.IsModuleBinding = x.IsMemberOrModuleBinding && not x.IsMember
member x.IsCompiledIntoModule = x.IsExtensionMember || x.IsModuleBinding
member x.IsInstanceMember = x.IsMember && x.MemberInfo.Value.MemberFlags.MemberIsInstance
member x.IsConstructor =
match x.MemberInfo with
| Some(memberInfo) when not x.IsExtensionMember && (memberInfo.MemberFlags.MemberKind = MemberKindConstructor) -> true
| _ -> false
member x.IsOverride =
match x.MemberInfo with
| Some(memberInfo) when memberInfo.MemberFlags.MemberIsOverrideOrExplicitImpl -> true
| _ -> false
member x.IsMutable = (match x.Data.val_flags |> ValFlags.mutability_of_vflags with Immutable -> false | Mutable -> true)
/// Was the value inferred to be a method or function that definitely makes no critical tailcalls?
member x.MakesNoCriticalTailcalls = x.Data.val_flags |> ValFlags.is_notailcall_hint_of_vflags
member x.IsIncrClassGeneratedMember = x.IsCompilerGenerated && x.Data.val_flags |> ValFlags.is_incr_class_of_vflags
member x.IsIncrClassConstructor = x.IsConstructor && x.Data.val_flags |> ValFlags.is_incr_class_of_vflags
member x.RecursiveValInfo = x.Data.val_flags |> ValFlags.vrec_of_vflags
member x.BaseOrThisInfo = x.Data.val_flags |> ValFlags.base_of_vflags
// Was this value declared to be a type function, e.g. "let f<'a> = typeof<'a>"
member x.IsTypeFunction = x.Data.val_flags |> ValFlags.is_tyfunc_of_vflags
member x.TopValInfo = x.Data.val_top_repr_info
member x.InlineInfo = x.Data.val_flags |> ValFlags.inline_info_of_vflags
member x.MustInline = mustinline(x.InlineInfo)
member x.IsCompilerGenerated = x.Data.val_flags |> ValFlags.is_compgen_of_vflags
member x.Attribs = x.Data.val_attribs
member x.XmlDoc = x.Data.val_xmldoc
/// The parent type or module, if any (None for expression bindings and parameters)
member x.ActualParent = x.Data.val_actual_parent
member x.MemberActualParent =
match x.ActualParent with
| Parent tcref -> tcref
| ParentNone -> error(InternalError("MemberActualParent: does not have a parent",x.Range))
member x.MemberApparentParent =
match x.MemberInfo with
| Some membInfo -> membInfo.ApparentParent
| None -> error(InternalError("MemberApparentParent",x.Range))
member x.ApparentParent =
match x.MemberInfo with
| Some membInfo -> Parent(membInfo.ApparentParent)
| None -> x.ActualParent
member x.CoreDisplayName =
match x.MemberInfo with
| Some membInfo ->
match membInfo.MemberFlags.MemberKind with
| MemberKindClassConstructor
| MemberKindConstructor
| MemberKindMember -> membInfo.CompiledName
| MemberKindPropertyGetSet
| MemberKindPropertySet
| MemberKindPropertyGet -> membInfo.PropertyName
| None -> x.MangledName
member x.DisplayName =
DemangleOperatorName x.CoreDisplayName
member x.TypeScheme =
match x.Type with
| TType_forall(tps,tau) -> tps,tau
| ty -> [],ty
member x.TauType =
match x.Type with
| TType_forall(_,tau) -> tau
| ty -> ty
member x.Typars =
match x.Type with
| TType_forall(tps,_) -> tps
| ty -> []
member x.CompiledName =
match x.MemberInfo with
| Some membInfo -> membInfo.CompiledName
| None -> x.MangledName
// OSGN support
static member NewUnlinked() : Val = { Data = nullable_slot_empty() }
static member New(data) : Val = { Data = data }
member x.Link(tg) = x.Data <- nullable_slot_full(tg)
member x.IsLinked = match box x.Data with null -> false | _ -> true
override x.ToString() = x.MangledName
and
[<StructuralEquality(false); StructuralComparison(false)>]
ValData =
{ val_name: string;
val_range: range;
mutable val_defn_range: range;
mutable val_type: typ;
val_stamp: stamp;
/// See vflags section further below for encoding/decodings here
mutable val_flags: int64;
mutable val_const: Constant option;
val_pubpath : PublicPath option;
/// What is the original, unoptimized, closed-term definition, if any?
/// Used to implement [<ReflectedDefinition>]
mutable val_defn: expr option;
/// How visible is this?
val_access: Accessibility;
/// Is the value actually an instance method/property/event that augments
/// a type, and if so what name does it take in the IL?
val_member_info: ValMemberInfo option;
/// Custom attributes attached to the value. These contain references to other values (i.e. constructors in types). Mutable to fixup
/// these value references after copying a colelction of values.
mutable val_attribs: Attribs;
/// Top level values have an arity inferred and/or specified
/// signatures. The arity records the number of arguments preferred
/// in each position for a curried functions. The currying is based
/// on the number of lambdas, and in each position the elements are
/// based on attempting to deconstruct the type of the argument as a
/// tuple-type. The field is mutable because arities for recursive
/// values are only inferred after the r.h.s. is analyzed, but the
/// value itself is created before the r.h.s. is analyzed.
///
/// TLR also sets this for inner bindings that it wants to
/// represent as "top level" bindings.
// MUTABILITY CLEANUP: mutability of this field is used by
// -- adjustAllUsesOfRecValue
// -- TLR optimizations
// -- LinearizeTopMatch
//
// For example, we use mutability to replace the empty arity initially assumed with an arity garnered from the
// type-checked expression.
mutable val_top_repr_info: ValTopReprInfo option;
// MUTABILITY CLEANUP: mutability of this field is used by
// -- LinearizeTopMatch
//
// The fresh temporary should just be created with the right parent
mutable val_actual_parent: ParentRef;
/// XML documentation attached to a value.
val_xmldoc : XmlDoc;
}
and
[<StructuralEquality(false); StructuralComparison(false)>]
ValMemberInfo =
{ /// The member name in compiled code
CompiledName: string;
/// The parent type. For an extension member this is the type being extended
ApparentParent: TyconRef;
/// Gets updated with full slotsig after interface implementation relation is checked
mutable ImplementedSlotSigs: SlotSig list;
/// Gets updated with 'true' if an abstract slot is implemented in the file being typechecked. Internal only.
mutable IsImplemented: bool;
MemberFlags: MemberFlags }
member x.PropertyName =
let logicalName =
match x.ImplementedSlotSigs with
| (TSlotSig(nm,_,_,_,_,_)) :: _ -> nm
| _ -> x.CompiledName
ChopPropertyName logicalName
member x.LogicalName =
match x.ImplementedSlotSigs with
| slotsig :: _ -> slotsig.Name
| _ -> x.CompiledName
/// Non-local references indirect via a CCU
/// The lookup into the CCU is a NonLocalPath, which is a series of strings
/// We cache the result of dereferencing
and NonLocalItemRef =
{ /// The path to an item referenced via a CCU
nlr_nlpath : NonLocalPath;
/// The name of an item referenced via a CCU
nlr_item: string; }
/// A public path records where a construct lives within the global namespace
/// of a CCU.
and PublicPath =
| PubPath of string[] * string
/// The information ILXGEN needs about the location of an item
and CompilationPath =
| CompPath of ILScopeRef * (string * ModuleOrNamespaceKind) list
member x.ILScopeRef = (let (CompPath(scoref,_)) = x in scoref)
member x.AccessPath = (let (CompPath(_,p)) = x in p)
/// Index into the namespace/module structure of a particular CCU
and NonLocalPath =
| NLPath of ccu * string[]
member nlpath.TryDeref =
let (NLPath(ccu,p)) = nlpath
ccu.EnsureDerefable(p)
let rec loop (entity:Entity) i =
if i >= p.Length then Some entity
else
let next = entity.ModuleOrNamespaceType.AllEntities.TryFind(p.[i])
match next with
| Some res -> loop res (i+1)
| None -> None
match loop ccu.Contents 0 with
| Some res as r -> r
| None ->
// OK, the lookup failed. Check if we can redirect through a type forwarder on this assembly.
// Look for a forwarder for each prefix-path
let rec tryForwardPrefixPath i =
if i < p.Length then
match ccu.TryForward(p.[0..i-1],p.[i]) with
| Some tcref ->
// OK, found a forwarder, now continue with the lookup to find the nested type
loop tcref.Deref (i+1)
| None -> tryForwardPrefixPath (i+1)
else
None
tryForwardPrefixPath 0
member nlpath.DisplayName =
let (NLPath(ccu,p)) = nlpath
String.concat "." p
member nlpath.AssemblyName =
let (NLPath(ccu,p)) = nlpath
ccu.AssemblyName
member nlpath.Deref =
match nlpath.TryDeref with
| Some res -> res
| None ->
errorR (InternalUndefinedItemRef ("module/namespace",nlpath.DisplayName, nlpath.AssemblyName, "<some module on this path>"));
raise (KeyNotFoundException())
member nlpath.TryModuleOrNamespaceType =
nlpath.TryDeref |> Option.map (fun v -> v.ModuleOrNamespaceType)
member nlpath.ModuleOrNamespaceType =
nlpath.Deref.ModuleOrNamespaceType
and
[<StructuralEquality(false); StructuralComparison(false)>]
EntityRef =
{ /// Indicates a reference to something bound in this CCU
mutable binding: Entity nonnull_slot
/// Indicates a reference to something bound in another CCU
nlr: NonLocalItemRef }
member x.IsLocalRef = match box x.nlr with null -> true | _ -> false
member x.IsResolved = match box x.binding with null -> false | _ -> true
member x.PrivateTarget = x.binding
member x.ResolvedTarget = x.binding
member private tcr.Resolve() =
let res =
match tcr.nlr.nlr_nlpath.TryModuleOrNamespaceType with
| Some mtyp ->
Map.tryFind tcr.nlr.nlr_item mtyp.AllEntities
| None -> None
let res =
match res with
| Some _ -> res
| None ->
// The lookup failed. See if we can go through a type forwarder
let (NLPath(ccu,p)) = tcr.nlr.nlr_nlpath
ccu.EnsureDerefable(p)
match ccu.TryForward(p,tcr.nlr.nlr_item) with
| Some forwardedTo ->
forwardedTo.TryDeref // recurse
| None ->
None
match res with
| Some r ->
tcr.binding <- nullable_slot_full r;
| None ->
()
// Dereference the TyconRef to a Tycon. Amortize the cost of doing this.
// This path should not allocate in the amortized case
member tcr.Deref =
match box tcr.binding with
| null ->
tcr.Resolve()
match box tcr.binding with
| null -> raise (InternalUndefinedItemRef ("namespace, module or type",tcr.nlr.nlr_nlpath.DisplayName,tcr.nlr.nlr_nlpath.AssemblyName, tcr.nlr.nlr_item))
| _ -> tcr.binding
| _ ->
tcr.binding
// Dereference the TyconRef to a Tycon option.
member tcr.TryDeref =
match box tcr.binding with
| null ->
tcr.Resolve()
match box tcr.binding with
| null -> None
| _ -> Some tcr.binding
| _ ->
Some tcr.binding
override x.ToString() =
if x.IsLocalRef then
x.ResolvedTarget.DisplayName
else
x.nlr.nlr_nlpath.DisplayName + "::" + x.nlr.nlr_item
member x.CompiledRepresentation = x.Deref.CompiledRepresentation
member x.CompiledRepresentationForTyrepNamed = x.Deref.CompiledRepresentationForTyrepNamed
member x.MangledName = x.Deref.MangledName
member x.DisplayName = x.Deref.DisplayName
member x.DisplayNameWithUnderscoreTypars = x.Deref.DisplayNameWithUnderscoreTypars
member x.Range = x.Deref.Range
member x.Stamp = x.Deref.Stamp
member x.Attribs = x.Deref.Attribs
member x.XmlDoc = x.Deref.XmlDoc
member x.ModuleOrNamespaceType = x.Deref.ModuleOrNamespaceType
member x.TypeContents = x.Deref.TypeContents
member x.TypeOrMeasureKind = x.Deref.TypeOrMeasureKind
member x.Id = x.Deref.Id
member x.TypeReprInfo = x.Deref.TypeReprInfo
member x.ExceptionInfo = x.Deref.ExceptionInfo
member x.IsExceptionDecl = x.Deref.IsExceptionDecl
member x.DemangledExceptionName = x.Deref.DemangledExceptionName
member x.Typars(m) = x.Deref.Typars(m)
member x.TyparsNoRange = x.Deref.TyparsNoRange
member x.TypeAbbrev = x.Deref.TypeAbbrev
member x.IsTypeAbbrev = x.Deref.IsTypeAbbrev
member x.TypeReprAccessibility = x.Deref.TypeReprAccessibility
member x.CompiledReprCache = x.Deref.CompiledReprCache
member x.PublicPath = x.Deref.PublicPath
member x.Accessibility = x.Deref.Accessibility
member x.IsPrefixDisplay = x.Deref.IsPrefixDisplay
member x.IsModuleOrNamespace = x.Deref.IsModuleOrNamespace
member x.IsNamespace = x.Deref.IsNamespace
member x.IsModule = x.Deref.IsModule
member x.CompilationPathOpt = x.Deref.CompilationPathOpt
member x.CompilationPath = x.Deref.CompilationPath
member x.AllFieldTable = x.Deref.AllFieldTable
member x.AllFieldsArray = x.Deref.AllFieldsArray
member x.AllFieldsAsList = x.Deref.AllFieldsAsList
member x.TrueFieldsAsList = x.Deref.TrueFieldsAsList
member x.TrueInstanceFieldsAsList = x.Deref.TrueInstanceFieldsAsList
member x.AllInstanceFieldsAsList = x.Deref.AllInstanceFieldsAsList
member x.GetFieldByIndex(n) = x.Deref.GetFieldByIndex(n)
member x.GetFieldByName(n) = x.Deref.GetFieldByName(n)
member x.UnionTypeInfo = x.Deref.UnionTypeInfo
member x.UnionCasesArray = x.Deref.UnionCasesArray
member x.UnionCasesAsList = x.Deref.UnionCasesAsList
member x.GetUnionCaseByName(n) = x.Deref.GetUnionCaseByName(n)
member x.FSharpObjectModelTypeInfo = x.Deref.FSharpObjectModelTypeInfo
member x.IsStructTycon = x.Deref.IsStructTycon
member x.IsAsmReprTycon = x.Deref.IsAsmReprTycon
member x.IsMeasureableReprTycon = x.Deref.IsMeasureableReprTycon
member x.IsILTycon = x.Deref.IsILTycon
member x.ILTyconInfo = x.Deref.ILTyconInfo
member x.ILTyconRawMetadata = x.Deref.ILTyconRawMetadata
member x.IsUnionTycon = x.Deref.IsUnionTycon
member x.UnionInfo = x.Deref.UnionInfo
member x.IsRecordTycon = x.Deref.IsRecordTycon
member x.IsFSharpObjectModelTycon = x.Deref.IsFSharpObjectModelTycon
member x.IsHiddenReprTycon = x.Deref.IsHiddenReprTycon
member x.IsFSharpInterfaceTycon = x.Deref.IsFSharpInterfaceTycon
member x.IsFSharpDelegateTycon = x.Deref.IsFSharpDelegateTycon
member x.IsFSharpEnumTycon = x.Deref.IsFSharpEnumTycon
member x.IsFSharpStructTycon = x.Deref.IsFSharpStructTycon
member x.IsILStructTycon = x.Deref.IsILStructTycon
/// note: ModuleOrNamespaceRef and TyconRef are type equivalent
and ModuleOrNamespaceRef = EntityRef
and TyconRef = EntityRef
/// References are either local or nonlocal
and
[<StructuralEquality(false); StructuralComparison(false)>]
ValRef =
{ /// Indicates a reference to something bound in this CCU
mutable binding: Val nonnull_slot
/// Indicates a reference to something bound in another CCU
nlr: NonLocalItemRef }
member x.IsLocalRef = match box x.nlr with null -> true | _ -> false
member x.IsResolved = match box x.binding with null -> false | _ -> true
member x.PrivateTarget = x.binding
member x.ResolvedTarget = x.binding
member vr.Deref =
match box vr.binding with
| null ->
let res =
let nlr = vr.nlr
let mtyp = nlr.nlr_nlpath.ModuleOrNamespaceType
try Map.find nlr.nlr_item mtyp.AllValuesAndMembers
with :? KeyNotFoundException -> raise (InternalUndefinedItemRef ("val",nlr.nlr_nlpath.DisplayName, nlr.nlr_nlpath.AssemblyName, nlr.nlr_item))
vr.binding <- nullable_slot_full res;
res
| x -> vr.binding
member vr.TryDeref =
match box vr.binding with
| null ->
vr.nlr.nlr_nlpath.TryModuleOrNamespaceType |> Option.bind (fun mty -> Map.tryFind vr.nlr.nlr_item mty.AllValuesAndMembers)
| _ -> Some vr.binding
member x.Type = x.Deref.Type
member x.TypeScheme = x.Deref.TypeScheme
member x.TauType = x.Deref.TauType
member x.Typars = x.Deref.Typars
member x.MangledName = x.Deref.MangledName
member x.DisplayName = x.Deref.DisplayName
member x.CompiledName = x.Deref.CompiledName
member x.CoreDisplayName = x.Deref.CoreDisplayName
member x.Range = x.Deref.Range
member x.Accessibility = x.Deref.Accessibility
member x.ActualParent = x.Deref.ActualParent
member x.ApparentParent = x.Deref.ApparentParent
member x.DefinitionRange = x.Deref.DefinitionRange
member x.LiteralValue = x.Deref.LiteralValue
member x.Id = x.Deref.Id
member x.Stamp = x.Deref.Stamp
member x.IsCompiledAsTopLevel = x.Deref.IsCompiledAsTopLevel
member x.UniqueCompiledName = x.Deref.UniqueCompiledName
member x.PublicPath = x.Deref.PublicPath
member x.ReflectedDefinition = x.Deref.ReflectedDefinition
member x.IsConstructor = x.Deref.IsConstructor
member x.MemberInfo = x.Deref.MemberInfo
member x.IsMember = x.Deref.IsMember
member x.IsModuleBinding = x.Deref.IsModuleBinding
member x.IsInstanceMember = x.Deref.IsInstanceMember
member x.IsMutable = x.Deref.IsMutable
member x.MakesNoCriticalTailcalls = x.Deref.MakesNoCriticalTailcalls
member x.IsMemberOrModuleBinding = x.Deref.IsMemberOrModuleBinding
member x.IsExtensionMember = x.Deref.IsExtensionMember
member x.IsIncrClassConstructor = x.Deref.IsIncrClassConstructor
member x.IsIncrClassGeneratedMember = x.Deref.IsIncrClassGeneratedMember
member x.RecursiveValInfo = x.Deref.RecursiveValInfo
member x.BaseOrThisInfo = x.Deref.BaseOrThisInfo
member x.IsTypeFunction = x.Deref.IsTypeFunction
member x.TopValInfo = x.Deref.TopValInfo
member x.InlineInfo = x.Deref.InlineInfo
member x.MustInline = x.Deref.MustInline
member x.IsCompilerGenerated = x.Deref.IsCompilerGenerated
member x.Attribs = x.Deref.Attribs
member x.XmlDoc = x.Deref.XmlDoc
member x.MemberActualParent = x.Deref.MemberActualParent
member x.MemberApparentParent = x.Deref.MemberApparentParent
override x.ToString() =
if x.IsLocalRef then x.ResolvedTarget.DisplayName else x.nlr.nlr_nlpath.DisplayName + "::" + x.nlr.nlr_item
and UnionCaseRef = UCRef of TyconRef * string
and RecdFieldRef = RFRef of TyconRef * string
and
/// The algebra of types
[<StructuralEquality(false); StructuralComparison(false)>]
// REMOVING because of possible stack overflow [<System.Diagnostics.DebuggerTypeProxy(typedefof<Dumper>)>]
typ =
/// Indicates the type is a universal type, only used for types of values, members and record fields
| TType_forall of typars * typ
/// Indicates the type is a type application
| TType_app of TyconRef * tinst
/// Indicates the type is a tuple type
| TType_tuple of typ list
/// Indicates the type is a function type
| TType_fun of typ * typ
/// Indicates the type is a non-F#-visible type representing a "proof" that a union value belongs to a particular union case
/// These types are not user-visible and will never appear as an inferred type. They are the types given to
/// the temporaries arising out of pattern matching on union values.
| TType_ucase of UnionCaseRef * tinst
/// Indicates the type is a variable type, whether declared, generalized or an inference type parameter
| TType_var of Typar
/// A legacy fake type used in legacy code to indicate the "type" of a module when building a module expression
| TType_modul_bindings
| TType_measure of measure
and tinst = typ list
and measure =
| MeasureVar of Typar
| MeasureCon of TyconRef
| MeasureProd of measure*measure
| MeasureInv of measure
| MeasureOne
and
[<StructuralEquality(false); StructuralComparison(false)>]
CcuData =
{ /// Holds the filename for the DLL, if any
ccu_filename: string option;
/// Holds the data indicating how this assembly/module is referenced from the code being compiled.
ccu_scoref: ILScopeRef;
/// A unique stamp for this DLL
ccu_stamp: stamp;
/// The fully qualified assembly reference string to refer to this assembly. This is persisted in quotations
ccu_qname: string option;
/// A hint as to where does the code for the CCU live (e.g what was the tcConfig.implicitIncludeDir at compilation time for this DLL?)
ccu_code_dir: string;
/// Indicates that this DLL was compiled using the F# compiler
ccu_fsharp: bool;
/// Indicates that this DLL uses quotation literals somewhere. This is used to implement a restriction on static linking
mutable ccu_usesQuotations : bool;
/// A handle to the full specification of the contents of the module contained in this ccu *)
(* NOTE: may contain transient state during typechecking *)
mutable ccu_contents: ModuleOrNamespace;
ccu_forwarders : CcuTypeForwarderTable }
and CcuTypeForwarderTable = Lazy<Map<string[] * string, EntityRef>>
and CcuReference = string // ILAssemblyRef
and ccu = CcuThunk
// Compilation units and Cross-compilation-unit thunks.
//
// A compilation unit is, more or less, the new material created in one
// invocation of the compiler. Due to static linking assemblies may hold more
// than one compilation unit (i.e. when two assemblies are merged into a compilation
// the resulting assembly will contain 3 CUs). Compilation units are also created for referenced
// .NET assemblies.
//
// References to items such as type constructors are via
// cross-compilation-unit thunks, which directly reference the data structures that define
// these modules. Thus, when saving out values to disk we only wish
// to save out the "current" part of the term graph. When reading values
// back in we "fixup" the links to previously referenced modules.
//
// All non-local accesses to the data structures are mediated
// by ccu-thunks. Ultimately, a ccu-thunk is either a (named) element of
// the data structure, or it is a delayed fixup, i.e. an invalid dangling
// reference that has not had an appropriate fixup applied.
/// A relinkable handle to the contents of a compilation unit. Relinking is performed by mutation.
and CcuThunk =
{ mutable target: CcuData;
mutable orphanfixup : bool;
name: CcuReference }
member ccu.Deref =
if (ccu.target = Unchecked.defaultof<CcuData>) || ccu.orphanfixup then
raise(UnresolvedReferenceNoRange ccu.name)
ccu.target
member ccu.IsUnresolvedReference = (ccu.target = Unchecked.defaultof<CcuData> || ccu.orphanfixup)
/// Ensure the ccu is derefable in advance. Supply a path to attach to any resulting error message.
member ccu.EnsureDerefable(requiringPath:string[]) =
// ccu.orphanfixup is true when a reference is missing in the transitive closure of static references that
// may potentially be required for the metadata of referenced DLLs. It is set to true if the "loader"
// used in the F# metadata-deserializer or the .NET metadata reader returns a failing value (e.g. None).
// Note: When used from Visual Studio, the loader will not automatically chase down transitively referenced DLLs - they
// must be in the explicit references in the project.
if ccu.IsUnresolvedReference then
let path = System.String.Join(".", requiringPath)
raise(UnresolvedPathReferenceNoRange(ccu.name,path))
member ccu.UsesQuotations with get() = ccu.Deref.ccu_usesQuotations and set(v) = ccu.Deref.ccu_usesQuotations <- v
member ccu.AssemblyName = ccu.name
member ccu.ILScopeRef = ccu.Deref.ccu_scoref
member ccu.Stamp = ccu.Deref.ccu_stamp
member ccu.FileName = ccu.Deref.ccu_filename
member ccu.QualifiedName = ccu.Deref.ccu_qname
member ccu.SourceCodeDirectory = ccu.Deref.ccu_code_dir
member ccu.IsFSharp = ccu.Deref.ccu_fsharp
member ccu.Contents = ccu.Deref.ccu_contents
member ccu.TypeForwarders : Map<string[] * string, EntityRef> = ccu.Deref.ccu_forwarders.Force()
static member Create(nm,x) =
{ target = x;
orphanfixup = false;
name = nm; }
static member CreateDelayed(nm) =
{ target = Unchecked.defaultof<_>;
orphanfixup = false;
name = nm; }
member x.Fixup(avail:CcuThunk) =
match box x.target with
| null ->
assert (avail.AssemblyName = x.AssemblyName)
x.target <-
(match box avail.target with
| null -> error(Failure("internal error: ccu thunk '"^avail.name^"' not fixed up!"))
| _ -> avail.target)
| _ -> errorR(Failure("internal error: the ccu thunk for assembly "^x.AssemblyName^" not delayed!"));
member x.FixupOrphaned() =
match box x.target with
| null -> x.orphanfixup<-true
| _ -> errorR(Failure("internal error: the ccu thunk for assembly "^x.AssemblyName^" not delayed!"));
member ccu.TryForward(nlpath:string[],item:string) : EntityRef option =
ccu.EnsureDerefable(nlpath)
ccu.TypeForwarders.TryFind(nlpath,item)
//printfn "trying to forward %A::%s from ccu '%s', res = '%A'" p n ccu.AssemblyName res.IsSome
override ccu.ToString() = ccu.AssemblyName
/// The result of attempting to resolve an assembly name to a full ccu.
/// UnresolvedCcu will contain the name of the assembly that could not be resolved.
and CcuResolutionResult =
| ResolvedCcu of ccu
| UnresolvedCcu of string
and PickledModuleInfo =
{ mspec: ModuleOrNamespace;
compile_time_working_dir: string;
usesQuotations : bool }
//---------------------------------------------------------------------------
// Attributes
//---------------------------------------------------------------------------
and Attribs = Attrib list
and AttribKind =
/// Indicates an attribute refers to a type defined in an imported .NET assembly *)
| ILAttrib of ILMethodRef
/// Indicates an attribute refers to a type defined in an imported F# assembly *)
| FSAttrib of ValRef
/// Attrib(kind,unnamedArgs,propVals)
and Attrib =
| Attrib of TyconRef * AttribKind * AttribExpr list * AttribNamedArg list * range
/// We keep both source expression and evaluated expression around to help intellisense and signature printing
and AttribExpr = AttribExpr of (* source *) expr * (* evaluated *) expr
/// AttribNamedArg(name,type,isField,value)
and AttribNamedArg = AttribNamedArg of (string*typ*bool*AttribExpr)
/// Constants in expressions
and Constant =
| TConst_bool of bool
| TConst_sbyte of sbyte
| TConst_byte of byte
| TConst_int16 of int16
| TConst_uint16 of uint16
| TConst_int32 of int32
| TConst_uint32 of uint32
| TConst_int64 of int64
| TConst_uint64 of uint64
| TConst_nativeint of int64
| TConst_unativeint of uint64
| TConst_float32 of single
| TConst_float of double
| TConst_char of char
| TConst_string of string (* in unicode *)
| TConst_decimal of System.Decimal (* in unicode *)
| TConst_unit
| TConst_zero (* null/zero-bit-pattern *)
/// Decision trees. Pattern matching has been compiled down to
/// a decision tree by this point. The right-hand-sides (actions) of
/// the decision tree are labelled by integers that are unique for that
/// particular tree.
and
[<StructuralEquality(false); StructuralComparison(false)>]
DecisionTree =
/// Indicates a decision point in a decision tree.
| TDSwitch of
(* input: *) expr *
(* cases: *) DecisionTreeCase list *
(* default: *) DecisionTree option * range
/// Indicates the decision tree has terminated with success, calling the given target with the given parameters
| TDSuccess of
(* results: *) FlatExprs *
(* target: *) int
/// Bind the given value throught the remaining cases of the dtree.
| TDBind of
(* binding: *) Binding *
(* body: *) DecisionTree
and DecisionTreeCase =
| TCase of DecisionTreeDiscriminator * DecisionTree
and
[<StructuralEquality(false); StructuralComparison(false)>]
DecisionTreeDiscriminator =
/// Test if the input to a decision tree matches the given constructor
| TTest_unionconstr of (UnionCaseRef * tinst)
/// Test if the input to a decision tree is an array of the given length
| TTest_array_length of int * typ
/// Test if the input to a decision tree is the given constant value
| TTest_const of Constant
/// Test if the input to a decision tree is null
| TTest_isnull
/// Test if the input to a decision tree is an instance of the given type
| TTest_isinst of (* source: *) typ * (* target: *) typ
/// Run the active pattern and bind a successful result to the (one) variable in the remaining tree
| TTest_query of expr * typ list * ValRef option * int * ActivePatternInfo
/// A target of a decision tree. Can be thought of as a little function, though is compiled as a local block.
and DecisionTreeTarget =
| TTarget of FlatVals * expr * SequencePointInfoForTarget
and Bindings = FlatList<Binding>
and Binding =
| TBind of Val * expr * SequencePointInfoForBinding
member x.Var = (let (TBind(v,_,_)) = x in v)
member x.Expr = (let (TBind(_,e,_)) = x in e)
member x.SequencePointInfo = (let (TBind(_,_,sp)) = x in sp)
// ActivePatternElemRef: active pattern element (deconstruction case), e.g. 'JNil' or 'JCons'.
// Integer indicates which choice in the target set is being selected by this item.
and ActivePatternElemRef =
| APElemRef of ActivePatternInfo * ValRef * int
member x.IsTotalActivePattern = (let (APElemRef(total,vref,n)) = x in total)
member x.ActivePatternVal = (let (APElemRef(total,vref,n)) = x in vref)
member x.CaseIndex = (let (APElemRef(total,vref,n)) = x in n)
and ActivePatternInfo =
| APInfo of bool * string list * range
and ValTopReprInfo =
| TopValInfo of (* numTypars: *) TopTyparInfo list * (* args: *) TopArgInfo list list * (* result: *) TopArgInfo
member x.ArgInfos = (let (TopValInfo(_,args,_)) = x in args)
member x.NumCurriedArgs = (let (TopValInfo(_,args,_)) = x in args.Length)
member x.NumTypars = (let (TopValInfo(n,_,_)) = x in n.Length)
member x.HasNoArgs = (let (TopValInfo(n,args,_)) = x in n.IsEmpty && args.IsEmpty)
member x.AritiesOfArgs = (let (TopValInfo(_,args,_)) = x in List.map List.length args)
member x.KindsOfTypars = (let (TopValInfo(n,_,_)) = x in n |> List.map (fun (TopTyparInfo(_,k)) -> k))
/// The extra metadata stored about typars for top-level definitions. Any information here is propagated from signature through
/// to the compiled code.
and TopArgInfo = TopArgInfo of (* attributes: *) Attribs * (* name: *) ident option
/// The extra metadata stored about typars for top-level definitions. Any information here is propagated from signature through
/// to the compiled code.
and TopTyparInfo = TopTyparInfo of ident * TyparKind
and typars = Typar list
and Exprs = expr list
and FlatExprs = FlatList<expr>
and Vals = Val list
and FlatVals = FlatList<Val>
/// The big type of expressions.
and expr =
/// A constant expression.
| TExpr_const of Constant * range * typ
/// Reference a value. The flag is only relevant if the value is an object model member
/// and indicates base calls and special uses of object constructors.
| TExpr_val of ValRef * ValUseFlag * range
/// Sequence expressions, used for "a;b", "let a = e in b;a" and "a then b" (the last an OO constructor).
| TExpr_seq of expr * expr * SequentialOpKind * SequencePointInfoForSeq * range
/// Lambda expressions.
// Why multiple vspecs? A TExpr_lambda taking multiple arguments really accepts a tuple.
// But it is in a convenient form to be compile accepting multiple
// arguments, e.g. if compiled as a toplevel static method.
// REVIEW: see if we can eliminate this and just use lambdas taking single arguments.
// though perhaps propagating metadata about preferred argument names.
// REVIEW: it would probably be better if the freevar cache cached those of the body rather than the
// whole expression.
// REVIEW: why not conjoin multiple lambdas into a single iterated lambda node?
| TExpr_lambda of uniq * Val option * Val list * expr * range * typ * SkipFreeVarsCache
// Type lambdas. These are used for the r.h.s. of polymorphic 'let' bindings and
// for expressions that implement first-class polymorphic values.
// REVIEW: it would probably be better if the freevar cache cached those of the body rather than the
// whole expression.
| TExpr_tlambda of uniq * typars * expr * range * typ * SkipFreeVarsCache
/// Applications.
/// Applications combine type and term applications, and are normalized so
/// that sequential applications are combined, so "(f x y)" becomes "f [[x];[y]]".
/// The type attached to the function is the formal function type, used to ensure we don't build application
/// nodes that over-apply when instantiating at function types.
| TExpr_app of expr * typ * tinst * Exprs * range
/// Bind a recursive set of values.
// REVIEW: it would probably be better if the freevar cache cached those of the body rather than the
// whole expression.
| TExpr_letrec of Bindings * expr * range * FreeVarsCache
/// Bind a value.
// REVIEW: do we really need both TExpr_let AND TExpr_letrec AND TExpr_match AND TExpr_lambda!?
// Why not just TExpr_match the primitive?
// REVIEW: it would probably be better if the freevar cache cached those of the body rather than the
// whole expression.
| TExpr_let of Binding * expr * range * FreeVarsCache
// Object expressions: A closure that implements an interface or a base type.
// The base object type might be a delegate type.
| TExpr_obj of
(* unique *) uniq *
(* object typ *) typ * (* <-- NOTE: specifies type parameters for base type *)
(* base val *) Val option *
(* ctor call *) expr *
(* overrides *) ObjExprMethod list *
(* extra interfaces *) (typ * ObjExprMethod list) list *
range *
SkipFreeVarsCache
// Pattern matching.
/// Matches are a more complicated form of "let" with multiple possible destinations
/// and possibly multiple ways to get to each destination.
/// The first mark is that of the expression being matched, which is used
/// as the mark for all the decision making and binding that happens during the match.
| TExpr_match of SequencePointInfoForBinding * range * DecisionTree * DecisionTreeTarget array * range * typ * SkipFreeVarsCache
/// If we statically know some infomation then in many cases we can use a more optimized expression
/// This is primarily used by terms in the standard library, particularly those implementing overloaded
/// operators.
| TExpr_static_optimization of StaticOptimization list * expr * expr * range
/// An intrinsic applied to some (strictly evaluated) arguments
/// A few of intrinsics (TOp_try, TOp_while, TOp_for) expect arguments kept in a normal form involving lambdas
| TExpr_op of ExprOpSpec * tinst * Exprs * range
// Indicates the expression is a quoted expression tree.
| TExpr_quote of expr * (typ list * Exprs * ExprData) option ref * range * typ
/// Typechecking residue: Indicates a free choice of typars that arises due to
/// minimization of polymorphism at let-rec bindings. These are
/// resolved to a concrete instantiation on subsequent rewrites.
| TExpr_tchoose of typars * expr * range
/// Typechecking residue: A TExpr_link occurs for every use of a recursively bound variable. While type-checking
/// the recursive bindings a dummy expression is stored in the mutable reference cell.
/// After type checking the bindings this is replaced by a use of the variable, perhaps at an
/// appropriate type instantiation. These are immediately eliminated on subsequent rewrites.
| TExpr_link of expr ref
/// A type for a module-or-namespace-fragment and the actual definition of the module-or-namespace-fragment
and ModuleOrNamespaceExprWithSig =
| TMTyped of
/// The module_typ is a binder. However it is not used in the ModuleOrNamespaceExpr: it is only referenced from the 'outside'
ModuleOrNamespaceType
* ModuleOrNamespaceExpr
* range
/// The contents of a module-or-namespace-fragment definition
and ModuleOrNamespaceExpr =
/// Indicates the module is a module with a signature
| TMAbstract of ModuleOrNamespaceExprWithSig
/// Indicates the module fragment is made of several module fragments in succession
| TMDefs of ModuleOrNamespaceExpr list
/// Indicates the module fragment is a 'let' definition
| TMDefLet of Binding * range
/// Indicates the module fragment is an evaluation of expression for side-effects
| TMDefDo of expr * range
/// Indicates the module fragment is a 'rec' definition of types, values and modules
| TMDefRec of Tycon list * Bindings * ModuleOrNamespaceBinding list * range
/// A named module-or-namespace-fragment definition
and ModuleOrNamespaceBinding =
| TMBind of
/// This ModuleOrNamespace that represents the compilation of a module as a class.
/// The same set of tycons etc. are bound in the ModuleOrNamespace as in the ModuleOrNamespaceExpr
ModuleOrNamespace *
/// This is the body of the module/namespace
ModuleOrNamespaceExpr
#if STANDALONE_METADATA
#else
and TypedImplFile = TImplFile of QualifiedNameOfFile * ScopedPragma list * ModuleOrNamespaceExprWithSig
and TypedAssembly = TAssembly of TypedImplFile list
#endif
and RecordConstructionInfo =
/// We're in a constructor. The purpose of the record expression is to
/// fill in the fields of a pre-created but uninitialized object
| RecdExprIsObjInit
/// Normal record construction
| RecdExpr
and
[<StructuralEquality(false); StructuralComparison(false)>]
ExprOpSpec =
/// An operation representing the creation of a union value of the particular union case
| TOp_ucase of UnionCaseRef
/// An operation representing the creation of an exception value using an F# exception declaration
| TOp_exnconstr of TyconRef
/// An operation representing the creation of a tuple value
| TOp_tuple
/// An operation representing the creation of an array value
| TOp_array
/// Constant bytes, but a new mutable blob is generated each time the construct is executed
| TOp_bytes of byte[]
| TOp_uint16s of uint16[]
// REVIEW: simplify these two to a more general concretization of inner letrec bindings
/// An operation representing a lambda-encoded while loop
| TOp_while of SequencePointInfoForWhileLoop
/// An operation representing a lambda-encoded for loop
| TOp_for of SequencePointInfoForForLoop * ForLoopStyle (* count up or down? *)
/// An operation representing a lambda-encoded try/catch
| TOp_try_catch of SequencePointInfoForTry * SequencePointInfoForWith
/// An operation representing a lambda-encoded try/finally
| TOp_try_finally of SequencePointInfoForTry * SequencePointInfoForFinally
/// Construct a record or object-model value. The ValRef is for self-referential class constructors, otherwise
/// it indicates that we're in a constructor and the purpose of the expression is to
/// fill in the fields of a pre-created but uninitialized object, and to assign the initialized
/// version of the object into the optional mutable cell pointed to be the given value.
| TOp_recd of RecordConstructionInfo * TyconRef
/// An operation representing setting a record field
| TOp_rfield_set of RecdFieldRef
/// An operation representing getting a record field
| TOp_rfield_get of RecdFieldRef
/// An operation representing getting the address of a record field
| TOp_field_get_addr of RecdFieldRef
/// An operation representing getting an integer tag for a union value representing the union case number
| TOp_ucase_tag_get of TyconRef
/// An operation representing a coercion that proves a union value is of a particular union case. THis is not a test, its
/// simply added proof to enable us to generate verifiable code for field access on union types
| TOp_ucase_proof of UnionCaseRef
/// An operation representing a field-get from a union value, where that value has been proven to be of the corresponding union case.
| TOp_ucase_field_get of UnionCaseRef * int
/// An operation representing a field-get from a union value. THe value is not assumed to have been proven to be of the corresponding union case.
| TOp_ucase_field_set of UnionCaseRef * int
/// An operation representing a field-get from an F# exception value.
| TOp_exnconstr_field_get of TyconRef * int
/// An operation representing a field-set on an F# exception value.
| TOp_exnconstr_field_set of TyconRef * int
/// An operation representing a field-get from an F# tuple value.
| TOp_tuple_field_get of int
/// IL assembly code - type list are the types pushed on the stack
| TOp_asm of ILInstr list * typ list
/// generate a ldflda on an 'a ref. REVIEW: generalize to a TOp_flda
| TOp_get_ref_lval
/// Conversion node, compiled via type-directed translation or to box/unbox
| TOp_coerce
/// Represents a "rethrow" operation. May not be rebound, or used outside of try-finally, expecting a unit argument
| TOp_rethrow
| TOp_return
#if STANDALONE_METADATA
#else
| TOp_goto of ILCodeLabel
| TOp_label of ILCodeLabel
#endif
/// Pseudo method calls. This is used for overloaded operations like op_Addition.
| TOp_trait_call of TraitConstraintInfo
/// Operation nodes represnting C-style operations on byrefs and mutable vals (l-values)
| TOp_lval_op of LValueOperation * ValRef
/// IL method calls
| TOp_ilcall of
(bool * (* virtual call? *)
bool * (* protected? *)
bool * (* is the object a value type? *)
bool * (* newobj call? *)
ValUseFlag * (* isSuperInit call? *)
bool * (* property? used for reflection *)
bool * (* DllImport? if so don't tailcall *)
(typ * typ) option * (* coercion to box 'this' *)
ILMethodRef) *
typ list * (* tinst *)
typ list * (* minst *)
typ list (* types of pushed values if any *)
and ForLoopStyle =
/// Evaluate start and end once, loop up
| FSharpForLoopUp
/// Evaluate start and end once, loop down
| FSharpForLoopDown
/// Evaluate start once and end multiple times, loop up
| CSharpForLoopUp
and LValueOperation =
/// In C syntax this is: &localv
| LGetAddr
/// In C syntax this is: *localv_ptr
| LByrefGet
/// In C syntax this is: localv = e , note == *(&localv) = e == LGetAddr; LByrefSet
| LSet
/// In C syntax this is: *localv_ptr = e
| LByrefSet
and SequentialOpKind =
/// a ; b
| NormalSeq
/// let res = a in b;res
| ThenDoSeq
and ValUseFlag =
| NormalValUse
/// A call to a constructor, e.g. 'inherit C()'
| CtorValUsedAsSuperInit
/// A call to a constructor, e.g. 'new C() = new C(3)'
| CtorValUsedAsSelfInit
/// A call to a base method, e.g. 'base.OnPaint(args)'
| VSlotDirectCall
and StaticOptimization =
| TTyconEqualsTycon of typ * typ
/// A representation of a method in an object expression.
/// Note: Methods associated with types are represented as val declarations
/// Note: We should probably use val_specs for object expressions, as then the treatment of members
/// in object expressions could be more unified with the treatment of members in types
and ObjExprMethod =
| TObjExprMethod of SlotSig * typars * Val list list * expr * range
member x.Id = let (TObjExprMethod(slotsig,methFormalTypars,_,_,m)) = x in mksyn_id m slotsig.Name
and SlotSig =
| TSlotSig of string * typ * typars * typars * SlotParam list list * typ option
member ss.Name = let (TSlotSig(nm,_,_,_,_,_)) = ss in nm
member ss.ImplementedType = let (TSlotSig(_,ty,_,_,_,_)) = ss in ty
member ss.ClassTypars = let (TSlotSig(_,_,ctps,_,_,_)) = ss in ctps
member ss.MethodTypars = let (TSlotSig(_,_,_,mtps,_,_)) = ss in mtps
member ss.FormalParams = let (TSlotSig(_,_,_,_,ps,_)) = ss in ps
member ss.FormalReturnType = let (TSlotSig(_,_,_,_,_,rt)) = ss in rt
and SlotParam =
| TSlotParam of string option * typ * bool (* in *) * bool (* out *) * bool (* optional *) * Attribs
member x.Type = let (TSlotParam(_,ty,_,_,_,_)) = x in ty
//---------------------------------------------------------------------------
// Freevars. Computed and cached by later phases (never computed type checking). Cached in terms. Not pickled.
//---------------------------------------------------------------------------
#if STANDALONE_METADATA
#else
and FreeLocals = Val Zset.t
and FreeTypars = Typar Zset.t
and FreeTycons = Tycon Zset.t
and FreeRecdFields = RecdFieldRef Zset.t
and FreeUnionCases = UnionCaseRef Zset.t
and FreeTyvars =
{ /// The summary of locally defined type definitions used in the expression. These may be made private by a signature
/// and we have to check various conditions associated with that.
FreeTycons: FreeTycons;
/// The summary of values used as trait solutions
FreeTraitSolutions: FreeLocals;
/// The summary of type parameters used in the expression. These may not escape the enclosing generic construct
/// and we have to check various conditions associated with that.
FreeTypars: FreeTypars }
and SkipFreeVarsCache = unit
and FreeVarsCache = FreeVars cache
and FreeVars =
{ /// The summary of locally defined variables used in the expression. These may be hidden at let bindings etc.
/// or made private by a signature or marked 'internal' or 'private', and we have to check various conditions associated with that.
FreeLocals: FreeLocals;
/// Indicates if the expression contains a call to a protected member or a base call.
/// Calls to protected members and direct calls to super classes can't escape, also code can't be inlined
UsesMethodLocalConstructs: bool;
/// Indicates if the expression contains a call to rethrow that is not bound under a (try-)with branch.
/// Rethrow may only occur in such locations.
UsesUnboundRethrow: bool;
/// The summary of locally defined tycon representations used in the expression. These may be made private by a signature
/// or marked 'internal' or 'private' and we have to check various conditions associated with that.
FreeLocalTyconReprs: FreeTycons;
/// The summary of fields used in the expression. These may be made private by a signature
/// or marked 'internal' or 'private' and we have to check various conditions associated with that.
FreeRecdFields: FreeRecdFields;
/// The summary of union constructors used in the expression. These may be
/// marked 'internal' or 'private' and we have to check various conditions associated with that.
FreeUnionCases: FreeUnionCases;
/// See FreeTyvars above.
FreeTyvars: FreeTyvars }
#endif
/// Specifies the compiled representations of type and exception definitions.
/// Computed and cached by later phases (never computed type checking). Cached at
/// type and exception definitions. Not pickled.
and CompiledTypeRepr =
| TyrepNamed of ILTypeRef * ILBoxity
| TyrepOpen of ILType
//---------------------------------------------------------------------------
// Basic properties on type definitions
//---------------------------------------------------------------------------
let demangled_name_of_entity_name nm k =
match k with
| FSharpModuleWithSuffix -> String.dropSuffix nm FSharpModuleSuffix
| _ -> nm
let demangled_name_of_modul (x:ModuleOrNamespace) =
demangled_name_of_entity_name x.MangledName x.ModuleOrNamespaceType.ModuleOrNamespaceKind
/// Metadata on values (names of arguments etc.
module TopValInfo =
let unnamedTopArg1 = TopArgInfo([],None)
let unnamedTopArg = [unnamedTopArg1]
let unitArgData = [[]]
let unnamedRetVal = TopArgInfo([],None)
let selfMetadata = unnamedTopArg
let emptyValData = TopValInfo([],[],unnamedRetVal)
let InferTyparInfo (tps:Typar list) = tps |> List.map (fun tp -> TopTyparInfo(tp.Id, tp.Kind))
let InferTopArgInfo (v:Val) = TopArgInfo ([], Some v.Id)
let InferTopArgInfos (vs:Val list list) = TopValInfo([],List.mapSquared InferTopArgInfo vs,unnamedRetVal)
let HasNoArgs (TopValInfo(n,args,_)) = n.IsEmpty && args.IsEmpty
//---------------------------------------------------------------------------
// Basic properties via functions (old style)
//---------------------------------------------------------------------------
let id_of_tycon (tc:Tycon) = ident(tc.MangledName, tc.Range)
let stamp_of_tycon (tc:Tycon) = tc.Stamp
let attribs_of_tycon (tc:Tycon) = tc.Attribs
let pubpath_of_tycon (tc:Tycon) = tc.PublicPath
let data_of_val (v:Val) = v.Data
let type_of_val (v:Val) = v.Type
let types_of_vals (v:Val list) = v |> List.map (fun v -> v.Type)
let name_of_val (v:Val) = v.MangledName
let id_of_val (v:Val) = ident(v.MangledName,v.Range)
let pubpath_of_val (v:Val) = v.PublicPath
let arity_of_val (v:Val) = (match v.TopValInfo with None -> TopValInfo.emptyValData | Some arities -> arities)
let set_vrec_of_vflags x b = x.val_flags <- ValFlags.encode_vrec_of_vflags b x.val_flags
let set_is_topbind_of_vflags x b = x.val_flags <- ValFlags.encode_is_topbind_of_vflags b x.val_flags
let set_notailcall_hint_of_vflags x b = x.val_flags <- ValFlags.encode_notailcall_hint_of_vflags b x.val_flags
//-------------------------------------------------------------------------
// Managed cached type name lookup tables
//-------------------------------------------------------------------------
let AddTyconsByDemangledNameAndArity nm (typars:Typar list) x tab =
let nm = DemangleGenericTypeName nm
Map.add (NameArityPair(nm, typars.Length)) x tab
let AddTyconsByAccessNames nm x tab =
if IsMangledGenericName nm then
let dnm = DemangleGenericTypeName nm
let res = NameMultiMap.add nm x tab
NameMultiMap.add dnm x res
else
NameMultiMap.add nm x tab
type ModuleOrNamespaceType with
member mtyp.TypeDefinitions = mtyp.AllEntities |> NameMap.range |> List.filter (fun x -> not x.IsExceptionDecl && not x.IsModuleOrNamespace)
member mtyp.ExceptionDefinitions = mtyp.AllEntities |> NameMap.range |> List.filter (fun x -> x.IsExceptionDecl)
member mtyp.ModuleAndNamespaceDefinitions = mtyp.AllEntities |> NameMap.range |> List.filter (fun x -> x.IsModuleOrNamespace)
member mtyp.TypeAndExceptionDefinitions = mtyp.AllEntities |> NameMap.range |> List.filter (fun x -> not x.IsModuleOrNamespace)
member mtyp.TypesByDemangledNameAndArity(m) =
cacheOptRef mtyp.TypesByDemangledNameAndArityLookupTable (fun () ->
List.foldBack (fun (tc:Tycon) acc -> AddTyconsByDemangledNameAndArity tc.MangledName (tc.Typars(m)) tc acc) mtyp.TypeAndExceptionDefinitions Map.empty)
member mtyp.TypesByAccessNames =
cacheOptRef mtyp.TypesByAccessNamesLookupTable (fun () ->
List.foldBack (fun (tc:Tycon) acc -> AddTyconsByAccessNames tc.MangledName tc acc) mtyp.TypeAndExceptionDefinitions Map.empty)
member mtyp.TypesByMangledName =
let add_tyconsByMangledName (x:Tycon) tab = NameMap.add x.MangledName x tab
cacheOptRef mtyp.TypesByMangledNameLookupTable (fun () ->
List.foldBack add_tyconsByMangledName mtyp.TypeAndExceptionDefinitions Map.empty)
member mtyp.ExceptionDefinitionsByDemangledName =
let add_exconsByDemangledName (tycon:Tycon) acc = NameMap.add tycon.DemangledExceptionName tycon acc
cacheOptRef mtyp.FSharpExceptionsLookupTable (fun () ->
List.foldBack add_exconsByDemangledName mtyp.ExceptionDefinitions Map.empty)
member mtyp.ModulesAndNamespacesByDemangledName =
let add_moduleByDemangledName (tycon:Entity) acc =
if tycon.IsModuleOrNamespace then
NameMap.add (demangled_name_of_modul tycon) tycon acc
else acc
cacheOptRef mtyp.ModulesAndNamespacesLookupTable (fun () ->
NameMap.foldRange add_moduleByDemangledName mtyp.AllEntities Map.empty)
type CcuThunk with
member ccu.TopModulesAndNamespaces = ccu.Contents.ModuleOrNamespaceType.ModulesAndNamespacesByDemangledName
member ccu.TopTypeAndExceptionDefinitions = ccu.Contents.ModuleOrNamespaceType.TypeAndExceptionDefinitions
let name_of_rfield v = v.rfield_id.idText
let set_rigid_of_tpdata x b = x.typar_flags <- TyparFlags.encode_rigid_of_tpflags b x.typar_flags
let set_from_error_of_tpdata x b = x.typar_flags <- TyparFlags.encode_from_error_of_tpflags b x.typar_flags
let set_static_req_of_tpdata x b = x.typar_flags <- TyparFlags.encode_static_req_of_tpflags b x.typar_flags
let set_dynamic_req_of_tpdata x b = x.typar_flags <- TyparFlags.encode_dynamic_req_of_tpflags b x.typar_flags
let set_compgen_of_tpdata x b = x.typar_flags <- TyparFlags.encode_compgen_of_tpflags b x.typar_flags
let set_kind_of_tpdata x b = x.typar_flags <- TyparFlags.encode_kind_of_tpflags b x.typar_flags
//---------------------------------------------------------------------------
// Aggregate operations to help transform the components that
// make up the entire compilation unit
//---------------------------------------------------------------------------
#if STANDALONE_METADATA
#else
let mapTImplFile f (TImplFile(fragName,pragmas,moduleExpr)) = TImplFile(fragName, pragmas,f moduleExpr)
let fmapTImplFile f z (TImplFile(fragName,pragmas,moduleExpr)) = let z,moduleExpr = f z moduleExpr in z,TImplFile(fragName,pragmas,moduleExpr)
let map_acc_TImplFile f z (TImplFile(fragName,pragmas,moduleExpr)) = let moduleExpr,z = f z moduleExpr in TImplFile(fragName,pragmas,moduleExpr), z
let foldTImplFile f z (TImplFile(fragName,pragmas,moduleExpr)) = f z moduleExpr
#endif
//---------------------------------------------------------------------------
// Equality relations on locally defined things
//---------------------------------------------------------------------------
let local_tcref_eq (lv1:Tycon) (lv2:Tycon) = lv1.Stamp === lv2.Stamp
let typar_ref_eq (lv1:Typar) (lv2:Typar) = lv1.Stamp === lv2.Stamp
/// Equality on value specs, implemented as reference equality
let vspec_eq (lv1: Val) (lv2: Val) = (lv1 === lv2)
/// Equality on CCUs, implemented as reference equality
let ccu_eq (mv1: ccu) (mv2: ccu) = (mv1 === mv2) || (mv1.Contents === mv2.Contents)
/// Equality on type varialbes, implemented as reference equality
let tpspec_eq (tp1: Typar) (tp2: Typar) = (tp1 === tp2)
let deref_tycon (tcr :TyconRef) = tcr.Deref
/// Identical to tcref.Deref and deref_tycon, just used to help distinguish what kind of entity we expect here
let deref_modul (tcr :ModuleOrNamespaceRef) = tcr.Deref
let deref_val (vr :ValRef) = vr.Deref
let (|ValDeref|) (vr :ValRef) = vr.Deref
let try_deref_val (vr :ValRef) = vr.TryDeref
//---------------------------------------------------------------------------
// Get information from refs
//---------------------------------------------------------------------------
exception InternalUndefinedTyconItem of string * TyconRef * string
type RecdFieldRef with
member x.TyconRef = let (RFRef(tcref,id)) = x in tcref
member x.FieldName = let (RFRef(tcref,id)) = x in id
member x.Tycon = x.TyconRef.Deref
member x.RecdField =
let (RFRef(tcref,id)) = x
match tcref.GetFieldByName id with
| Some res -> res
| None -> raise (InternalUndefinedTyconItem ("field",tcref, id))
member x.PropertyAttribs = x.RecdField.PropertyAttribs
member x.Range = x.RecdField.Range
type UnionCaseRef with
member x.TyconRef = let (UCRef(tcref,_)) = x in tcref
member x.CaseName = let (UCRef(_,nm)) = x in nm
member x.Tycon = x.TyconRef.Deref
member x.UnionCase =
let (UCRef(tcref,nm)) = x
match tcref.GetUnionCaseByName nm with
| Some res -> res
| None -> raise (InternalUndefinedTyconItem ("union case",tcref, nm))
member x.Attribs = x.UnionCase.Attribs
member x.Range = x.UnionCase.Range
//--------------------------------------------------------------------------
// Make references to TAST items
//--------------------------------------------------------------------------
let mk_rfref tcref f = RFRef(tcref, f)
let mk_ucref tcref c = UCRef(tcref, c)
let rfref_of_rfield tcref f = mk_rfref tcref f.rfield_id.idText
let ucref_of_ucase tcref c = mk_ucref tcref c.ucase_id.idText
let mk_nlpath (NLPath(mref,p)) n = NLPath(mref,Array.append p [| n |])
let mk_cpath (CompPath(scoref,p)) n modKind = CompPath(scoref,p@[(n,modKind)])
let path_of_nlpath (NLPath(a,b)) = b
let ccu_of_nlpath (NLPath(a,b)) = a
let demangled_name_of_modref (x:ModuleOrNamespaceRef) = (deref_modul x) |> demangled_name_of_modul
let nlpath_of_nlref nlr = nlr.nlr_nlpath
let item_of_nlref nlr = nlr.nlr_item
let ccu_of_nlref nlr = ccu_of_nlpath (nlpath_of_nlref nlr)
let VRef_private(x) : ValRef = { binding=x; nlr=Unchecked.defaultof<_> }
let VRef_nonlocal(x) : ValRef = { binding=Unchecked.defaultof<_>; nlr=x }
let VRef_nonlocal_preresolved x xref : ValRef = { binding=x; nlr=xref }
let (|VRef_private|VRef_nonlocal|) (x: ValRef) =
match box x.nlr with
| null -> VRef_private(x.binding)
| _ -> VRef_nonlocal(x.nlr)
let ERef_private(x) : EntityRef = { binding=x; nlr=Unchecked.defaultof<_> }
let ERef_nonlocal(x) : EntityRef = { binding=Unchecked.defaultof<_>; nlr=x }
let ERef_nonlocal_preresolved x xref : EntityRef = { binding=x; nlr=xref }
let (|ERef_private|ERef_nonlocal|) (x: EntityRef) =
match box x.nlr with
| null -> ERef_private(x.binding)
| _ -> ERef_nonlocal(x.nlr)
let ccu_of_vref iref =
match iref with
| VRef_private _ -> None
| VRef_nonlocal(nlr) -> Some (ccu_of_nlref iref.nlr)
let ccu_of_tcref iref =
match iref with
| ERef_private _ -> None
| ERef_nonlocal(nlr) -> Some (ccu_of_nlref iref.nlr)
//--------------------------------------------------------------------------
// Type parameters and inference unknowns
//-------------------------------------------------------------------------
let mk_typar_ty (tp:Typar) =
match tp.Kind with
| KindType -> tp.AsType
| KindMeasure -> TType_measure (MeasureVar tp)
let CopyTypar (tp: Typar) = let x = tp.Data in Typar.New { x with typar_stamp=new_stamp() }
let CopyTypars tps = List.map CopyTypar tps
let fixup_typar_constraints (tp:Typar) cs =
tp.Data.typar_constraints <- cs
//--------------------------------------------------------------------------
// Inference variables
//--------------------------------------------------------------------------
let tpref_is_solved (r:Typar) =
match r.Solution with
| None -> false
| _ -> true
let try_shortcut_solved_upref canShortcut (r:Typar) =
if r.Kind = KindType then failwith "try_shortcut_solved_upref: kind=type";
match r.Solution with
| Some (TType_measure unt) ->
if canShortcut then
match unt with
| MeasureVar r2 ->
match r2.Solution with
| None -> ()
| Some res as soln ->
r.Data.typar_solution <- soln;
| _ -> ()
unt
| _ ->
failwith "try_shortcut_solved_upref: unsolved"
let rec strip_upeqnsA canShortcut measure =
match measure with
| MeasureVar r when tpref_is_solved r -> strip_upeqnsA canShortcut (try_shortcut_solved_upref canShortcut r)
| _ -> measure
let rec strip_tpeqnsA canShortcut ty =
match ty with
| TType_var r ->
match r.Solution with
| Some soln ->
if canShortcut then
match soln with
// We avoid shortcutting when there are additional constraints on the type variable we're trying to cut out
// This is only because IterType likes to walk _all_ the constraints _everywhere_ in a type, including
// those attached to _solved_ type variables. In an ideal world this would never be needed - see the notes
// on IterType.
| TType_var r2 when r2.Constraints.IsEmpty ->
match r2.Solution with
| None -> ()
| Some res as soln2 ->
r.Data.typar_solution <- soln2;
| _ -> ()
strip_tpeqnsA canShortcut soln
| None ->
ty
| TType_measure measure ->
TType_measure (strip_upeqnsA canShortcut measure)
| _ -> ty
let strip_tpeqns ty = strip_tpeqnsA false ty
let strip_upeqns measure = strip_upeqnsA false measure
//--------------------------------------------------------------------------
// Construct local references
//--------------------------------------------------------------------------
let mk_nlr mp id = {nlr_nlpath = mp; nlr_item=id }
let mk_local_tcref x = ERef_private x
let mk_nonlocal_tcref mp id = ERef_nonlocal (mk_nlr mp id)
let mk_nonlocal_vref mp id = VRef_nonlocal (mk_nlr mp id)
let mk_nonlocal_tcref_preresolved x mp id = ERef_nonlocal_preresolved x (mk_nlr mp id)
let mk_nonlocal_vref_preresolved x mp id = VRef_nonlocal_preresolved x (mk_nlr mp id)
//--------------------------------------------------------------------------
// From Ref_private to Ref_nonlocal when exporting data.
//--------------------------------------------------------------------------
let enclosing_nlpath_of_pubpath viewedCcu (PubPath(p,nm)) = NLPath(viewedCcu, p)
let nlpath_of_pubpath viewedCcu (PubPath(p,nm)) = NLPath(viewedCcu,Array.append p [| nm |])
let nlpath_of_modul viewedCcu (v:ModuleOrNamespace) = v.PublicPath |> Option.map (nlpath_of_pubpath viewedCcu)
let nlref_of_pubpath viewedCcu (PubPath(p,nm) as pubpath) x =
mk_nlr (enclosing_nlpath_of_pubpath viewedCcu pubpath) nm
let rescope_val_pubpath viewedCcu pubpath x : ValRef = VRef_nonlocal (nlref_of_pubpath viewedCcu pubpath x)
let rescope_tycon_pubpath viewedCcu pubpath x : TyconRef = ERef_nonlocal (nlref_of_pubpath viewedCcu pubpath x)
//---------------------------------------------------------------------------
// Equality between TAST items.
//---------------------------------------------------------------------------
let vref_in_this_assembly compilingFslib (x: ValRef) =
match x with
| VRef_private _ -> true
| VRef_nonlocal _ -> compilingFslib
let tcref_in_this_assembly compilingFslib (x: TyconRef) =
match x with
| ERef_private _ -> true
| ERef_nonlocal _ -> compilingFslib
let array_path_eq (y1:string[]) (y2:string[]) =
let len1 = y1.Length
let len2 = y2.Length
(len1 = len2) &&
(let rec loop i = (i >= len1) || (y1.[i] = y2.[i] && loop (i+1))
loop 0)
let nlpath_eq (NLPath(x1,y1) as smr1) (NLPath(x2,y2) as smr2) =
smr1 === smr2 || (ccu_eq x1 x2 && array_path_eq y1 y2)
/// This predicate tests if non-local resolution paths are definitely known to resolve
/// to different entities. All references with different named paths always resolve to
/// different entities. Two references with the same named paths may resolve to the same
/// entities even if they reference through different CCUs, because one reference
/// may be forwarded to another via a .NET TypeForwarder.
let nlpath_definitely_not_eq (NLPath(x1,y1)) (NLPath(x2,y2) as smr2) =
not (array_path_eq y1 y2)
let nlref_eq nlr1 nlr2 =
(nlr1 === nlr2 ) ||
(nlpath_eq nlr1.nlr_nlpath nlr2.nlr_nlpath &&
(nlr1.nlr_item === nlr2.nlr_item || nlr1.nlr_item = nlr2.nlr_item))
/// See nlpath_definitely_not_eq
let nlref_definitely_not_eq nlr1 nlr2 =
(nlpath_definitely_not_eq nlr1.nlr_nlpath nlr2.nlr_nlpath || nlr1.nlr_item <> nlr2.nlr_item)
/// Compiler-internal references to items in fslib are generated as Ref_nonlocal even when compiling fslib
let fslib_nlpath_eq_pubpath nlr (PubPath(path,nm)) =
nlr.nlr_item = nm &&
let (NLPath(ccu,p)) = nlr.nlr_nlpath
if (array_path_eq p path) then true
else ( (* warning(Failure(sprintf "%s <> %s" (text_of_arr_path p) (text_of_arr_path path))); *) false)
let fslib_refs_eq ppF namef (|Ref_private|Ref_nonlocal|) fslibCcu x y =
match x,y with
| (Ref_nonlocal nlr, Ref_private x)
| (Ref_private x, Ref_nonlocal nlr) ->
ccu_eq (ccu_of_nlpath nlr.nlr_nlpath) fslibCcu &&
let pubpathOpt = ppF x
isSome pubpathOpt && fslib_nlpath_eq_pubpath nlr (Option.get pubpathOpt)
| (Ref_private x, Ref_private y) ->
let pubpathOpt1 = ppF x
let pubpathOpt2 = ppF y
isSome pubpathOpt1 && isSome pubpathOpt2 && pubpathOpt1 = pubpathOpt2
| _ -> false
let prim_tcref_eq compilingFslib fslibCcu (x : TyconRef) (y : TyconRef) =
x === y ||
match x.IsResolved,y.IsResolved with
| true, true when not compilingFslib -> x.ResolvedTarget === y.ResolvedTarget
| _ ->
match x.IsLocalRef,y.IsLocalRef with
| false, false when
(// Two tcrefs with identical paths are always equal
nlref_eq x.nlr y.nlr ||
// The tcrefs may have forwarders. If they may possibly be equal then resolve them to get their canonical references
// and compare those using pointer equality.
(not (nlref_definitely_not_eq x.nlr y.nlr) && x.Deref === y.Deref)) ->
true
| _ ->
compilingFslib && fslib_refs_eq pubpath_of_tycon (fun (tc:Tycon) -> tc.MangledName) (|ERef_private|ERef_nonlocal|) fslibCcu x y
let prim_ucref_eq compilingFslib fslibCcu (UCRef(tcr1,c1) as uc1) (UCRef(tcr2,c2) as uc2) =
uc1 === uc2 || (prim_tcref_eq compilingFslib fslibCcu tcr1 tcr2 && c1 = c2)
let prim_vref_eq compilingFslib fslibCcu (x : ValRef) (y : ValRef) =
x === y ||
match x.IsResolved,y.IsResolved with
| true, true when x.ResolvedTarget === y.ResolvedTarget -> true
| _ ->
match x.IsLocalRef,y.IsLocalRef with
| true,true when vspec_eq x.PrivateTarget y.PrivateTarget -> true
| false,false when nlref_eq x.nlr y.nlr -> true
| _ -> compilingFslib && fslib_refs_eq pubpath_of_val name_of_val (|VRef_private|VRef_nonlocal|) fslibCcu x y
//---------------------------------------------------------------------------
// pubpath/cpath mess
//---------------------------------------------------------------------------
#if STANDALONE_METADATA
#else
let GetNameOfScopeRef sref =
match sref with
| ScopeRef_local -> "<local>"
| ScopeRef_module mref -> mref.Name
| ScopeRef_assembly aref -> aref.Name
let mangled_text_of_cpath (CompPath(scoref,path)) = GetNameOfScopeRef scoref ^"/"^ text_of_path (List.map fst path)
let string_of_access (TAccess paths) = String.concat ";" (List.map mangled_text_of_cpath paths)
#endif
let mangled_path_of_cpath (CompPath(scoref,path)) = List.map fst path
let pubpath_of_cpath (id:ident) cpath = PubPath(Array.of_list (mangled_path_of_cpath cpath),id.idText)
let demangled_path_of_cpath (CompPath(scoref,path)) =
path |> List.map (fun (nm,k) -> demangled_name_of_entity_name nm k)
let parent_cpath (CompPath(scoref,cpath)) =
let a,b = List.frontAndBack cpath
CompPath(scoref,a)
let full_cpath_of_modul (m:ModuleOrNamespace) =
let (CompPath(scoref,cpath)) = m.CompilationPath
CompPath(scoref,cpath@[(m.MangledName, m.ModuleOrNamespaceType.ModuleOrNamespaceKind)])
// Can cpath2 be accessed given a right to access cpath1. That is, is cpath2 a nested type or namespace of cpath1. Note order of arguments.
let can_access_cpath_from (CompPath(scoref1,cpath1)) (CompPath(scoref2,cpath2)) =
let rec loop p1 p2 =
match p1,p2 with
| (a1,k1)::rest1, (a2,k2)::rest2 -> (a1=a2) && (k1=k2) && loop rest1 rest2
| [],_ -> true
| _ -> false // cpath1 is longer
loop cpath1 cpath2 &&
(scoref1 = scoref2)
let can_access_cpath_from_one_of cpaths cpathTest =
List.exists (fun cpath -> can_access_cpath_from cpath cpathTest) cpaths
let can_access_from (TAccess x) cpath =
x |> List.forall (fun cpath1 -> can_access_cpath_from cpath1 cpath)
let can_access_from_everywhere (TAccess x) = x.IsEmpty
let can_access_from_somewhere (TAccess x) = true
let IsLessAccessible (TAccess aa) (TAccess bb) =
(* not (ListSet.isSubsetOf (=) aa bb) *)
not (aa |> List.forall(fun a -> bb |> List.exists (fun b -> can_access_cpath_from a b)))
/// Given (newPath,oldPath) replace oldPath by newPath in the TAccess.
let access_subst_paths (newPath,oldPath) (TAccess paths) =
let subst cpath = if cpath=oldPath then newPath else cpath
TAccess (List.map subst paths)
let cpath_of_ccu (ccu:ccu) = CompPath(ccu.ILScopeRef,[])
let nlpath_of_ccu ccu = NLPath(ccu,[| |])
let taccessPublic = TAccess []
//---------------------------------------------------------------------------
// Construct TAST nodes
//---------------------------------------------------------------------------
let SkipFreeVarsCache() = ()
let SkipCacheCompute (cache:SkipFreeVarsCache) f = f()
let NewFreeVarsCache() = new_cache ()
let MakeUnionCasesTable ucs =
{ ucases_by_index = Array.of_list ucs;
ucases_by_name = NameMap.of_keyed_list (fun uc -> uc.DisplayName) ucs }
let MakeRecdFieldsTable ucs =
{ rfields_by_index = Array.of_list ucs;
rfields_by_name = ucs |> NameMap.of_keyed_list (fun rfld -> rfld.Name) }
let MakeUnionCases ucs =
{ funion_ucases=MakeUnionCasesTable ucs;
#if STANDALONE_METADATA
#else
funion_ilx_repr=new_cache()
#endif
}
let MakeUnionRepr ucs = TFiniteUnionRepr (MakeUnionCases ucs)
let new_ccu nm x : ccu = CcuThunk.Create(nm,x)
let NewTypar (kind,rigid,Typar(id,staticReq,isCompGen),isFromError,dynamicReq,attribs) =
Typar.New
{ typar_id = id;
typar_stamp = new_stamp();
typar_flags= TyparFlags.encode (kind,rigid,isFromError,isCompGen,staticReq,dynamicReq);
typar_attribs= attribs;
typar_solution = None;
typar_constraints=[];
typar_xmldoc = emptyXmlDoc; (* todo *) }
let mk_rigid_typar nm m = NewTypar (KindType,TyparRigid,Typar(mksyn_id m nm,NoStaticReq,true),false,DynamicReq,[])
let new_tcaug () = { tcaug_compare=None;
tcaug_compare_withc=None;
tcaug_equals=None;
tcaug_structural_hash=None;
tcaug_hash_and_equals_withc=None;
tcaug_hasObjectGetHashCode=false;
tcaug_adhoc=NameMultiMap.empty;
tcaug_super=None;
tcaug_implements=[];
tcaug_closed=false;
tcaug_abstract=false; }
let combineAccess (TAccess a1) (TAccess a2) = TAccess(a1@a2)
let NewUnionCase id nm tys rty attribs docOption vis =
{ ucase_id=id;
ucase_il_name=nm;
ucase_xmldoc=docOption;
ucase_access=vis;
ucase_rfields = MakeRecdFieldsTable tys;
ucase_rty = rty;
ucase_attribs=attribs }
let set_tcaug_compare tcaug x = tcaug.tcaug_compare <- Some x
let set_tcaug_compare_withc tcaug x = tcaug.tcaug_compare_withc <- Some x
let set_tcaug_equals tcaug x = tcaug.tcaug_equals <- Some x
let set_tcaug_hash_and_equals_withc tcaug x = tcaug.tcaug_hash_and_equals_withc <- Some x
let set_tcaug_hasObjectGetHashCode tcaug b = tcaug.tcaug_hasObjectGetHashCode <- b
let NewModuleOrNamespaceType mkind tycons vals =
new ModuleOrNamespaceType(mkind, NameMap.of_keyed_list name_of_val vals, NameMap.of_keyed_list (fun (tc:Tycon) -> tc.MangledName) tycons)
let empty_mtype mkind = NewModuleOrNamespaceType mkind [] []
let NewExn cpath (id:ident) vis repr attribs doc =
let id = mksyn_id id.idRange (mangle_exception_name id.idText)
Tycon.New "exnc"
{ entity_stamp=new_stamp();
entity_attribs=attribs;
entity_kind=KindType;
entity_name=id.idText;
entity_range=id.idRange;
entity_exn_info= repr;
entity_tycon_tcaug=new_tcaug();
entity_xmldoc=doc;
entity_pubpath=cpath |> Option.map (pubpath_of_cpath id);
entity_accessiblity=vis;
entity_tycon_repr_accessibility=vis;
entity_modul_contents = notlazy (empty_mtype FSharpModule);
entity_cpath= cpath;
entity_typars=LazyWithContext<_,_>.NotLazy [];
entity_tycon_abbrev = None;
entity_tycon_repr = None;
entity_uses_prefix_display=false; (* REVIEW, though note these are not generic anyway *)
entity_is_modul_or_namespace = false;
entity_il_repr_cache= new_cache() ; }
let NewRecdField stat konst id ty isMutable pattribs fattribs docOption vis secret =
{ rfield_mutable=isMutable;
rfield_pattribs=pattribs;
rfield_fattribs=fattribs;
rfield_type=ty;
rfield_static=stat;
rfield_const=konst;
rfield_access = vis;
rfield_secret = secret;
rfield_xmldoc = docOption;
rfield_id=id; }
let NewTycon cpath (nm,m) vis repr_vis kind typars docOption preferPostfix mtyp =
let stamp = new_stamp()
Tycon.New "tycon"
{ entity_stamp=stamp;
entity_name=nm;
entity_kind=kind;
entity_range=m;
entity_uses_prefix_display=preferPostfix;
entity_attribs=[];
entity_typars=typars;
entity_tycon_abbrev = None;
entity_tycon_repr = None;
entity_tycon_repr_accessibility = repr_vis;
entity_exn_info=TExnNone;
entity_tycon_tcaug=new_tcaug();
entity_modul_contents = mtyp;
entity_accessiblity=vis;
entity_xmldoc = docOption;
entity_pubpath=cpath |> Option.map (pubpath_of_cpath (mksyn_id m nm));
entity_cpath = cpath;
entity_is_modul_or_namespace =false;
entity_il_repr_cache = new_cache(); }
let NewILTycon nlpath id tps (scoref,enc,tdef) mtyp =
let tycon = NewTycon nlpath id taccessPublic taccessPublic KindType tps emptyXmlDoc true mtyp
tycon.Data.entity_tycon_repr <- Some (TILObjModelRepr (scoref,enc,tdef));
tycon.TypeContents.tcaug_closed <- true;
tycon
exception Duplicate of string * string * range
exception NameClash of string * string * string * range * string * string * range
exception FullAbstraction of string * range
let mk_namemap s (idf: _ -> ident) items =
(items,NameMap.empty) ||> List.foldBack (fun item sofar ->
let id = idf item
if NameMap.mem id.idText sofar then raise (Duplicate(s,id.idText,id.idRange));
NameMap.add id.idText item sofar)
let mk_tycon_namemap = mk_namemap "type" id_of_tycon
let mk_exnconstr_namemap = mk_namemap "exception" id_of_tycon
let mk_val_namemap = mk_namemap "value" id_of_val
let NewModuleOrNamespace cpath vis (id:ident) xml attribs mtype =
let stamp = new_stamp()
// Put the module suffix on if needed
Tycon.New "mspec"
{ entity_name=id.idText;
entity_range = id.idRange;
entity_stamp=stamp;
entity_kind=KindType;
entity_modul_contents = mtype;
entity_uses_prefix_display=false;
entity_is_modul_or_namespace =true;
entity_typars=LazyWithContext<_,_>.NotLazy [];
entity_tycon_abbrev = None;
entity_tycon_repr = None;
entity_tycon_repr_accessibility = vis;
entity_exn_info=TExnNone;
entity_tycon_tcaug=new_tcaug();
entity_pubpath=cpath |> Option.map (pubpath_of_cpath id);
entity_cpath=cpath;
entity_accessiblity=vis;
entity_attribs=attribs;
entity_xmldoc=xml;
entity_il_repr_cache = new_cache(); }
let NewVal (id:ident,ty,isMutable,isCompGen,arity,cpathOpt,vis,vrec,specialRepr,baseOrThis,attribs,mustinline,doc,isTopBinding,isExtensionMember,isImplicitCtor,isTyFunc,konst,actualParent) : Val =
let stamp = new_stamp()
if !verboseStamps then dprintf "NewVal, %s#%d\n" id.idText stamp;
Val.New
{ val_stamp = stamp;
val_name=id.idText;
val_range=id.idRange;
val_defn_range=id.idRange;
val_defn=None;
val_top_repr_info= arity;
val_actual_parent= actualParent;
val_flags = ValFlags.encode(vrec,baseOrThis,isCompGen,mustinline,isMutable,isTopBinding,isExtensionMember,isImplicitCtor,isTyFunc);
val_pubpath= cpathOpt |> Option.map (pubpath_of_cpath id);
val_const= konst;
val_access=vis;
val_member_info=specialRepr;
val_attribs=attribs;
val_type = ty;
val_xmldoc = doc; }
let NewCcuContents sref m nm mty =
NewModuleOrNamespace (Some(CompPath(sref,[]))) taccessPublic (mksyn_id m nm) emptyXmlDoc [] (notlazy mty)
//--------------------------------------------------------------------------
// Cloning and adjusting
//--------------------------------------------------------------------------
/// Create a tycon based on an existing one using the function 'f'.
/// We require that we be given the new parent for the new tycon.
/// We pass the new tycon to 'f' in case it needs to reparent the
/// contents of the tycon.
let NewModifiedTycon f (orig:Tycon) =
let stamp = new_stamp()
let data = orig.Data
if !verboseStamps then dprintf "NewModifiedTycon, %s#%d, based on %s#%d\n" orig.MangledName stamp orig.MangledName data.entity_stamp;
Tycon.New "NewModifiedTycon" (f { data with entity_stamp=stamp; })
/// Create a module Tycon based on an existing one using the function 'f'.
/// We require that we be given the parent for the new module.
/// We pass the new module to 'f' in case it needs to reparent the
/// contents of the module.
let NewModifiedModuleOrNamespace f orig =
orig |> NewModifiedTycon (fun d ->
{ d with entity_modul_contents = notlazy (f (d.entity_modul_contents.Force())) })
/// Create a Val based on an existing one using the function 'f'.
/// We require that we be given the parent for the new Val.
let NewModifiedVal f (orig:Val) =
let data = orig.Data
let stamp = new_stamp()
if !verboseStamps then dprintf "NewModifiedVal, stamp #%d, based on stamp #%d\n" stamp data.val_stamp;
let data' = f { data with val_stamp=stamp }
Val.New data'
let NewClonedModuleOrNamespace orig = NewModifiedModuleOrNamespace (fun mty -> mty) orig
let NewClonedTycon orig = NewModifiedTycon (fun d -> d) orig
//------------------------------------------------------------------------------
/// Combine module types when multiple namespace fragments contribute to the
/// same namespace, making new module specs as we go.
let private combine_maps f m1 m2 =
Map.foldBack (fun k v acc -> Map.add k (if Map.contains k m2 then f [v;Map.find k m2] else f [v]) acc) m1
(Map.foldBack (fun k v acc -> if Map.contains k m1 then acc else Map.add k (f [v]) acc) m2 Map.empty)
let rec private combine_msigtyps path m (mty1:ModuleOrNamespaceType) (mty2:ModuleOrNamespaceType) =
match mty1.ModuleOrNamespaceKind,mty2.ModuleOrNamespaceKind with
| Namespace,Namespace ->
let kind = mty1.ModuleOrNamespaceKind
let entities = combine_maps (combine_entitiesl path) mty1.AllEntities mty2.AllEntities
let vals = combine_maps (function [] -> failwith "??" | [v] -> v | (v:Val) :: _ -> errorR(Error( sprintf "two values named '%s' occur in namespace '%s' in two parts of this assembly" v.MangledName (text_of_path path),v.Range)); v) mty1.AllValuesAndMembers mty2.AllValuesAndMembers
new ModuleOrNamespaceType(kind, vals, entities)
| Namespace, _ | _,Namespace -> error(Error(sprintf "a namespace and a module named '%s' both occur in two parts of this assembly" (text_of_path path),m))
| _-> error(Error(sprintf "two modules named '%s' occur in two parts of this assembly" (text_of_path path),m))
and private combine_entitiesl path l =
match l with
| h :: t -> List.fold (combine_entites path) h t
| _ -> failwith "combine_entitiesl"
and private combine_entites path (tycon1:Entity) (tycon2:Entity) =
match tycon1.IsModuleOrNamespace, tycon2.IsModuleOrNamespace with
| true,true ->
tycon1 |> NewModifiedTycon (fun data1 ->
{ data1 with
entity_xmldoc = MergeXmlDoc tycon1.XmlDoc tycon2.XmlDoc;
entity_attribs = tycon1.Attribs @ tycon2.Attribs;
entity_modul_contents=lazy (combine_msigtyps (path@[demangled_name_of_modul tycon2]) tycon2.Range tycon1.ModuleOrNamespaceType tycon2.ModuleOrNamespaceType); })
| false,false ->
error(Error( sprintf "two type definitions named '%s' occur in namespace '%s' in two parts of this assembly" tycon2.MangledName (text_of_path path),tycon2.Range))
| _,_ ->
error(Error( sprintf "a module and a type definition named '%s' occur in namespace '%s' in two parts of this assembly" tycon2.MangledName (text_of_path path),tycon2.Range))
and combine_mtyps path m l =
match l with
| h :: t -> List.fold (combine_msigtyps path m) h t
| _ -> failwith "combine_mtyps"
//--------------------------------------------------------------------------
// Resource format for pickled data
//--------------------------------------------------------------------------
let FSharpOptimizationDataResourceName = "FSharpOptimizationData"
let FSharpSignatureDataResourceName = "FSharpSignatureData"
#if STANDALONE_METADATA
type TcGlobals =
{ nativeptr_tcr:TyconRef;
nativeint_tcr:TyconRef;
byref_tcr:TyconRef;
il_arr1_tcr:TyconRef;
il_arr2_tcr:TyconRef;
il_arr3_tcr:TyconRef;
il_arr4_tcr:TyconRef;
unit_tcr:TyconRef; }
let mk_nativeptr_typ g ty = TType_app (g.nativeptr_tcr, [ty])
let mk_byref_typ g ty = TType_app (g.byref_tcr, [ty])
let mk_unit_typ g = TType_app (g.unit_tcr, [])
let mk_nativeint_typ g = TType_app (g.nativeint_tcr, [])
let mk_multi_dim_array_typ g n ty =
if n = 1 then TType_app (g.il_arr1_tcr, [ty])
elif n = 2 then TType_app (g.il_arr2_tcr, [ty])
elif n = 3 then TType_app (g.il_arr3_tcr, [ty])
elif n = 4 then TType_app (g.il_arr4_tcr, [ty])
else failwith "F# supports a maxiumum .NET array dimension of 4"
#endif