* update fantomas (#13206)

* Format most of FSharp.Core (#13150)

* modify fantomasignore

* fix setting

* no single line functions in FSHarp.Core

* update fantomas

* apply formatting

* Format src/Compiler/Driver (#13195)

* adjust settings

* adjust code

* adjust settings

* adjust code

* fix code before formatting

* remove unnecessary yield

* manual pre-formatting

* preadjust code

* preadjust code

* preadjust code

* preadjust code

* adjust settings"

* adjust settings"

* adjust settings

* adjust settings

* fix build

* adjust settings

* adjust code

* adjust code

* adjust code

* update fantomas

* apply formatting

* apply formatting (fix build) (#13209)

* preformat

* apply formatting

Co-authored-by: Don Syme <dsyme@users.noreply.github.com>
This commit is contained in:
dotnet bot 2022-05-31 10:11:55 -07:00 коммит произвёл GitHub
Родитель ad3e6de201
Коммит e1e4d6a8b1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
88 изменённых файлов: 18509 добавлений и 12119 удалений

Просмотреть файл

@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"fantomas": {
"version": "5.0.0-alpha-006",
"version": "5.0.0-alpha-008",
"commands": [
"fantomas"
]

Просмотреть файл

@ -1,8 +1,11 @@
root = true
# max_line_length is set to 140. At some point we will reduce it to 120 for as many files as reasonable.
[*.fs]
max_line_length=140
fsharp_newline_between_type_definition_and_members=true
fsharp_max_function_binding_width=40
fsharp_max_if_then_else_short_width=60
fsharp_max_infix_operator_expression=80
fsharp_max_array_or_list_width=80
fsharp_max_array_or_list_number_of_items=5
@ -13,3 +16,13 @@ fsharp_keep_max_number_of_blank_lines=1
[*.fsi]
fsharp_newline_between_type_definition_and_members=true
fsharp_keep_max_number_of_blank_lines=1
# These files contains many imperative if-then expressions which are not clearer on one line
# Reducing fsharp_max_if_then_else_short_width back to its default formats these over multiple lines.
[src/FSharp.Build/*.fs]
fsharp_max_if_then_else_short_width=40
# This file contains a long list of one-line function definitions. Increasing
# fsharp_max_function_binding_width formats these over a single line.
[src/Compiler/Driver/CompilerDiagnostics.fs]
fsharp_max_function_binding_width=70

Просмотреть файл

@ -13,11 +13,9 @@ artifacts/
# Explicitly unformatted implementation files
src/FSharp.Core/**/*.fs
src/Compiler/Checking/**/*.fs
src/Compiler/CodeGen/**/*.fs
src/Compiler/DependencyManager/**/*.fs
src/Compiler/Driver/**/*.fs
src/Compiler/Facilities/**/*.fs
src/Compiler/Interactive/**/*.fs
src/Compiler/Legacy/**/*.fs
@ -28,6 +26,23 @@ src/Compiler/SyntaxTree/**/*.fs
src/Compiler/TypedTree/**/*.fs
src/Microsoft.FSharp.Compiler/**/*.fs
# Fantomas limitations on implementation files in FSharp.Core (to investigate)
src/FSharp.Core/array2.fs
src/FSharp.Core/array3.fs
src/FSharp.Core/Linq.fs
src/FSharp.Core/local.fs
src/FSharp.Core/nativeptr.fs
src/FSharp.Core/prim-types-prelude.fs
src/FSharp.Core/prim-types.fs
src/FSharp.Core/printf.fs
src/FSharp.Core/Query.fs
src/FSharp.Core/seqcore.fs
# Fantomas limitation https://github.com/fsprojects/fantomas/issues/2264
src/FSharp.Core/SI.fs
# Fantomas limitations on implementation files (to investigate)
src/Compiler/AbstractIL/ilwrite.fs

Просмотреть файл

@ -25,9 +25,7 @@ open Internal.Utilities
let logging = false
let _ =
if logging then
dprintn "* warning: Il.logging is on"
let _ = if logging then dprintn "* warning: Il.logging is on"
let int_order = LanguagePrimitives.FastGenericComparer<int>
@ -70,19 +68,13 @@ let memoizeNamespaceRightTable =
let memoizeNamespacePartTable = ConcurrentDictionary<string, string>()
let splitNameAt (nm: string) idx =
if idx < 0 then
failwith "splitNameAt: idx < 0"
if idx < 0 then failwith "splitNameAt: idx < 0"
let last = nm.Length - 1
if idx > last then
failwith "splitNameAt: idx > last"
if idx > last then failwith "splitNameAt: idx > last"
(nm.Substring(0, idx)),
(if idx < last then
nm.Substring(idx + 1, last - idx)
else
"")
(nm.Substring(0, idx)), (if idx < last then nm.Substring(idx + 1, last - idx) else "")
let rec splitNamespaceAux (nm: string) =
match nm.IndexOf '.' with
@ -218,14 +210,10 @@ module SHA1 =
let inline (>>>&) (x: int) (y: int) = int32 (uint32 x >>> y)
let f (t, b, c, d) =
if t < 20 then
(b &&& c) ||| ((~~~b) &&& d)
elif t < 40 then
b ^^^ c ^^^ d
elif t < 60 then
(b &&& c) ||| (b &&& d) ||| (c &&& d)
else
b ^^^ c ^^^ d
if t < 20 then (b &&& c) ||| ((~~~b) &&& d)
elif t < 40 then b ^^^ c ^^^ d
elif t < 60 then (b &&& c) ||| (b &&& d) ||| (c &&& d)
else b ^^^ c ^^^ d
[<Literal>]
let k0to19 = 0x5A827999
@ -563,8 +551,7 @@ type ILAssemblyRef(data) =
addC (convDigit (int32 v / 16))
addC (convDigit (int32 v % 16))
// retargetable can be true only for system assemblies that definitely have Version
if aref.Retargetable then
add ", Retargetable=Yes"
if aref.Retargetable then add ", Retargetable=Yes"
b.ToString()
@ -773,17 +760,9 @@ type ILTypeRef =
else
y.ApproxId
let xScope =
if isPrimaryX then
primaryScopeRef
else
x.Scope
let xScope = if isPrimaryX then primaryScopeRef else x.Scope
let yScope =
if isPrimaryY then
primaryScopeRef
else
y.Scope
let yScope = if isPrimaryY then primaryScopeRef else y.Scope
(xApproxId = yApproxId)
&& (xScope = yScope)
@ -806,10 +785,7 @@ type ILTypeRef =
else
let c = compare x.Name y.Name
if c <> 0 then
c
else
compare x.Enclosing y.Enclosing
if c <> 0 then c else compare x.Enclosing y.Enclosing
member tref.FullName = String.concat "." (tref.Enclosing @ [ tref.Name ])
@ -883,11 +859,7 @@ and [<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugT
&& (x.GenericArgs = y.GenericArgs)
override x.ToString() =
x.TypeRef.ToString()
+ if isNil x.GenericArgs then
""
else
"<...>"
x.TypeRef.ToString() + if isNil x.GenericArgs then "" else "<...>"
and [<RequireQualifiedAccess; StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>] ILType =
| Void
@ -1859,20 +1831,13 @@ type ILGenericParameterDefs = ILGenericParameterDef list
let memberAccessOfFlags flags =
let f = (flags &&& 0x00000007)
if f = 0x00000001 then
ILMemberAccess.Private
elif f = 0x00000006 then
ILMemberAccess.Public
elif f = 0x00000004 then
ILMemberAccess.Family
elif f = 0x00000002 then
ILMemberAccess.FamilyAndAssembly
elif f = 0x00000005 then
ILMemberAccess.FamilyOrAssembly
elif f = 0x00000003 then
ILMemberAccess.Assembly
else
ILMemberAccess.CompilerControlled
if f = 0x00000001 then ILMemberAccess.Private
elif f = 0x00000006 then ILMemberAccess.Public
elif f = 0x00000004 then ILMemberAccess.Family
elif f = 0x00000002 then ILMemberAccess.FamilyAndAssembly
elif f = 0x00000005 then ILMemberAccess.FamilyOrAssembly
elif f = 0x00000003 then ILMemberAccess.Assembly
else ILMemberAccess.CompilerControlled
let convertMemberAccess (ilMemberAccess: ILMemberAccess) =
match ilMemberAccess with
@ -2509,12 +2474,9 @@ let typeAccessOfFlags flags =
let typeEncodingOfFlags flags =
let f = (flags &&& 0x00030000)
if f = 0x00020000 then
ILDefaultPInvokeEncoding.Auto
elif f = 0x00010000 then
ILDefaultPInvokeEncoding.Unicode
else
ILDefaultPInvokeEncoding.Ansi
if f = 0x00020000 then ILDefaultPInvokeEncoding.Auto
elif f = 0x00010000 then ILDefaultPInvokeEncoding.Unicode
else ILDefaultPInvokeEncoding.Ansi
[<RequireQualifiedAccess>]
type ILTypeDefKind =
@ -3613,32 +3575,20 @@ and rescopeILType scoref ty =
| ILType.Boxed cr1 ->
let cr2 = rescopeILTypeSpec scoref cr1
if cr1 === cr2 then
ty
else
mkILBoxedType cr2
if cr1 === cr2 then ty else mkILBoxedType cr2
| ILType.Array (s, ety1) ->
let ety2 = rescopeILType scoref ety1
if ety1 === ety2 then
ty
else
ILType.Array(s, ety2)
if ety1 === ety2 then ty else ILType.Array(s, ety2)
| ILType.Value cr1 ->
let cr2 = rescopeILTypeSpec scoref cr1
if cr1 === cr2 then
ty
else
ILType.Value cr2
if cr1 === cr2 then ty else ILType.Value cr2
| ILType.Modified (b, tref, ty) -> ILType.Modified(b, rescopeILTypeRef scoref tref, rescopeILType scoref ty)
| x -> x
and rescopeILTypes scoref i =
if isNil i then
i
else
List.mapq (rescopeILType scoref) i
if isNil i then i else List.mapq (rescopeILType scoref) i
and rescopeILCallSig scoref csig =
mkILCallSig (csig.CallingConv, rescopeILTypes scoref csig.ArgTypes, rescopeILType scoref csig.ReturnType)
@ -3933,13 +3883,7 @@ let prependInstrsToCode (instrs: ILInstr list) (c2: ILCode) =
let dict = Dictionary.newWithSize c2.Labels.Count
for kvp in c2.Labels do
dict.Add(
kvp.Key,
if kvp.Value = 0 then
0
else
kvp.Value + n
)
dict.Add(kvp.Key, (if kvp.Value = 0 then 0 else kvp.Value + n))
dict
@ -4013,22 +3957,10 @@ let mkILField (isStatic, nm, ty, init: ILFieldInit option, at: byte[] option, ac
fieldType = ty,
attributes =
(convertFieldAccess access
||| (if isStatic then
FieldAttributes.Static
else
enum 0)
||| (if isLiteral then
FieldAttributes.Literal
else
enum 0)
||| (if init.IsSome then
FieldAttributes.HasDefault
else
enum 0)
||| (if at.IsSome then
FieldAttributes.HasFieldRVA
else
enum 0)),
||| (if isStatic then FieldAttributes.Static else enum 0)
||| (if isLiteral then FieldAttributes.Literal else enum 0)
||| (if init.IsSome then FieldAttributes.HasDefault else enum 0)
||| (if at.IsSome then FieldAttributes.HasFieldRVA else enum 0)),
literalValue = init,
data = at,
offset = None,
@ -4362,12 +4294,7 @@ let mkCtorMethSpecForDelegate (ilg: ILGlobals) (ty: ILType, useUIntPtr) =
let argTys =
[
rescopeILType scoref ilg.typ_Object
rescopeILType
scoref
(if useUIntPtr then
ilg.typ_UIntPtr
else
ilg.typ_IntPtr)
rescopeILType scoref (if useUIntPtr then ilg.typ_UIntPtr else ilg.typ_IntPtr)
]
mkILInstanceMethSpecInTy (ty, ".ctor", argTys, ILType.Void, emptyILGenericArgsList)
@ -5143,8 +5070,8 @@ let decodeILAttribData (ca: ILAttribute) =
try
let parser = ILTypeSigParser n
parser.ParseTypeSpec(), sigptr
with
| exn -> failwith (sprintf "decodeILAttribData: error parsing type in custom attribute blob: %s" exn.Message)
with exn ->
failwith (sprintf "decodeILAttribData: error parsing type in custom attribute blob: %s" exn.Message)
| ILType.Boxed tspec when tspec.Name = "System.Object" ->
let et, sigptr = sigptr_get_u8 bytes sigptr
@ -5605,10 +5532,7 @@ and unscopeILType ty =
| x -> x
and unscopeILTypes i =
if List.isEmpty i then
i
else
List.map unscopeILType i
if List.isEmpty i then i else List.map unscopeILType i
and unscopeILCallSig csig =
mkILCallSig (csig.CallingConv, unscopeILTypes csig.ArgTypes, unscopeILType csig.ReturnType)

Просмотреть файл

@ -184,8 +184,8 @@ let cattr_ty2ty f (c: ILAttribute) =
let elems = elems |> List.map (celem_ty2ty f)
let namedArgs = namedArgs |> List.map (cnamedarg_ty2ty f)
mkILCustomAttribMethRef (meth, elems, namedArgs)
with
| _ -> c.WithMethod(meth)
with _ ->
c.WithMethod(meth)
else
c.WithMethod(meth)

Просмотреть файл

@ -253,8 +253,8 @@ type COFFResourceReader() =
if int64 relocLastAddress > stream.Length then
raise <| ResourceException "CoffResourceInvalidRelocation"
with
| :? OverflowException -> (raise <| ResourceException("CoffResourceInvalidRelocation"))
with :? OverflowException ->
(raise <| ResourceException("CoffResourceInvalidRelocation"))
let mutable relocationOffsets = Array.zeroCreate (int rsrc1.NumberOfRelocations)
@ -284,8 +284,8 @@ type COFFResourceReader() =
if lastSymAddress > stream.Length then
raise <| ResourceException "CoffResourceInvalidSymbol"
with
| :? OverflowException -> (raise <| ResourceException("CoffResourceInvalidSymbol"))
with :? OverflowException ->
(raise <| ResourceException("CoffResourceInvalidSymbol"))
let mutable outputStream = new MemoryStream(imageResourceSectionBytes)
let mutable writer = new BinaryWriter(outputStream)
@ -400,10 +400,7 @@ type VersionHelper() =
let mutable (values: uint16[]) = Array.zeroCreate 4
let mutable (lastExplicitValue: int) =
if hasWildcard then
elements.Length - 1
else
elements.Length
if hasWildcard then elements.Length - 1 else elements.Length
let mutable (parseError: bool) = false
let mutable earlyReturn = None
@ -1147,19 +1144,12 @@ type NativeResourceWriter() =
dataWriter.WriteByte 0uy
false
| e ->
failwithf
"Unknown entry %s"
(if isNull e then
"<NULL>"
else
e.GetType().FullName)
| e -> failwithf "Unknown entry %s" (if isNull e then "<NULL>" else e.GetType().FullName)
if id >= 0 then
writer.WriteInt32 id
else
if name = Unchecked.defaultof<_> then
name <- String.Empty
if name = Unchecked.defaultof<_> then name <- String.Empty
writer.WriteUInt32(nameOffset ||| 0x80000000u)
dataWriter.WriteUInt16(uint16 name.Length)

Просмотреть файл

@ -661,20 +661,16 @@ let goutput_fdef _tref env os (fd: ILFieldDef) =
output_member_access os fd.Access
output_string os " "
if fd.IsStatic then
output_string os " static "
if fd.IsStatic then output_string os " static "
if fd.IsLiteral then
output_string os " literal "
if fd.IsLiteral then output_string os " literal "
if fd.IsSpecialName then
output_string os " specialname rtspecialname "
if fd.IsInitOnly then
output_string os " initonly "
if fd.IsInitOnly then output_string os " initonly "
if fd.NotSerialized then
output_string os " notserialized "
if fd.NotSerialized then output_string os " notserialized "
goutput_typ env os fd.FieldType
output_string os " "
@ -744,8 +740,7 @@ let output_code_label os lab = output_string os (formatCodeLabel lab)
let goutput_local env os (l: ILLocal) =
goutput_typ env os l.Type
if l.IsPinned then
output_string os " pinned"
if l.IsPinned then output_string os " pinned"
let goutput_param env os (l: ILParameter) =
match l.Name with
@ -990,8 +985,7 @@ let rec goutput_instr env os inst =
let rank = shape.Rank
output_parens (output_array ", " (goutput_typ env)) os (Array.create rank PrimaryAssemblyILGlobals.typ_Int32)
| I_ldelema (ro, _, shape, tok) ->
if ro = ReadonlyAddress then
output_string os "readonly. "
if ro = ReadonlyAddress then output_string os "readonly. "
if shape = ILArrayShape.SingleDimensional then
output_string os "ldelema "
@ -1040,8 +1034,7 @@ let rec goutput_instr env os inst =
| _ -> output_string os "<printing for this instruction is not implemented>"
let goutput_ilmbody env os (il: ILMethodBody) =
if il.IsZeroInit then
output_string os " .zeroinit\n"
if il.IsZeroInit then output_string os " .zeroinit\n"
output_string os " .maxstack "
output_i32 os il.MaxStack
@ -1060,21 +1053,11 @@ let goutput_mbody is_entrypoint env os (md: ILMethodDef) =
else
output_string os "runtime "
output_string
os
(if md.IsInternalCall then
"internalcall "
else
" ")
output_string os (if md.IsInternalCall then "internalcall " else " ")
output_string os (if md.IsManaged then "managed " else " ")
output_string
os
(if md.IsForwardRef then
"forwardref "
else
" ")
output_string os (if md.IsForwardRef then "forwardref " else " ")
output_string os " \n{ \n"
goutput_security_decls env os md.SecurityDecls
@ -1084,8 +1067,7 @@ let goutput_mbody is_entrypoint env os (md: ILMethodDef) =
| MethodBody.IL il -> goutput_ilmbody env os il.Value
| _ -> ()
if is_entrypoint then
output_string os " .entrypoint"
if is_entrypoint then output_string os " .entrypoint"
output_string os "\n"
output_string os "}\n"
@ -1096,14 +1078,8 @@ let goutput_mdef env os (md: ILMethodDef) =
"virtual "
+ (if md.IsFinal then "final " else "")
+ (if md.IsNewSlot then "newslot " else "")
+ (if md.IsCheckAccessOnOverride then
" strict "
else
"")
+ (if md.IsAbstract then
" abstract "
else
"")
+ (if md.IsCheckAccessOnOverride then " strict " else "")
+ (if md.IsAbstract then " abstract " else "")
+ " "
elif md.IsNonVirtualInstance then
""
@ -1136,14 +1112,8 @@ let goutput_mdef env os (md: ILMethodDef) =
| PInvokeCharEncoding.Auto -> " autochar")
+
(if attr.NoMangle then
" nomangle"
else
"")
+ (if attr.LastError then
" lasterr"
else
"")
(if attr.NoMangle then " nomangle" else "")
+ (if attr.LastError then " lasterr" else "")
+ ")"
| _ -> "")
elif md.IsClassInitializer then
@ -1155,14 +1125,11 @@ let goutput_mdef env os (md: ILMethodDef) =
let menv = ppenv_enter_method (List.length md.GenericParams) env
output_string os " .method "
if md.IsHideBySig then
output_string os "hidebysig "
if md.IsHideBySig then output_string os "hidebysig "
if md.IsReqSecObj then
output_string os "reqsecobj "
if md.IsReqSecObj then output_string os "reqsecobj "
if md.IsSpecialName then
output_string os "specialname "
if md.IsSpecialName then output_string os "specialname "
if md.IsUnmanagedExport then
output_string os "unmanagedexp "
@ -1182,17 +1149,13 @@ let goutput_mdef env os (md: ILMethodDef) =
(goutput_params menv) os md.Parameters
output_string os " "
if md.IsSynchronized then
output_string os "synchronized "
if md.IsSynchronized then output_string os "synchronized "
if md.IsMustRun then
output_string os "/* mustrun */ "
if md.IsMustRun then output_string os "/* mustrun */ "
if md.IsPreserveSig then
output_string os "preservesig "
if md.IsPreserveSig then output_string os "preservesig "
if md.IsNoInline then
output_string os "noinlining "
if md.IsNoInline then output_string os "noinlining "
if md.IsAggressiveInline then
output_string os "aggressiveinlining "
@ -1292,17 +1255,13 @@ let rec goutput_tdef enc env contents os (cd: ILTypeDef) =
output_string os layout_attr
output_string os " "
if cd.IsSealed then
output_string os "sealed "
if cd.IsSealed then output_string os "sealed "
if cd.IsAbstract then
output_string os "abstract "
if cd.IsAbstract then output_string os "abstract "
if cd.IsSerializable then
output_string os "serializable "
if cd.IsSerializable then output_string os "serializable "
if cd.IsComInterop then
output_string os "import "
if cd.IsComInterop then output_string os "import "
output_sqstring os cd.Name
goutput_gparams env os cd.GenericParams
@ -1380,8 +1339,7 @@ let output_assemblyRef os (aref: ILAssemblyRef) =
output_string os " .assembly extern "
output_sqstring os aref.Name
if aref.Retargetable then
output_string os " retargetable "
if aref.Retargetable then output_string os " retargetable "
output_string os " { "
output_option output_hash os aref.Hash
@ -1470,10 +1428,7 @@ let goutput_module_manifest env os modul =
os
((if modul.IsILOnly then 0x0001 else 0)
||| (if modul.Is32Bit then 0x0002 else 0)
||| (if modul.Is32BitPreferred then
0x00020003
else
0))
||| (if modul.Is32BitPreferred then 0x00020003 else 0))
List.iter (fun r -> goutput_resource env os r) (modul.Resources.AsList())
output_string os "\n"

Просмотреть файл

@ -41,15 +41,15 @@ let _ =
let noStableFileHeuristic =
try
(Environment.GetEnvironmentVariable("FSharp_NoStableFileHeuristic") <> null)
with
| _ -> false
with _ ->
false
let alwaysMemoryMapFSC =
try
(Environment.GetEnvironmentVariable("FSharp_AlwaysMemoryMapCommandLineCompiler")
<> null)
with
| _ -> false
with _ ->
false
let stronglyHeldReaderCacheSizeDefault = 30
@ -58,8 +58,8 @@ let stronglyHeldReaderCacheSize =
(match Environment.GetEnvironmentVariable("FSharp_StronglyHeldBinaryReaderCacheSize") with
| null -> stronglyHeldReaderCacheSizeDefault
| s -> int32 s)
with
| _ -> stronglyHeldReaderCacheSizeDefault
with _ ->
stronglyHeldReaderCacheSizeDefault
let singleOfBits (x: int32) =
BitConverter.ToSingle(BitConverter.GetBytes x, 0)
@ -101,12 +101,9 @@ let uncodedTokenToTypeDefOrRefOrSpec (tab, tok) =
let uncodedTokenToMethodDefOrRef (tab, tok) =
let tag =
if tab = TableNames.Method then
mdor_MethodDef
elif tab = TableNames.MemberRef then
mdor_MemberRef
else
failwith "bad table in uncodedTokenToMethodDefOrRef"
if tab = TableNames.Method then mdor_MethodDef
elif tab = TableNames.MemberRef then mdor_MemberRef
else failwith "bad table in uncodedTokenToMethodDefOrRef"
TaggedIndex(tag, tok)
@ -1382,8 +1379,7 @@ let seekReadGuidIdx (ctxt: ILMetadataReader) mdv (addr: byref<int>) = seekReadId
let seekReadBlobIdx (ctxt: ILMetadataReader) mdv (addr: byref<int>) = seekReadIdx ctxt.blobsBigness mdv &addr
let seekReadModuleRow (ctxt: ILMetadataReader) mdv idx =
if idx = 0 then
failwith "cannot read Module table row 0"
if idx = 0 then failwith "cannot read Module table row 0"
let mutable addr = ctxt.rowAddr TableNames.Module idx
let generation = seekReadUInt16Adv mdv &addr
@ -1695,10 +1691,7 @@ let readStringHeapUncached ctxtH idx =
let readStringHeap (ctxt: ILMetadataReader) idx = ctxt.readStringHeap idx
let readStringHeapOption (ctxt: ILMetadataReader) idx =
if idx = 0 then
None
else
Some(readStringHeap ctxt idx)
if idx = 0 then None else Some(readStringHeap ctxt idx)
let readBlobHeapUncached ctxtH idx =
let (ctxt: ILMetadataReader) = getHole ctxtH
@ -1713,10 +1706,7 @@ let readBlobHeapUncached ctxtH idx =
let readBlobHeap (ctxt: ILMetadataReader) idx = ctxt.readBlobHeap idx
let readBlobHeapOption ctxt idx =
if idx = 0 then
None
else
Some(readBlobHeap ctxt idx)
if idx = 0 then None else Some(readBlobHeap ctxt idx)
//let readGuidHeap ctxt idx = seekReadGuid ctxt.mdv (ctxt.guidsStreamPhysicalLoc + idx)
@ -2210,14 +2200,10 @@ and seekReadGenericParamsUncached ctxtH (GenericParamsIdx (numTypars, a, b)) =
let variance_flags = flags &&& 0x0003
let variance =
if variance_flags = 0x0000 then
NonVariant
elif variance_flags = 0x0001 then
CoVariant
elif variance_flags = 0x0002 then
ContraVariant
else
NonVariant
if variance_flags = 0x0000 then NonVariant
elif variance_flags = 0x0001 then CoVariant
elif variance_flags = 0x0002 then ContraVariant
else NonVariant
let constraints = seekReadGenericParamConstraints ctxt mdv numTypars gpidx
@ -2522,16 +2508,7 @@ and sigptrGetTy (ctxt: ILMetadataReader) numTypars bytes sigptr =
let struct (n, sigptr) = sigptrGetZInt32 bytes sigptr
let argTys, sigptr = sigptrFold (sigptrGetTy ctxt numTypars) n bytes sigptr
seekReadTypeDefOrRef
ctxt
numTypars
(if b0 = et_CLASS then
AsObject
else
AsValue)
argTys
tdorIdx,
sigptr
seekReadTypeDefOrRef ctxt numTypars (if b0 = et_CLASS then AsObject else AsValue) argTys tdorIdx, sigptr
elif b0 = et_CLASS then
let tdorIdx, sigptr = sigptrGetTypeDefOrRefOrSpecIdx bytes sigptr
@ -2570,10 +2547,7 @@ and sigptrGetTy (ctxt: ILMetadataReader) numTypars bytes sigptr =
Some(List.item i lobounds)
else
None),
(if i < numSized then
Some(List.item i sizes)
else
None)
(if i < numSized then Some(List.item i sizes) else None)
ILArrayShape(List.init rank dim)
@ -2591,8 +2565,7 @@ and sigptrGetTy (ctxt: ILMetadataReader) numTypars bytes sigptr =
let ccByte, sigptr = sigptrGetByte bytes sigptr
let generic, cc = byteAsCallConv ccByte
if generic then
failwith "fptr sig may not be generic"
if generic then failwith "fptr sig may not be generic"
let struct (numparams, sigptr) = sigptrGetZInt32 bytes sigptr
let retTy, sigptr = sigptrGetTy ctxt numTypars bytes sigptr
@ -2632,10 +2605,7 @@ and sigptrGetLocal (ctxt: ILMetadataReader) numTypars bytes sigptr =
let pinned, sigptr =
let b0, sigptr' = sigptrGetByte bytes sigptr
if b0 = et_PINNED then
true, sigptr'
else
false, sigptr
if b0 = et_PINNED then true, sigptr' else false, sigptr
let ty, sigptr = sigptrGetTy ctxt numTypars bytes sigptr
@ -2844,12 +2814,9 @@ and seekReadMethodDefAsMethodDataUncached ctxtH idx =
(fun i -> i, seekReadTypeDefRowWithExtents ctxt i),
(fun r -> r),
(fun (_, ((_, _, _, _, _, methodsIdx), (_, endMethodsIdx))) ->
if endMethodsIdx <= idx then
1
elif methodsIdx <= idx && idx < endMethodsIdx then
0
else
-1),
if endMethodsIdx <= idx then 1
elif methodsIdx <= idx && idx < endMethodsIdx then 0
else -1),
true,
fst
)
@ -2895,12 +2862,9 @@ and seekReadFieldDefAsFieldSpecUncached ctxtH idx =
(fun i -> i, seekReadTypeDefRowWithExtents ctxt i),
(fun r -> r),
(fun (_, ((_, _, _, _, fieldsIdx, _), (endFieldsIdx, _))) ->
if endFieldsIdx <= idx then
1
elif fieldsIdx <= idx && idx < endFieldsIdx then
0
else
-1),
if endFieldsIdx <= idx then 1
elif fieldsIdx <= idx && idx < endFieldsIdx then 0
else -1),
true,
fst
)
@ -3619,10 +3583,7 @@ and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numTypars (sz: int) start s
dprintn (
"invalid instruction: "
+ string lastb
+ (if lastb = 0xfe then
", " + string lastb2
else
"")
+ (if lastb = 0xfe then ", " + string lastb2 else "")
)
I_ret
@ -3719,8 +3680,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int
let isFatFormat = (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_FatFormat
if not isTinyFormat && not isFatFormat then
if logging then
failwith "unknown format"
if logging then failwith "unknown format"
MethodBody.Abstract
else
@ -3804,8 +3764,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int
[] (* <REVIEW> scopes fail for mscorlib </REVIEW> scopes rootScope *)
// REVIEW: look through sps to get ranges? Use GetRanges?? Change AbsIL??
(localPdbInfos, None, seqpoints)
with
| e ->
with e ->
// "* Warning: PDB info for method "+nm+" could not be read and will be ignored: "+e.Message
[], None, []
#endif
@ -3965,8 +3924,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int
nextSectionBase <- sectionBase + sectionSize
// Convert the linear code format to the nested code format
if logging then
dprintn "doing localPdbInfos2"
if logging then dprintn "doing localPdbInfos2"
let localPdbInfos2 = List.map (fun f -> f raw2nextLab) localPdbInfos
@ -3975,8 +3933,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int
let code = buildILCode nm lab2pc instrs seh localPdbInfos2
if logging then
dprintn "done checking code."
if logging then dprintn "done checking code."
{
IsZeroInit = initlocals
@ -4222,8 +4179,7 @@ let getPdbReader pdbDirPath fileName =
| _ -> failwith ("Document with URL " + url + " not found in list of documents in the PDB file")
Some(pdbr, docfun)
with
| e ->
with e ->
dprintn ("* Warning: PDB file could not be read and will be ignored: " + e.Message)
None
#endif
@ -5111,8 +5067,8 @@ let stableFileHeuristicApplies fileName =
not noStableFileHeuristic
&& try
FileSystem.IsStableFileHeuristic fileName
with
| _ -> false
with _ ->
false
let createByteFileChunk opts fileName chunk =
// If we're trying to reduce memory usage then we are willing to go back and re-read the binary, so we can use
@ -5184,8 +5140,7 @@ let OpenILModuleReader fileName opts =
ILModuleReaderCacheKey(fullPath, writeTime, opts.pdbDirPath.IsSome, opts.reduceMemoryUsage, opts.metadataOnly)
key, true
with
| exn ->
with exn ->
Debug.Assert(
false,
sprintf

Просмотреть файл

@ -646,8 +646,8 @@ let envUpdateCreatedTypeRef emEnv (tref: ILTypeRef) =
try
System.Runtime.Serialization.FormatterServices.GetUninitializedObject ty
|> ignore
with
| _ -> ()
with _ ->
()
#endif
{ emEnv with
emTypMap = Zmap.add tref (typT, typB, typeDef, Some ty) emEnv.emTypMap
@ -1101,11 +1101,7 @@ let queryableTypeGetMethod cenv emEnv parentT (mref: ILMethodRef) : MethodInfo =
let stat = mref.CallingConv.IsStatic
let cconv =
(if stat then
BindingFlags.Static
else
BindingFlags.Instance)
let cconv = (if stat then BindingFlags.Static else BindingFlags.Instance)
let methInfo =
try
@ -1117,8 +1113,8 @@ let queryableTypeGetMethod cenv emEnv parentT (mref: ILMethodRef) : MethodInfo =
(null: ParameterModifier[])
)
// This can fail if there is an ambiguity w.r.t. return type
with
| _ -> null
with _ ->
null
if (isNotNull methInfo && equalTypes resT methInfo.ReturnType) then
methInfo
@ -2568,8 +2564,7 @@ let createTypeRef (visited: Dictionary<_, _>, created: Dictionary<_, _>) emEnv t
match emEnv.emTypMap.TryFind typeRef with
| Some (_, tb, _, _) ->
if not (tb.IsCreated()) then
tb.CreateTypeAndLog() |> ignore
if not (tb.IsCreated()) then tb.CreateTypeAndLog() |> ignore
tb.Assembly
| None -> null)
@ -2595,8 +2590,7 @@ let createTypeRef (visited: Dictionary<_, _>, created: Dictionary<_, _>) emEnv t
traverseTypeRef tref
let rec buildTypeDefPass4 (visited, created) nesting emEnv (tdef: ILTypeDef) =
if verbose2 then
dprintf "buildTypeDefPass4 %s\n" tdef.Name
if verbose2 then dprintf "buildTypeDefPass4 %s\n" tdef.Name
let tref = mkRefForNestedILTypeDef ILScopeRef.Local (nesting, tdef)
createTypeRef (visited, created) emEnv tref
@ -2759,8 +2753,8 @@ let EmitDynamicAssemblyFragment
try
ignore (typB.InvokeMemberAndLog(methodName, BindingFlags.InvokeMethod ||| BindingFlags.Public ||| BindingFlags.Static, [||]))
None
with
| :? TargetInvocationException as exn -> Some exn.InnerException
with :? TargetInvocationException as exn ->
Some exn.InnerException
let emEnv, entryPts = envPopEntryPts emEnv
let execs = List.map execEntryPtFun entryPts

Просмотреть файл

@ -221,28 +221,14 @@ let toCLRKeyBlob (rsaParameters: RSAParameters) (algId: int) : byte[] =
bw.Write(int (modulusLength + BLOBHEADER_LENGTH)) // CLRHeader.KeyLength
// Write out the BLOBHEADER
bw.Write(
byte (
if isPrivate = true then
PRIVATEKEYBLOB
else
PUBLICKEYBLOB
)
) // BLOBHEADER.bType
bw.Write(byte (if isPrivate = true then PRIVATEKEYBLOB else PUBLICKEYBLOB)) // BLOBHEADER.bType
bw.Write(byte BLOBHEADER_CURRENT_BVERSION) // BLOBHEADER.bVersion
bw.Write(int16 0) // BLOBHEADER.wReserved
bw.Write(int CALG_RSA_SIGN) // BLOBHEADER.aiKeyAlg
// Write the RSAPubKey header
bw.Write(
int (
if isPrivate then
RSA_PRIV_MAGIC
else
RSA_PUB_MAGIC
)
) // RSAPubKey.magic
bw.Write(int (if isPrivate then RSA_PRIV_MAGIC else RSA_PUB_MAGIC)) // RSAPubKey.magic
bw.Write(int (modulusLength * 8)) // RSAPubKey.bitLen
@ -580,10 +566,7 @@ let legacySignerCloseKeyContainer kc =
let legacySignerSignatureSize (pk: byte[]) =
if runningOnMono then
if pk.Length > 32 then
pk.Length - 32
else
128
if pk.Length > 32 then pk.Length - 32 else 128
else
let mutable pSize = 0u
let iclrSN = getICLRStrongName ()
@ -704,8 +687,7 @@ type ILStrongNameSigner =
let pkSignatureSize pk =
try
signerSignatureSize pk
with
| exn ->
with exn ->
failwith ("A call to StrongNameSignatureSize failed (" + exn.Message + ")")
0x80

Просмотреть файл

@ -611,8 +611,7 @@ type ResFormatNode(tid: int32, nid: int32, lid: int32, dataOffset: int32, pbLink
let bNil = Bytes.zeroCreate 3
// Align remaining fields on DWORD (nb. poor bit twiddling code taken from ildasm's dres.cpp)
if (dwFiller &&& 0x1) <> 0 then
SaveChunk(bNil, 2)
if (dwFiller &&& 0x1) <> 0 then SaveChunk(bNil, 2)
//---- Constant part of the header: DWORD, WORD, WORD, DWORD, DWORD
SaveChunk(dwToBytes resHdr.DataVersion)
@ -628,8 +627,7 @@ type ResFormatNode(tid: int32, nid: int32, lid: int32, dataOffset: int32, pbLink
dwFiller <- dataEntry.Size &&& 0x3
if dwFiller <> 0 then
SaveChunk(bNil, 4 - dwFiller)
if dwFiller <> 0 then SaveChunk(bNil, 4 - dwFiller)
size
@ -1039,8 +1037,8 @@ let pdbClose (writer: PdbWriter) dllFilename pdbFilename =
FileSystem.OpenFileForWriteShim(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
false
with
| _ -> true
with _ ->
true
let mutable attempts = 0
@ -1072,8 +1070,8 @@ let internal setCheckSum (url: string, writer: ISymUnmanagedDocumentWriter) =
if (checkSum.Length = hashSizeOfMD5) then
writer.SetCheckSum(guidSourceHashMD5, hashSizeOfMD5, checkSum)
with
| _ -> ()
with _ ->
()
let pdbDefineDocument (writer: PdbWriter) (url: string) =
//3F5162F8-07C6-11D3-9053-00C04FA302A1
@ -1204,8 +1202,8 @@ let pdbReadOpen (moduleName: string) (path: string) : PdbReader =
)
{ symReader = reader :?> ISymbolReader }
with
| _ -> { symReader = null }
with _ ->
{ symReader = null }
#else
let symbolBinder = new System.Diagnostics.SymbolStore.SymBinder()

Просмотреть файл

@ -768,17 +768,16 @@ and GetTypeDescAsTypeRefIdx cenv (scoref, enc, n) =
GetTypeRefAsTypeRefIdx cenv (mkILNestedTyRef (scoref, enc, n))
and GetResolutionScopeAsElem cenv (scoref, enc) =
if isNil enc then
match List.tryFrontAndBack enc with
| None ->
match scoref with
| ILScopeRef.Local -> (rs_Module, 1)
| ILScopeRef.Assembly aref -> (rs_AssemblyRef, GetAssemblyRefAsIdx cenv aref)
| ILScopeRef.Module mref -> (rs_ModuleRef, GetModuleRefAsIdx cenv mref)
| ILScopeRef.PrimaryAssembly -> (rs_AssemblyRef, GetAssemblyRefAsIdx cenv cenv.ilg.primaryAssemblyRef)
else
let enc2, n2 = List.frontAndBack enc
| Some (enc2, n2) ->
(rs_TypeRef, GetTypeDescAsTypeRefIdx cenv (scoref, enc2, n2))
let getTypeInfoAsTypeDefOrRefEncoded cenv (scoref, enc, nm) =
if isScopeRefLocal scoref then
let idx = GetIdxForTypeDef cenv (TdKey(enc, nm))

Просмотреть файл

@ -130,10 +130,7 @@ module SequencePoint =
else
let c1 = compare sp1.Line sp2.Line
if c1 <> 0 then
c1
else
compare sp1.Column sp2.Column
if c1 <> 0 then c1 else compare sp1.Column sp2.Column
let orderByOffset sp1 sp2 = compare sp1.Offset sp2.Offset
@ -184,8 +181,8 @@ let checkSum (url: string) (checksumAlgorithm: HashAlgorithm) =
let checkSum = alg.ComputeHash file
Some(guid, checkSum)
with
| _ -> None
with _ ->
None
//---------------------------------------------------------------------
// Portable PDB Writer
@ -377,11 +374,7 @@ type PortablePdbGenerator
let s1, s2 = '/', '\\'
let separator =
if (count name s1) >= (count name s2) then
s1
else
s2
let separator = if (count name s1) >= (count name s2) then s1 else s2
let writer = BlobBuilder()
writer.WriteByte(byte separator)
@ -445,12 +438,7 @@ type PortablePdbGenerator
let documentIndex =
let mutable index = Dictionary<string, DocumentHandle>(docs.Length)
let docLength =
docs.Length
+ if String.IsNullOrEmpty sourceLink then
1
else
0
let docLength = docs.Length + if String.IsNullOrEmpty sourceLink then 1 else 0
metadata.SetCapacity(TableIndex.Document, docLength)
@ -935,14 +923,14 @@ let writePdbInfo showTimes outfile pdbfile info cvChunk =
try
FileSystem.FileDeleteShim pdbfile
with
| _ -> ()
with _ ->
()
let pdbw =
try
pdbInitialize outfile pdbfile
with
| _ -> error (Error(FSComp.SR.ilwriteErrorCreatingPdb pdbfile, rangeCmdArgs))
with _ ->
error (Error(FSComp.SR.ilwriteErrorCreatingPdb pdbfile, rangeCmdArgs))
match info.EntryPoint with
| None -> ()
@ -1020,16 +1008,14 @@ let writePdbInfo showTimes outfile pdbfile info cvChunk =
| Some p -> sco.StartOffset <> p.StartOffset || sco.EndOffset <> p.EndOffset
| None -> true
if nested then
pdbOpenScope pdbw sco.StartOffset
if nested then pdbOpenScope pdbw sco.StartOffset
sco.Locals
|> Array.iter (fun v -> pdbDefineLocalVariable pdbw v.Name v.Signature v.Index)
sco.Children |> Array.iter (writePdbScope (if nested then Some sco else parent))
if nested then
pdbCloseScope pdbw sco.EndOffset)
if nested then pdbCloseScope pdbw sco.EndOffset)
match minfo.RootScope with
| None -> ()
@ -1119,16 +1105,16 @@ let writeMdbInfo fmdb f info =
// Note, if we can't delete it code will fail later
try
FileSystem.FileDeleteShim fmdb
with
| _ -> ()
with _ ->
()
// Try loading the MDB symbol writer from an assembly available on Mono dynamically
// Report an error if the assembly is not available.
let wr =
try
createWriter f
with
| _ -> error (Error(FSComp.SR.ilwriteErrorCreatingMdb (), rangeCmdArgs))
with _ ->
error (Error(FSComp.SR.ilwriteErrorCreatingMdb (), rangeCmdArgs))
// NOTE: MonoSymbolWriter doesn't need information about entrypoints, so 'info.EntryPoint' is unused here.
// Write information about Documents. Returns '(SourceFileEntry*CompileUnitEntry)[]'

Просмотреть файл

@ -10,10 +10,7 @@ let mkLowerName (nm: string) =
// Use the lower case name of a field or constructor as the field/parameter name if it differs from the uppercase name
let lowerName = String.uncapitalize nm
if lowerName = nm then
"_" + nm
else
lowerName
if lowerName = nm then "_" + nm else lowerName
[<Sealed>]
type IlxUnionCaseField(fd: ILFieldDef) =

Просмотреть файл

@ -150,11 +150,9 @@ let mkDerefThis g m (thisv: Val) thise =
else thise
let mkCompareTestConjuncts g m exprs =
match exprs with
| [] -> mkZero g m
| [h] -> h
| l ->
let a, b = List.frontAndBack l
match List.tryFrontAndBack exprs with
| None -> mkZero g m
| Some (a,b) ->
(a, b) ||> List.foldBack (fun e acc ->
let nv, ne = mkCompGenLocal m "n" g.int_ty
mkCompGenLet m nv e
@ -167,11 +165,9 @@ let mkCompareTestConjuncts g m exprs =
acc)))
let mkEqualsTestConjuncts g m exprs =
match exprs with
| [] -> mkOne g m
| [h] -> h
| l ->
let a, b = List.frontAndBack l
match List.tryFrontAndBack exprs with
| None -> mkOne g m
| Some (a,b) ->
List.foldBack (fun e acc -> mkCond DebugPointAtBinding.NoneAtSticky m g.bool_ty e acc (mkFalse g m)) a b
let mkMinimalTy (g: TcGlobals) (tcref: TyconRef) =

Просмотреть файл

@ -5816,16 +5816,17 @@ let ApplyAssemblyLevelAutoOpenAttributeToTcEnv g amap (ccu: CcuThunk) scopem env
warning(Error(FSComp.SR.tcAttributeAutoOpenWasIgnored(p, ccu.AssemblyName), scopem))
[], env
let p = splitNamespace p
if isNil p then warn() else
let h, t = List.frontAndBack p
let modref = mkNonLocalTyconRef (mkNonLocalEntityRef ccu (Array.ofList h)) t
match modref.TryDeref with
| ValueNone -> warn()
| ValueSome _ ->
let openTarget = SynOpenDeclTarget.ModuleOrNamespace([], scopem)
let openDecl = OpenDeclaration.Create (openTarget, [modref], [], scopem, false)
let envinner = OpenModuleOrNamespaceRefs TcResultsSink.NoSink g amap scopem root env [modref] openDecl
[openDecl], envinner
match List.tryFrontAndBack p with
| None -> warn()
| Some (h, t) ->
let modref = mkNonLocalTyconRef (mkNonLocalEntityRef ccu (Array.ofList h)) t
match modref.TryDeref with
| ValueNone -> warn()
| ValueSome _ ->
let openTarget = SynOpenDeclTarget.ModuleOrNamespace([], scopem)
let openDecl = OpenDeclaration.Create (openTarget, [modref], [], scopem, false)
let envinner = OpenModuleOrNamespaceRefs TcResultsSink.NoSink g amap scopem root env [modref] openDecl
[openDecl], envinner
// Add the CCU and apply the "AutoOpen" attributes
let AddCcuToTcEnv (g, amap, scopem, env, assemblyName, ccu, autoOpens, internalsVisibleToAttributes) =

Просмотреть файл

@ -8571,10 +8571,11 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) =
let CodegenAssembly cenv eenv mgbuf implFiles =
if not (isNil implFiles) then
let a, b = List.frontAndBack implFiles
let eenv = List.fold (GenImplFile cenv mgbuf None) eenv a
let eenv = GenImplFile cenv mgbuf cenv.options.mainMethodInfo eenv b
match List.tryFrontAndBack implFiles with
| None -> ()
| Some (firstImplFiles, lastImplFile) ->
let eenv = List.fold (GenImplFile cenv mgbuf None) eenv firstImplFiles
let eenv = GenImplFile cenv mgbuf cenv.options.mainMethodInfo eenv lastImplFile
// Some constructs generate residue types and bindings. Generate these now. They don't result in any
// top-level initialization code.

Просмотреть файл

@ -8,37 +8,41 @@ open FSharp.Compiler.AbstractIL.IL
// Helpers for generating binary blobs
module BinaryGenerationUtilities =
// Little-endian encoding of int32
let b0 n = byte (n &&& 0xFF)
let b1 n = byte ((n >>> 8) &&& 0xFF)
let b2 n = byte ((n >>> 16) &&& 0xFF)
let b3 n = byte ((n >>> 24) &&& 0xFF)
let b0 n = byte (n &&& 0xFF)
let b1 n = byte ((n >>> 8) &&& 0xFF)
let b2 n = byte ((n >>> 16) &&& 0xFF)
let b3 n = byte ((n >>> 24) &&& 0xFF)
let i16 (i: int32) = [| b0 i; b1 i |]
let i32 (i: int32) = [| b0 i; b1 i; b2 i; b3 i |]
// Emit the bytes and pad to a 32-bit alignment
let Padded initialAlignment (v: byte[]) =
[| yield! v
for _ in 1..(4 - (initialAlignment + v.Length) % 4) % 4 do
yield 0x0uy |]
[|
yield! v
for _ in 1 .. (4 - (initialAlignment + v.Length) % 4) % 4 do
0x0uy
|]
// Generate nodes in a .res file format. These are then linked by Abstract IL using linkNativeResources
module ResFileFormat =
open BinaryGenerationUtilities
let ResFileNode(dwTypeID, dwNameID, wMemFlags, wLangID, data: byte[]) =
[| yield! i32 data.Length // DWORD ResHdr.dwDataSize
yield! i32 0x00000020 // dwHeaderSize
yield! i32 ((dwTypeID <<< 16) ||| 0x0000FFFF) // dwTypeID, sizeof(DWORD)
yield! i32 ((dwNameID <<< 16) ||| 0x0000FFFF) // dwNameID, sizeof(DWORD)
yield! i32 0x00000000 // DWORD dwDataVersion
yield! i16 wMemFlags // WORD wMemFlags
yield! i16 wLangID // WORD wLangID
yield! i32 0x00000000 // DWORD dwVersion
yield! i32 0x00000000 // DWORD dwCharacteristics
yield! Padded 0 data |]
let ResFileNode (dwTypeID, dwNameID, wMemFlags, wLangID, data: byte[]) =
[|
yield! i32 data.Length // DWORD ResHdr.dwDataSize
yield! i32 0x00000020 // dwHeaderSize
yield! i32 ((dwTypeID <<< 16) ||| 0x0000FFFF) // dwTypeID, sizeof(DWORD)
yield! i32 ((dwNameID <<< 16) ||| 0x0000FFFF) // dwNameID, sizeof(DWORD)
yield! i32 0x00000000 // DWORD dwDataVersion
yield! i16 wMemFlags // WORD wMemFlags
yield! i16 wLangID // WORD wLangID
yield! i32 0x00000000 // DWORD dwVersion
yield! i32 0x00000000 // DWORD dwCharacteristics
yield! Padded 0 data
|]
let ResFileHeader() = ResFileNode(0x0, 0x0, 0x0, 0x0, [| |])
let ResFileHeader () = ResFileNode(0x0, 0x0, 0x0, 0x0, [||])
// Generate the VS_VERSION_INFO structure held in a Win32 Version Resource in a PE file
//
@ -46,172 +50,191 @@ module ResFileFormat =
module VersionResourceFormat =
open BinaryGenerationUtilities
let VersionInfoNode(data: byte[]) =
[| yield! i16 (data.Length + 2) // wLength : int16 // Specifies the length, in bytes, of the VS_VERSION_INFO structure.
yield! data |]
let VersionInfoElement(wType, szKey, valueOpt: byte[] option, children: byte[][], isString) =
// for String structs, wValueLength represents the word count, not the byte count
let wValueLength = (match valueOpt with None -> 0 | Some value -> (if isString then value.Length / 2 else value.Length))
VersionInfoNode
[| yield! i16 wValueLength // wValueLength: int16. Specifies the length, in words, of the Value member.
yield! i16 wType // wType : int16 Specifies the type of data in the version resource.
yield! Padded 2 szKey
match valueOpt with
| None -> yield! []
| Some value -> yield! Padded 0 value
for child in children do
yield! child |]
let Version(version: ILVersionInfo) =
[| // DWORD dwFileVersionMS
// Specifies the most significant 32 bits of the file's binary
// version number. This member is used with dwFileVersionLS to form a 64-bit value used
// for numeric comparisons.
yield! i32 (int32 version.Major <<< 16 ||| int32 version.Minor)
// DWORD dwFileVersionLS
// Specifies the least significant 32 bits of the file's binary
// version number. This member is used with dwFileVersionMS to form a 64-bit value used
// for numeric comparisons.
yield! i32 (int32 version.Build <<< 16 ||| int32 version.Revision)
let VersionInfoNode (data: byte[]) =
[|
yield! i16 (data.Length + 2) // wLength : int16 // Specifies the length, in bytes, of the VS_VERSION_INFO structure.
yield! data
|]
let String(string, value) =
let VersionInfoElement (wType, szKey, valueOpt: byte[] option, children: byte[][], isString) =
// for String structs, wValueLength represents the word count, not the byte count
let wValueLength =
(match valueOpt with
| None -> 0
| Some value -> (if isString then value.Length / 2 else value.Length))
VersionInfoNode
[|
yield! i16 wValueLength // wValueLength: int16. Specifies the length, in words, of the Value member.
yield! i16 wType // wType : int16 Specifies the type of data in the version resource.
yield! Padded 2 szKey
match valueOpt with
| None -> yield! []
| Some value -> yield! Padded 0 value
for child in children do
yield! child
|]
let Version (version: ILVersionInfo) =
[| // DWORD dwFileVersionMS
// Specifies the most significant 32 bits of the file's binary
// version number. This member is used with dwFileVersionLS to form a 64-bit value used
// for numeric comparisons.
yield! i32 (int32 version.Major <<< 16 ||| int32 version.Minor)
// DWORD dwFileVersionLS
// Specifies the least significant 32 bits of the file's binary
// version number. This member is used with dwFileVersionMS to form a 64-bit value used
// for numeric comparisons.
yield! i32 (int32 version.Build <<< 16 ||| int32 version.Revision)
|]
let String (string, value) =
let wType = 0x1 // Specifies the type of data in the version resource.
let szKey = Bytes.stringAsUnicodeNullTerminated string
VersionInfoElement(wType, szKey, Some (Bytes.stringAsUnicodeNullTerminated value), [| |], true)
VersionInfoElement(wType, szKey, Some(Bytes.stringAsUnicodeNullTerminated value), [||], true)
let StringTable(language, strings) =
let StringTable (language, strings) =
let wType = 0x1 // Specifies the type of data in the version resource.
let szKey = Bytes.stringAsUnicodeNullTerminated language
// Specifies an 8-digit hexadecimal number stored as a Unicode string.
// Specifies an 8-digit hexadecimal number stored as a Unicode string.
let children =
[| for string in strings do
yield String string |]
[|
for string in strings do
String string
|]
VersionInfoElement(wType, szKey, None, children, false)
let StringFileInfo(stringTables: #seq<string * #seq<string * string> >) =
let StringFileInfo (stringTables: #seq<string * #seq<string * string>>) =
let wType = 0x1 // Specifies the type of data in the version resource.
let szKey = Bytes.stringAsUnicodeNullTerminated "StringFileInfo" // Contains the Unicode string StringFileInfo
// Contains an array of one or more StringTable structures.
let children =
[| for stringTable in stringTables do
yield StringTable stringTable |]
[|
for stringTable in stringTables do
StringTable stringTable
|]
VersionInfoElement(wType, szKey, None, children, false)
let VarFileInfo(vars: #seq<int32 * int32>) =
let VarFileInfo (vars: #seq<int32 * int32>) =
let wType = 0x1 // Specifies the type of data in the version resource.
let szKey = Bytes.stringAsUnicodeNullTerminated "VarFileInfo" // Contains the Unicode string StringFileInfo
// Contains an array of one or more StringTable structures.
let children =
[| for lang, codePage in vars do
let szKey = Bytes.stringAsUnicodeNullTerminated "Translation"
yield VersionInfoElement(0x0, szKey, Some([| yield! i16 lang
yield! i16 codePage |]), [| |], false) |]
[|
for lang, codePage in vars do
let szKey = Bytes.stringAsUnicodeNullTerminated "Translation"
VersionInfoElement(0x0, szKey, Some([| yield! i16 lang; yield! i16 codePage |]), [||], false)
|]
VersionInfoElement(wType, szKey, None, children, false)
let VS_FIXEDFILEINFO(fileVersion: ILVersionInfo,
productVersion: ILVersionInfo,
dwFileFlagsMask,
dwFileFlags, dwFileOS,
dwFileType, dwFileSubtype,
lwFileDate: int64) =
let VS_FIXEDFILEINFO
(
fileVersion: ILVersionInfo,
productVersion: ILVersionInfo,
dwFileFlagsMask,
dwFileFlags,
dwFileOS,
dwFileType,
dwFileSubtype,
lwFileDate: int64
) =
let dwStrucVersion = 0x00010000
[| // DWORD dwSignature // Contains the value 0xFEEFO4BD.
yield! i32 0xFEEF04BD
yield! i32 0xFEEF04BD
// DWORD dwStrucVersion // Specifies the binary version number of this structure.
yield! i32 dwStrucVersion
// DWORD dwStrucVersion // Specifies the binary version number of this structure.
yield! i32 dwStrucVersion
// DWORD dwFileVersionMS, dwFileVersionLS // Specifies the most/least significant 32 bits of the file's binary version number.
yield! Version fileVersion
// DWORD dwFileVersionMS, dwFileVersionLS // Specifies the most/least significant 32 bits of the file's binary version number.
yield! Version fileVersion
// DWORD dwProductVersionMS, dwProductVersionLS // Specifies the most/least significant 32 bits of the file's binary version number.
yield! Version productVersion
// DWORD dwProductVersionMS, dwProductVersionLS // Specifies the most/least significant 32 bits of the file's binary version number.
yield! Version productVersion
// DWORD dwFileFlagsMask // Contains a bitmask that specifies the valid bits in dwFileFlags.
yield! i32 dwFileFlagsMask
// DWORD dwFileFlagsMask // Contains a bitmask that specifies the valid bits in dwFileFlags.
yield! i32 dwFileFlagsMask
// DWORD dwFileFlags // Contains a bitmask that specifies the Boolean attributes of the file.
yield! i32 dwFileFlags
// VS_FF_DEBUG 0x1L The file contains debugging information or is compiled with debugging features enabled.
// VS_FF_INFOINFERRED The file's version structure was created dynamically; therefore, some of the members
// in this structure may be empty or incorrect. This flag should never be set in a file's
// VS_VERSION_INFO data.
// VS_FF_PATCHED The file has been modified and is not identical to the original shipping file of
// the same version number.
// VS_FF_PRERELEASE The file is a development version, not a commercially released product.
// VS_FF_PRIVATEBUILD The file was not built using standard release procedures. If this flag is
// set, the StringFileInfo structure should contain a PrivateBuild entry.
// VS_FF_SPECIALBUILD The file was built by the original company using standard release procedures
// but is a variation of the normal file of the same version number. If this
// flag is set, the StringFileInfo structure should contain a SpecialBuild entry.
// DWORD dwFileFlags // Contains a bitmask that specifies the Boolean attributes of the file.
yield! i32 dwFileFlags
// VS_FF_DEBUG 0x1L The file contains debugging information or is compiled with debugging features enabled.
// VS_FF_INFOINFERRED The file's version structure was created dynamically; therefore, some of the members
// in this structure may be empty or incorrect. This flag should never be set in a file's
// VS_VERSION_INFO data.
// VS_FF_PATCHED The file has been modified and is not identical to the original shipping file of
// the same version number.
// VS_FF_PRERELEASE The file is a development version, not a commercially released product.
// VS_FF_PRIVATEBUILD The file was not built using standard release procedures. If this flag is
// set, the StringFileInfo structure should contain a PrivateBuild entry.
// VS_FF_SPECIALBUILD The file was built by the original company using standard release procedures
// but is a variation of the normal file of the same version number. If this
// flag is set, the StringFileInfo structure should contain a SpecialBuild entry.
//Specifies the operating system for which this file was designed. This member can be one of the following values: Flag
yield! i32 dwFileOS
//VOS_DOS 0x0001L The file was designed for MS-DOS.
//VOS_NT 0x0004L The file was designed for Windows NT.
//VOS__WINDOWS16 The file was designed for 16-bit Windows.
//VOS__WINDOWS32 The file was designed for the Win32 API.
//VOS_OS216 0x00020000L The file was designed for 16-bit OS/2.
//VOS_OS232 0x00030000L The file was designed for 32-bit OS/2.
//VOS__PM16 The file was designed for 16-bit Presentation Manager.
//VOS__PM32 The file was designed for 32-bit Presentation Manager.
//VOS_UNKNOWN The operating system for which the file was designed is unknown to Windows.
//Specifies the operating system for which this file was designed. This member can be one of the following values: Flag
yield! i32 dwFileOS
//VOS_DOS 0x0001L The file was designed for MS-DOS.
//VOS_NT 0x0004L The file was designed for Windows NT.
//VOS__WINDOWS16 The file was designed for 16-bit Windows.
//VOS__WINDOWS32 The file was designed for the Win32 API.
//VOS_OS216 0x00020000L The file was designed for 16-bit OS/2.
//VOS_OS232 0x00030000L The file was designed for 32-bit OS/2.
//VOS__PM16 The file was designed for 16-bit Presentation Manager.
//VOS__PM32 The file was designed for 32-bit Presentation Manager.
//VOS_UNKNOWN The operating system for which the file was designed is unknown to Windows.
// Specifies the general type of file. This member can be one of the following values:
yield! i32 dwFileType
// Specifies the general type of file. This member can be one of the following values:
yield! i32 dwFileType
//VFT_UNKNOWN The file type is unknown to Windows.
//VFT_APP The file contains an application.
//VFT_DLL The file contains a dynamic-link library (DLL).
//VFT_DRV The file contains a device driver. If dwFileType is VFT_DRV, dwFileSubtype contains a more specific description of the driver.
//VFT_FONT The file contains a font. If dwFileType is VFT_FONT, dwFileSubtype contains a more specific description of the font file.
//VFT_VXD The file contains a virtual device.
//VFT_STATIC_LIB The file contains a static-link library.
//VFT_UNKNOWN The file type is unknown to Windows.
//VFT_APP The file contains an application.
//VFT_DLL The file contains a dynamic-link library (DLL).
//VFT_DRV The file contains a device driver. If dwFileType is VFT_DRV, dwFileSubtype contains a more specific description of the driver.
//VFT_FONT The file contains a font. If dwFileType is VFT_FONT, dwFileSubtype contains a more specific description of the font file.
//VFT_VXD The file contains a virtual device.
//VFT_STATIC_LIB The file contains a static-link library.
// Specifies the function of the file. The possible values depend on the value of
// dwFileType. For all values of dwFileType not described in the following list,
// dwFileSubtype is zero. If dwFileType is VFT_DRV, dwFileSubtype can be one of the following values:
yield! i32 dwFileSubtype
//VFT2_UNKNOWN The driver type is unknown by Windows.
//VFT2_DRV_COMM The file contains a communications driver.
//VFT2_DRV_PRINTER The file contains a printer driver.
//VFT2_DRV_KEYBOARD The file contains a keyboard driver.
//VFT2_DRV_LANGUAGE The file contains a language driver.
//VFT2_DRV_DISPLAY The file contains a display driver.
//VFT2_DRV_MOUSE The file contains a mouse driver.
//VFT2_DRV_NETWORK The file contains a network driver.
//VFT2_DRV_SYSTEM The file contains a system driver.
//VFT2_DRV_INSTALLABLE The file contains an installable driver.
//VFT2_DRV_SOUND The file contains a sound driver.
//
//If dwFileType is VFT_FONT, dwFileSubtype can be one of the following values:
//
//VFT2_UNKNOWN The font type is unknown by Windows.
//VFT2_FONT_RASTER The file contains a raster font.
//VFT2_FONT_VECTOR The file contains a vector font.
//VFT2_FONT_TRUETYPE The file contains a TrueType font.
//
//If dwFileType is VFT_VXD, dwFileSubtype contains the virtual device identifier included in the virtual device control block.
// Specifies the function of the file. The possible values depend on the value of
// dwFileType. For all values of dwFileType not described in the following list,
// dwFileSubtype is zero. If dwFileType is VFT_DRV, dwFileSubtype can be one of the following values:
yield! i32 dwFileSubtype
//VFT2_UNKNOWN The driver type is unknown by Windows.
//VFT2_DRV_COMM The file contains a communications driver.
//VFT2_DRV_PRINTER The file contains a printer driver.
//VFT2_DRV_KEYBOARD The file contains a keyboard driver.
//VFT2_DRV_LANGUAGE The file contains a language driver.
//VFT2_DRV_DISPLAY The file contains a display driver.
//VFT2_DRV_MOUSE The file contains a mouse driver.
//VFT2_DRV_NETWORK The file contains a network driver.
//VFT2_DRV_SYSTEM The file contains a system driver.
//VFT2_DRV_INSTALLABLE The file contains an installable driver.
//VFT2_DRV_SOUND The file contains a sound driver.
//
//If dwFileType is VFT_FONT, dwFileSubtype can be one of the following values:
//
//VFT2_UNKNOWN The font type is unknown by Windows.
//VFT2_FONT_RASTER The file contains a raster font.
//VFT2_FONT_VECTOR The file contains a vector font.
//VFT2_FONT_TRUETYPE The file contains a TrueType font.
//
//If dwFileType is VFT_VXD, dwFileSubtype contains the virtual device identifier included in the virtual device control block.
// Specifies the most significant 32 bits of the file's 64-bit binary creation date and time stamp.
yield! i32 (int32 (lwFileDate >>> 32))
// Specifies the most significant 32 bits of the file's 64-bit binary creation date and time stamp.
yield! i32 (int32 (lwFileDate >>> 32))
//Specifies the least significant 32 bits of the file's 64-bit binary creation date and time stamp.
yield! i32 (int32 lwFileDate)
|]
//Specifies the least significant 32 bits of the file's 64-bit binary creation date and time stamp.
yield! i32 (int32 lwFileDate)
|]
let VS_VERSION_INFO(fixedFileInfo, stringFileInfo, varFileInfo) =
let VS_VERSION_INFO (fixedFileInfo, stringFileInfo, varFileInfo) =
let wType = 0x0
let szKey = Bytes.stringAsUnicodeNullTerminated "VS_VERSION_INFO" // Contains the Unicode string VS_VERSION_INFO
let value = VS_FIXEDFILEINFO fixedFileInfo
let children =
[| yield StringFileInfo stringFileInfo
yield VarFileInfo varFileInfo
|]
let children = [| StringFileInfo stringFileInfo; VarFileInfo varFileInfo |]
VersionInfoElement(wType, szKey, Some value, children, false)
let VS_VERSION_INFO_RESOURCE data =
@ -223,7 +246,7 @@ module VersionResourceFormat =
module ManifestResourceFormat =
let VS_MANIFEST_RESOURCE(data, isLibrary) =
let VS_MANIFEST_RESOURCE (data, isLibrary) =
let dwTypeID = 0x0018
let dwNameID = if isLibrary then 0x2 else 0x1
let wMemFlags = 0x0

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -99,7 +99,7 @@ and IProjectReference =
abstract TryGetLogicalTimeStamp: cache: TimeStampCache -> DateTime option
type AssemblyReference =
| AssemblyReference of range * string * IProjectReference option
| AssemblyReference of range: range * text: string * projectReference: IProjectReference option
member Range: range
@ -854,6 +854,4 @@ val FSharpScriptFileSuffixes: string list
/// File suffixes where #light is the default
val FSharpIndentationAwareSyntaxFileSuffixes: string list
val doNotRequireNamespaceOrModuleSuffixes: string list
val mlCompatSuffixes: string list
val FSharpMLCompatFileSuffixes: string list

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -31,31 +31,32 @@ module AttributeHelpers =
/// Try to find an attribute that takes a string argument
let TryFindStringAttribute (g: TcGlobals) attrib attribs =
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib(_, _, [ AttribStringArg s ], _, _, _, _)) -> Some s
| _ -> None
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib (_, _, [ AttribStringArg s ], _, _, _, _)) -> Some s
| _ -> None
let TryFindIntAttribute (g: TcGlobals) attrib attribs =
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib(_, _, [ AttribInt32Arg i ], _, _, _, _)) -> Some i
| _ -> None
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib (_, _, [ AttribInt32Arg i ], _, _, _, _)) -> Some i
| _ -> None
let TryFindBoolAttribute (g: TcGlobals) attrib attribs =
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib(_, _, [ AttribBoolArg p ], _, _, _, _)) -> Some p
| _ -> None
match g.TryFindSysAttrib attrib with
| None -> None
| Some attribRef ->
match TryFindFSharpAttribute g attribRef attribs with
| Some (Attrib (_, _, [ AttribBoolArg p ], _, _, _, _)) -> Some p
| _ -> None
let (|ILVersion|_|) (versionString: string) =
try Some (parseILVersion versionString)
try
Some(parseILVersion versionString)
with e ->
None
@ -67,20 +68,25 @@ module AttributeHelpers =
type StrongNameSigningInfo = StrongNameSigningInfo of delaysign: bool * publicsign: bool * signer: string option * container: string option
/// Validate the attributes and configuration settings used to perform strong-name signing
let ValidateKeySigningAttributes (tcConfig : TcConfig, tcGlobals, topAttrs) =
let delaySignAttrib = AttributeHelpers.TryFindBoolAttribute tcGlobals "System.Reflection.AssemblyDelaySignAttribute" topAttrs.assemblyAttrs
let signerAttrib = AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyKeyFileAttribute" topAttrs.assemblyAttrs
let containerAttrib = AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyKeyNameAttribute" topAttrs.assemblyAttrs
let ValidateKeySigningAttributes (tcConfig: TcConfig, tcGlobals, topAttrs) =
let delaySignAttrib =
AttributeHelpers.TryFindBoolAttribute tcGlobals "System.Reflection.AssemblyDelaySignAttribute" topAttrs.assemblyAttrs
let signerAttrib =
AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyKeyFileAttribute" topAttrs.assemblyAttrs
let containerAttrib =
AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyKeyNameAttribute" topAttrs.assemblyAttrs
// if delaySign is set via an attribute, validate that it wasn't set via an option
let delaysign =
match delaySignAttrib with
| Some delaysign ->
if tcConfig.delaysign then
warning(Error(FSComp.SR.fscDelaySignWarning(), rangeCmdArgs))
tcConfig.delaysign
else
delaysign
if tcConfig.delaysign then
warning (Error(FSComp.SR.fscDelaySignWarning (), rangeCmdArgs))
tcConfig.delaysign
else
delaysign
| _ -> tcConfig.delaysign
// if signer is set via an attribute, validate that it wasn't set via an option
@ -88,7 +94,7 @@ let ValidateKeySigningAttributes (tcConfig : TcConfig, tcGlobals, topAttrs) =
match signerAttrib with
| Some signer ->
if tcConfig.signer.IsSome && tcConfig.signer <> Some signer then
warning(Error(FSComp.SR.fscKeyFileWarning(), rangeCmdArgs))
warning (Error(FSComp.SR.fscKeyFileWarning (), rangeCmdArgs))
tcConfig.signer
else
Some signer
@ -101,35 +107,35 @@ let ValidateKeySigningAttributes (tcConfig : TcConfig, tcGlobals, topAttrs) =
match containerAttrib with
| Some container ->
if not FSharpEnvironment.isRunningOnCoreClr then
warning(Error(FSComp.SR.containerDeprecated(), rangeCmdArgs))
warning (Error(FSComp.SR.containerDeprecated (), rangeCmdArgs))
if tcConfig.container.IsSome && tcConfig.container <> Some container then
warning(Error(FSComp.SR.fscKeyNameWarning(), rangeCmdArgs))
tcConfig.container
warning (Error(FSComp.SR.fscKeyNameWarning (), rangeCmdArgs))
tcConfig.container
else
Some container
Some container
| None -> tcConfig.container
StrongNameSigningInfo (delaysign, tcConfig.publicsign, signer, container)
StrongNameSigningInfo(delaysign, tcConfig.publicsign, signer, container)
/// Get the object used to perform strong-name signing
let GetStrongNameSigner signingInfo =
let (StrongNameSigningInfo(delaysign, publicsign, signer, container)) = signingInfo
let (StrongNameSigningInfo (delaysign, publicsign, signer, container)) = signingInfo
// REVIEW: favor the container over the key file - C# appears to do this
match container with
| Some container ->
Some (ILStrongNameSigner.OpenKeyContainer container)
| Some container -> Some(ILStrongNameSigner.OpenKeyContainer container)
| None ->
match signer with
| None -> None
| Some s ->
try
if publicsign || delaysign then
Some (ILStrongNameSigner.OpenPublicKeyOptions s publicsign)
Some(ILStrongNameSigner.OpenPublicKeyOptions s publicsign)
else
Some (ILStrongNameSigner.OpenKeyPairFile s)
Some(ILStrongNameSigner.OpenKeyPairFile s)
with _ ->
// Note :: don't use errorR here since we really want to fail and not produce a binary
error(Error(FSComp.SR.fscKeyFileCouldNotBeOpened s, rangeCmdArgs))
error (Error(FSComp.SR.fscKeyFileCouldNotBeOpened s, rangeCmdArgs))
//----------------------------------------------------------------------------
// Building the contents of the finalized IL module
@ -138,65 +144,87 @@ let GetStrongNameSigner signingInfo =
module MainModuleBuilder =
let injectedCompatTypes =
set [ "System.Tuple`1"
"System.Tuple`2"
"System.Tuple`3"
"System.Tuple`4"
"System.Tuple`5"
"System.Tuple`6"
"System.Tuple`7"
"System.Tuple`8"
"System.ITuple"
"System.Tuple"
"System.Collections.IStructuralComparable"
"System.Collections.IStructuralEquatable" ]
set
[
"System.Tuple`1"
"System.Tuple`2"
"System.Tuple`3"
"System.Tuple`4"
"System.Tuple`5"
"System.Tuple`6"
"System.Tuple`7"
"System.Tuple`8"
"System.ITuple"
"System.Tuple"
"System.Collections.IStructuralComparable"
"System.Collections.IStructuralEquatable"
]
let typesForwardedToMscorlib =
set [ "System.AggregateException"
"System.Threading.CancellationTokenRegistration"
"System.Threading.CancellationToken"
"System.Threading.CancellationTokenSource"
"System.Lazy`1"
"System.IObservable`1"
"System.IObserver`1" ]
set
[
"System.AggregateException"
"System.Threading.CancellationTokenRegistration"
"System.Threading.CancellationToken"
"System.Threading.CancellationTokenSource"
"System.Lazy`1"
"System.IObservable`1"
"System.IObserver`1"
]
let typesForwardedToSystemNumerics =
set [ "System.Numerics.BigInteger" ]
let typesForwardedToSystemNumerics = set [ "System.Numerics.BigInteger" ]
let createMscorlibExportList (tcGlobals: TcGlobals) =
// We want to write forwarders out for all injected types except for System.ITuple, which is internal
// Forwarding System.ITuple will cause FxCop failures on 4.0
Set.union (Set.filter (fun t -> t <> "System.ITuple") injectedCompatTypes) typesForwardedToMscorlib |>
Seq.map (fun t -> mkTypeForwarder tcGlobals.ilg.primaryAssemblyScopeRef t (mkILNestedExportedTypes List.empty<ILNestedExportedType>) (mkILCustomAttrs List.empty<ILAttribute>) ILTypeDefAccess.Public )
|> Seq.toList
// We want to write forwarders out for all injected types except for System.ITuple, which is internal
// Forwarding System.ITuple will cause FxCop failures on 4.0
Set.union (Set.filter (fun t -> t <> "System.ITuple") injectedCompatTypes) typesForwardedToMscorlib
|> Seq.map (fun t ->
mkTypeForwarder
tcGlobals.ilg.primaryAssemblyScopeRef
t
(mkILNestedExportedTypes List.empty<ILNestedExportedType>)
(mkILCustomAttrs List.empty<ILAttribute>)
ILTypeDefAccess.Public)
|> Seq.toList
let createSystemNumericsExportList (tcConfig: TcConfig) (tcImports: TcImports) =
let refNumericsDllName =
if (tcConfig.primaryAssembly.Name = "mscorlib") then "System.Numerics"
else "System.Runtime.Numerics"
if (tcConfig.primaryAssembly.Name = "mscorlib") then
"System.Numerics"
else
"System.Runtime.Numerics"
let numericsAssemblyRef =
match tcImports.GetImportedAssemblies() |> List.tryFind<ImportedAssembly>(fun a -> a.FSharpViewOfMetadata.AssemblyName = refNumericsDllName) with
match tcImports.GetImportedAssemblies()
|> List.tryFind<ImportedAssembly> (fun a -> a.FSharpViewOfMetadata.AssemblyName = refNumericsDllName)
with
| Some asm ->
match asm.ILScopeRef with
| ILScopeRef.Assembly aref -> Some aref
| _ -> None
| None -> None
match numericsAssemblyRef with
| Some aref ->
let systemNumericsAssemblyRef = ILAssemblyRef.Create(refNumericsDllName, aref.Hash, aref.PublicKey, aref.Retargetable, aref.Version, aref.Locale)
typesForwardedToSystemNumerics |>
Seq.map (fun t ->
{ ScopeRef = ILScopeRef.Assembly systemNumericsAssemblyRef
Name = t
Attributes = enum<TypeAttributes>(0x00200000) ||| TypeAttributes.Public
Nested = mkILNestedExportedTypes []
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx }) |>
Seq.toList
let systemNumericsAssemblyRef =
ILAssemblyRef.Create(refNumericsDllName, aref.Hash, aref.PublicKey, aref.Retargetable, aref.Version, aref.Locale)
typesForwardedToSystemNumerics
|> Seq.map (fun t ->
{
ScopeRef = ILScopeRef.Assembly systemNumericsAssemblyRef
Name = t
Attributes = enum<TypeAttributes> (0x00200000) ||| TypeAttributes.Public
Nested = mkILNestedExportedTypes []
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx
})
|> Seq.toList
| None -> []
let ComputeILFileVersion findStringAttr (assemblyVersion: ILVersionInfo) =
let attrName = "System.Reflection.AssemblyFileVersionAttribute"
match findStringAttr attrName with
| None -> assemblyVersion
| Some (AttributeHelpers.ILVersion v) -> v
@ -206,69 +234,108 @@ module MainModuleBuilder =
let ComputeProductVersion findStringAttr (fileVersion: ILVersionInfo) =
let attrName = "System.Reflection.AssemblyInformationalVersionAttribute"
let toDotted (version: ILVersionInfo) = sprintf "%d.%d.%d.%d" version.Major version.Minor version.Build version.Revision
let toDotted (version: ILVersionInfo) =
sprintf "%d.%d.%d.%d" version.Major version.Minor version.Build version.Revision
match findStringAttr attrName with
| None | Some "" -> fileVersion |> toDotted
| None
| Some "" -> fileVersion |> toDotted
| Some (AttributeHelpers.ILVersion v) -> v |> toDotted
| Some v ->
// Warning will be reported by CheckExpressions.fs
v
let ConvertProductVersionToILVersionInfo (version: string) : ILVersionInfo =
let parseOrZero i (v:string) =
let parseOrZero i (v: string) =
let v =
// When i = 3 then this is the 4th part of the version. The last part of the version can be trailed by any characters so we trim them off
if i <> 3 then
v
else
((false, ""), v)
||> Seq.fold(fun (finished, v) c ->
||> Seq.fold (fun (finished, v) c ->
match finished with
| false when Char.IsDigit(c) -> false, v + c.ToString()
| _ -> true, v)
|> snd
match UInt16.TryParse v with
| true, i -> i
| false, _ -> 0us
let validParts =
version.Split('.')
|> Array.mapi(fun i v -> parseOrZero i v)
|> Seq.toList
match validParts @ [0us; 0us; 0us; 0us] with
version.Split('.') |> Array.mapi (fun i v -> parseOrZero i v) |> Seq.toList
match validParts @ [ 0us; 0us; 0us; 0us ] with
| major :: minor :: build :: rev :: _ -> ILVersionInfo(major, minor, build, rev)
| x -> failwithf "error converting product version '%s' to binary, tried '%A' " version x
let CreateMainModule
(ctok, tcConfig: TcConfig, tcGlobals, tcImports: TcImports,
pdbfile, assemblyName, outfile, topAttrs,
sigDataAttributes: ILAttribute list, sigDataResources: ILResource list, optDataResources: ILResource list,
codegenResults, assemVerFromAttrib, metadataVersion, secDecls) =
(
ctok,
tcConfig: TcConfig,
tcGlobals,
tcImports: TcImports,
pdbfile,
assemblyName,
outfile,
topAttrs,
sigDataAttributes: ILAttribute list,
sigDataResources: ILResource list,
optDataResources: ILResource list,
codegenResults,
assemVerFromAttrib,
metadataVersion,
secDecls
) =
RequireCompilationThread ctok
let ilTypeDefs =
//let topTypeDef = mkILTypeDefForGlobalFunctions tcGlobals.ilg (mkILMethods [], emptyILFields)
mkILTypeDefs codegenResults.ilTypeDefs
let mainModule =
let hashAlg = AttributeHelpers.TryFindIntAttribute tcGlobals "System.Reflection.AssemblyAlgorithmIdAttribute" topAttrs.assemblyAttrs
let locale = AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyCultureAttribute" topAttrs.assemblyAttrs
let flags = match AttributeHelpers.TryFindIntAttribute tcGlobals "System.Reflection.AssemblyFlagsAttribute" topAttrs.assemblyAttrs with | Some f -> f | _ -> 0x0
let hashAlg =
AttributeHelpers.TryFindIntAttribute tcGlobals "System.Reflection.AssemblyAlgorithmIdAttribute" topAttrs.assemblyAttrs
let locale =
AttributeHelpers.TryFindStringAttribute tcGlobals "System.Reflection.AssemblyCultureAttribute" topAttrs.assemblyAttrs
let flags =
match AttributeHelpers.TryFindIntAttribute tcGlobals "System.Reflection.AssemblyFlagsAttribute" topAttrs.assemblyAttrs with
| Some f -> f
| _ -> 0x0
// You're only allowed to set a locale if the assembly is a library
if (locale <> None && locale.Value <> "") && tcConfig.target <> CompilerTarget.Dll then
error(Error(FSComp.SR.fscAssemblyCultureAttributeError(), rangeCmdArgs))
error (Error(FSComp.SR.fscAssemblyCultureAttributeError (), rangeCmdArgs))
// Add the type forwarders to any .NET DLL post-.NET-2.0, to give binary compatibility
let exportedTypesList =
if tcConfig.compilingFSharpCore then
List.append (createMscorlibExportList tcGlobals) (createSystemNumericsExportList tcConfig tcImports)
List.append (createMscorlibExportList tcGlobals) (createSystemNumericsExportList tcConfig tcImports)
else
[]
let ilModuleName = GetGeneratedILModuleName tcConfig.target assemblyName
let isDLL = (tcConfig.target = CompilerTarget.Dll || tcConfig.target = CompilerTarget.Module)
mkILSimpleModule assemblyName ilModuleName isDLL tcConfig.subsystemVersion tcConfig.useHighEntropyVA ilTypeDefs hashAlg locale flags (mkILExportedTypes exportedTypesList) metadataVersion
let isDLL =
(tcConfig.target = CompilerTarget.Dll || tcConfig.target = CompilerTarget.Module)
mkILSimpleModule
assemblyName
ilModuleName
isDLL
tcConfig.subsystemVersion
tcConfig.useHighEntropyVA
ilTypeDefs
hashAlg
locale
flags
(mkILExportedTypes exportedTypesList)
metadataVersion
let disableJitOptimizations = not tcConfig.optSettings.JitOptimizationsEnabled
@ -277,74 +344,130 @@ module MainModuleBuilder =
let reflectedDefinitionAttrs, reflectedDefinitionResources =
codegenResults.quotationResourceInfo
|> List.map (fun (referencedTypeDefs, reflectedDefinitionBytes) ->
let reflectedDefinitionResourceName = QuotationPickler.SerializedReflectedDefinitionsResourceNameBase+"-"+assemblyName+"-"+string(newUnique())+"-"+string(hash reflectedDefinitionBytes)
let reflectedDefinitionResourceName =
QuotationPickler.SerializedReflectedDefinitionsResourceNameBase
+ "-"
+ assemblyName
+ "-"
+ string (newUnique ())
+ "-"
+ string (hash reflectedDefinitionBytes)
let reflectedDefinitionAttrs =
let qf = QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat tcGlobals
let qf =
QuotationTranslator.QuotationGenerationScope.ComputeQuotationFormat tcGlobals
if qf.SupportsDeserializeEx then
[ mkCompilationMappingAttrForQuotationResource tcGlobals (reflectedDefinitionResourceName, referencedTypeDefs) ]
[
mkCompilationMappingAttrForQuotationResource tcGlobals (reflectedDefinitionResourceName, referencedTypeDefs)
]
else
[ ]
[]
let reflectedDefinitionResource =
{ Name=reflectedDefinitionResourceName
Location = ILResourceLocation.Local(ByteStorage.FromByteArray(reflectedDefinitionBytes))
Access= ILResourceAccess.Public
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx }
{
Name = reflectedDefinitionResourceName
Location = ILResourceLocation.Local(ByteStorage.FromByteArray(reflectedDefinitionBytes))
Access = ILResourceAccess.Public
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx
}
reflectedDefinitionAttrs, reflectedDefinitionResource)
|> List.unzip
|> (fun (attrs, resource) -> List.concat attrs, resource)
let manifestAttrs =
mkILCustomAttrs
[ if not tcConfig.internConstantStrings then
yield mkILCustomAttribute (tcGlobals.FindSysILTypeRef "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", [tcGlobals.ilg.typ_Int32], [ILAttribElem.Int32( 8)], [])
yield! sigDataAttributes
yield! codegenResults.ilAssemAttrs
[
if not tcConfig.internConstantStrings then
mkILCustomAttribute (
tcGlobals.FindSysILTypeRef "System.Runtime.CompilerServices.CompilationRelaxationsAttribute",
[ tcGlobals.ilg.typ_Int32 ],
[ ILAttribElem.Int32(8) ],
[]
)
yield! sigDataAttributes
yield! codegenResults.ilAssemAttrs
if Option.isSome pdbfile then
yield (tcGlobals.mkDebuggableAttributeV2 (tcConfig.jitTracking, tcConfig.ignoreSymbolStoreSequencePoints, disableJitOptimizations, false (* enableEnC *) ))
yield! reflectedDefinitionAttrs ]
if Option.isSome pdbfile then
tcGlobals.mkDebuggableAttributeV2 (
tcConfig.jitTracking,
tcConfig.ignoreSymbolStoreSequencePoints,
disableJitOptimizations,
false (* enableEnC *)
)
yield! reflectedDefinitionAttrs
]
// Make the manifest of the assembly
let manifest =
if tcConfig.target = CompilerTarget.Module then None else
let man = mainModule.ManifestOfAssembly
let ver =
match assemVerFromAttrib with
| None -> tcVersion
| Some v -> v
Some { man with Version= Some ver
CustomAttrsStored = storeILCustomAttrs manifestAttrs
DisableJitOptimizations=disableJitOptimizations
JitTracking= tcConfig.jitTracking
IgnoreSymbolStoreSequencePoints = tcConfig.ignoreSymbolStoreSequencePoints
SecurityDeclsStored=storeILSecurityDecls secDecls }
if tcConfig.target = CompilerTarget.Module then
None
else
let man = mainModule.ManifestOfAssembly
let ver =
match assemVerFromAttrib with
| None -> tcVersion
| Some v -> v
Some
{ man with
Version = Some ver
CustomAttrsStored = storeILCustomAttrs manifestAttrs
DisableJitOptimizations = disableJitOptimizations
JitTracking = tcConfig.jitTracking
IgnoreSymbolStoreSequencePoints = tcConfig.ignoreSymbolStoreSequencePoints
SecurityDeclsStored = storeILSecurityDecls secDecls
}
let resources =
mkILResources
[ for file in tcConfig.embedResources do
let name, bytes, pub =
let file, name, pub = TcConfigBuilder.SplitCommandLineResourceInfo file
let file = tcConfig.ResolveSourceFile(rangeStartup, file, tcConfig.implicitIncludeDir)
let bytes = FileSystem.OpenFileForReadShim(file).ReadAllBytes()
name, bytes, pub
yield { Name=name
// TODO: We probably can directly convert ByteMemory to ByteStorage, without reading all bytes.
Location=ILResourceLocation.Local(ByteStorage.FromByteArray(bytes))
Access=pub
CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx }
mkILResources
[
for file in tcConfig.embedResources do
let name, bytes, pub =
let file, name, pub = TcConfigBuilder.SplitCommandLineResourceInfo file
yield! reflectedDefinitionResources
yield! sigDataResources
yield! optDataResources
for ri in tcConfig.linkResources do
let file, name, pub = TcConfigBuilder.SplitCommandLineResourceInfo ri
yield { Name=name
Location=ILResourceLocation.File(ILModuleRef.Create(name=file, hasMetadata=false, hash=Some (sha1HashBytes (FileSystem.OpenFileForReadShim(file).ReadAllBytes()))), 0)
Access=pub
CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx } ]
let file =
tcConfig.ResolveSourceFile(rangeStartup, file, tcConfig.implicitIncludeDir)
let bytes = FileSystem.OpenFileForReadShim(file).ReadAllBytes()
name, bytes, pub
{
Name = name
// TODO: We probably can directly convert ByteMemory to ByteStorage, without reading all bytes.
Location = ILResourceLocation.Local(ByteStorage.FromByteArray(bytes))
Access = pub
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx
}
yield! reflectedDefinitionResources
yield! sigDataResources
yield! optDataResources
for ri in tcConfig.linkResources do
let file, name, pub = TcConfigBuilder.SplitCommandLineResourceInfo ri
let location =
ILResourceLocation.File(
ILModuleRef.Create(
name = file,
hasMetadata = false,
hash = Some(sha1HashBytes (FileSystem.OpenFileForReadShim(file).ReadAllBytes()))
),
0
)
{
Name = name
Location = location
Access = pub
CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs
MetadataIndex = NoMetadataIdx
}
]
let assemblyVersion =
match tcConfig.version with
@ -362,7 +485,7 @@ module MainModuleBuilder =
| Some assemblyVersion ->
let FindAttribute key attrib =
match findAttribute attrib with
| Some text -> [(key, text)]
| Some text -> [ (key, text) ]
| _ -> []
let fileVersionInfo = ComputeILFileVersion findAttribute assemblyVersion
@ -370,26 +493,33 @@ module MainModuleBuilder =
let productVersionString = ComputeProductVersion findAttribute fileVersionInfo
let stringFileInfo =
// 000004b0:
// Specifies an 8-digit hexadecimal number stored as a Unicode string. The
// four most significant digits represent the language identifier. The four least
// significant digits represent the code page for which the data is formatted.
// Each Microsoft Standard Language identifier contains two parts: the low-order 10 bits
// specify the major language, and the high-order 6 bits specify the sublanguage.
// For a table of valid identifiers see Language Identifiers. //
// see e.g. http://msdn.microsoft.com/en-us/library/aa912040.aspx 0000 is neutral and 04b0(hex)=1252(dec) is the code page.
[ ("000004b0", [ yield ("Assembly Version", (sprintf "%d.%d.%d.%d" assemblyVersion.Major assemblyVersion.Minor assemblyVersion.Build assemblyVersion.Revision))
yield ("FileVersion", (sprintf "%d.%d.%d.%d" fileVersionInfo.Major fileVersionInfo.Minor fileVersionInfo.Build fileVersionInfo.Revision))
yield ("ProductVersion", productVersionString)
match tcConfig.outputFile with
| Some f -> yield ("OriginalFilename", Path.GetFileName f)
| None -> ()
yield! FindAttribute "Comments" "System.Reflection.AssemblyDescriptionAttribute"
yield! FindAttribute "FileDescription" "System.Reflection.AssemblyTitleAttribute"
yield! FindAttribute "ProductName" "System.Reflection.AssemblyProductAttribute"
yield! FindAttribute "CompanyName" "System.Reflection.AssemblyCompanyAttribute"
yield! FindAttribute "LegalCopyright" "System.Reflection.AssemblyCopyrightAttribute"
yield! FindAttribute "LegalTrademarks" "System.Reflection.AssemblyTrademarkAttribute" ]) ]
// 000004b0:
// Specifies an 8-digit hexadecimal number stored as a Unicode string. The
// four most significant digits represent the language identifier. The four least
// significant digits represent the code page for which the data is formatted.
// Each Microsoft Standard Language identifier contains two parts: the low-order 10 bits
// specify the major language, and the high-order 6 bits specify the sublanguage.
// For a table of valid identifiers see Language Identifiers. //
// see e.g. http://msdn.microsoft.com/en-us/library/aa912040.aspx 0000 is neutral and 04b0(hex)=1252(dec) is the code page.
[
("000004b0",
[
("Assembly Version",
$"%d{assemblyVersion.Major}.%d{assemblyVersion.Minor}.%d{assemblyVersion.Build}.%d{assemblyVersion.Revision}")
("FileVersion",
$"%d{fileVersionInfo.Major}.%d{fileVersionInfo.Minor}.%d{fileVersionInfo.Build}.%d{fileVersionInfo.Revision}")
("ProductVersion", productVersionString)
match tcConfig.outputFile with
| Some f -> ("OriginalFilename", Path.GetFileName f)
| None -> ()
yield! FindAttribute "Comments" "System.Reflection.AssemblyDescriptionAttribute"
yield! FindAttribute "FileDescription" "System.Reflection.AssemblyTitleAttribute"
yield! FindAttribute "ProductName" "System.Reflection.AssemblyProductAttribute"
yield! FindAttribute "CompanyName" "System.Reflection.AssemblyCompanyAttribute"
yield! FindAttribute "LegalCopyright" "System.Reflection.AssemblyCopyrightAttribute"
yield! FindAttribute "LegalTrademarks" "System.Reflection.AssemblyTrademarkAttribute"
])
]
// These entries listed in the MSDN documentation as "standard" string entries are not yet settable
@ -421,7 +551,7 @@ module MainModuleBuilder =
// Either high-order or low-order word can be zero, indicating that
// the file is language or code page independent. If the Var structure is
// omitted, the file will be interpreted as both language and code page independent. "
let varFileInfo = [ (0x0, 0x04b0) ]
let varFileInfo = [ (0x0, 0x04b0) ]
let fixedFileInfo =
let dwFileFlagsMask = 0x3f // REVIEW: HARDWIRED
@ -430,71 +560,127 @@ module MainModuleBuilder =
let dwFileType = 0x01 // REVIEW: HARDWIRED
let dwFileSubtype = 0x00 // REVIEW: HARDWIRED
let lwFileDate = 0x00L // REVIEW: HARDWIRED
(fileVersionInfo, productVersionString |> ConvertProductVersionToILVersionInfo, dwFileFlagsMask, dwFileFlags, dwFileOS, dwFileType, dwFileSubtype, lwFileDate)
let ilProductVersion = productVersionString |> ConvertProductVersionToILVersionInfo
(fileVersionInfo, ilProductVersion, dwFileFlagsMask, dwFileFlags, dwFileOS, dwFileType, dwFileSubtype, lwFileDate)
let vsVersionInfoResource =
VersionResourceFormat.VS_VERSION_INFO_RESOURCE(fixedFileInfo, stringFileInfo, varFileInfo)
let resource =
[| yield! ResFileFormat.ResFileHeader()
yield! vsVersionInfoResource |]
[| yield! ResFileFormat.ResFileHeader(); yield! vsVersionInfoResource |]
[ resource ]
// a user cannot specify both win32res and win32manifest
if not(tcConfig.win32manifest = "") && not(tcConfig.win32res = "") then
error(Error(FSComp.SR.fscTwoResourceManifests(), rangeCmdArgs))
if not (tcConfig.win32manifest = "") && not (tcConfig.win32res = "") then
error (Error(FSComp.SR.fscTwoResourceManifests (), rangeCmdArgs))
let win32Manifest =
// use custom manifest if provided
if not(tcConfig.win32manifest = "") then tcConfig.win32manifest
if not (tcConfig.win32manifest = "") then
tcConfig.win32manifest
// don't embed a manifest if target is not an exe, if manifest is specifically excluded, if another native resource is being included, or if running on mono
elif not(tcConfig.target.IsExe) || not(tcConfig.includewin32manifest) || not(tcConfig.win32res = "") || runningOnMono then ""
elif not (tcConfig.target.IsExe)
|| not (tcConfig.includewin32manifest)
|| not (tcConfig.win32res = "")
|| runningOnMono then
""
// otherwise, include the default manifest
else
let path=Path.Combine(FSharpEnvironment.getFSharpCompilerLocation(), @"default.win32manifest")
let path =
Path.Combine(FSharpEnvironment.getFSharpCompilerLocation (), @"default.win32manifest")
if FileSystem.FileExistsShim(path) then
path
else
let path = Path.Combine(AppContext.BaseDirectory, @"default.win32manifest")
if FileSystem.FileExistsShim(path) then
path
else
Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), @"default.win32manifest")
let nativeResources =
[ for av in assemblyVersionResources assemblyVersion do
yield ILNativeResource.Out av
if not(tcConfig.win32res = "") then
yield ILNativeResource.Out (FileSystem.OpenFileForReadShim(tcConfig.win32res).ReadAllBytes())
if tcConfig.includewin32manifest && not(win32Manifest = "") && not runningOnMono then
yield ILNativeResource.Out [| yield! ResFileFormat.ResFileHeader()
yield! (ManifestResourceFormat.VS_MANIFEST_RESOURCE((FileSystem.OpenFileForReadShim(win32Manifest).ReadAllBytes()), tcConfig.target = CompilerTarget.Dll)) |]
if tcConfig.win32res = "" && tcConfig.win32icon <> "" && tcConfig.target <> CompilerTarget.Dll then
use ms = new MemoryStream()
use iconStream = FileSystem.OpenFileForReadShim(tcConfig.win32icon)
Win32ResourceConversions.AppendIconToResourceStream(ms, iconStream)
yield ILNativeResource.Out [| yield! ResFileFormat.ResFileHeader()
yield! ms.ToArray() |] ]
[
for av in assemblyVersionResources assemblyVersion do
ILNativeResource.Out av
if not (tcConfig.win32res = "") then
ILNativeResource.Out(FileSystem.OpenFileForReadShim(tcConfig.win32res).ReadAllBytes())
if tcConfig.includewin32manifest && not (win32Manifest = "") && not runningOnMono then
ILNativeResource.Out
[|
yield! ResFileFormat.ResFileHeader()
yield!
(ManifestResourceFormat.VS_MANIFEST_RESOURCE(
(FileSystem.OpenFileForReadShim(win32Manifest).ReadAllBytes()),
tcConfig.target = CompilerTarget.Dll
))
|]
if tcConfig.win32res = ""
&& tcConfig.win32icon <> ""
&& tcConfig.target <> CompilerTarget.Dll then
use ms = new MemoryStream()
use iconStream = FileSystem.OpenFileForReadShim(tcConfig.win32icon)
Win32ResourceConversions.AppendIconToResourceStream(ms, iconStream)
ILNativeResource.Out [| yield! ResFileFormat.ResFileHeader(); yield! ms.ToArray() |]
]
let name =
if tcConfig.target = CompilerTarget.Module then
FileSystemUtils.fileNameOfPath outfile
else
mainModule.Name
let imageBase =
match tcConfig.baseAddress with
| None -> 0x00400000l
| Some b -> b
let isDLL =
(tcConfig.target = CompilerTarget.Dll || tcConfig.target = CompilerTarget.Module)
let is32bit =
match tcConfig.platform with
| Some X86
| Some ARM -> true
| _ -> false
let is64bit =
match tcConfig.platform with
| Some AMD64
| Some IA64
| Some ARM64 -> true
| _ -> false
let is32BitPreferred =
if tcConfig.prefer32Bit && not tcConfig.target.IsExe then
(error (Error(FSComp.SR.invalidPlatformTarget (), rangeCmdArgs)))
else
tcConfig.prefer32Bit
let attribs =
storeILCustomAttrs (
mkILCustomAttrs
[
if tcConfig.target = CompilerTarget.Module then
yield! sigDataAttributes
yield! codegenResults.ilNetModuleAttrs
]
)
// Add attributes, version number, resources etc.
{mainModule with
StackReserveSize = tcConfig.stackReserveSize
Name = (if tcConfig.target = CompilerTarget.Module then FileSystemUtils.fileNameOfPath outfile else mainModule.Name)
SubSystemFlags = (if tcConfig.target = CompilerTarget.WinExe then 2 else 3)
Resources= resources
ImageBase = (match tcConfig.baseAddress with None -> 0x00400000l | Some b -> b)
IsDLL=(tcConfig.target = CompilerTarget.Dll || tcConfig.target=CompilerTarget.Module)
Platform = tcConfig.platform
Is32Bit=(match tcConfig.platform with Some X86 | Some ARM -> true | _ -> false)
Is64Bit=(match tcConfig.platform with Some AMD64 | Some IA64 | Some ARM64 -> true | _ -> false)
Is32BitPreferred = if tcConfig.prefer32Bit && not tcConfig.target.IsExe then (error(Error(FSComp.SR.invalidPlatformTarget(), rangeCmdArgs))) else tcConfig.prefer32Bit
CustomAttrsStored=
storeILCustomAttrs
(mkILCustomAttrs
[ if tcConfig.target = CompilerTarget.Module then
yield! sigDataAttributes
yield! codegenResults.ilNetModuleAttrs ])
NativeResources=nativeResources
Manifest = manifest }
{ mainModule with
StackReserveSize = tcConfig.stackReserveSize
Name = name
SubSystemFlags = (if tcConfig.target = CompilerTarget.WinExe then 2 else 3)
Resources = resources
ImageBase = imageBase
IsDLL = isDLL
Platform = tcConfig.platform
Is32Bit = is32bit
Is64Bit = is64bit
Is32BitPreferred = is32BitPreferred
CustomAttrsStored = attribs
NativeResources = nativeResources
Manifest = manifest
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -20,11 +20,16 @@ open FSharp.Compiler.TypedTreeOps
let mutable showTermFileCount = 0
let PrintWholeAssemblyImplementation g (tcConfig:TcConfig) outfile header expr =
let PrintWholeAssemblyImplementation g (tcConfig: TcConfig) outfile header expr =
if tcConfig.showTerms then
if tcConfig.writeTermsToFiles then
let fileName = outfile + ".terms"
use f = FileSystem.OpenFileForWriteShim(fileName + "-" + string showTermFileCount + "-" + header, FileMode.Create).GetWriter()
use f =
FileSystem
.OpenFileForWriteShim(fileName + "-" + string showTermFileCount + "-" + header, FileMode.Create)
.GetWriter()
showTermFileCount <- showTermFileCount + 1
LayoutRender.outL f (Display.squashTo 192 (DebugPrint.implFilesL g expr))
else
@ -37,13 +42,24 @@ let AddExternalCcuToOptimizationEnv tcGlobals optEnv (ccuinfo: ImportedAssembly)
| None -> optEnv
| Some data -> Optimizer.BindCcu ccuinfo.FSharpViewOfMetadata data optEnv tcGlobals
let GetInitialOptimizationEnv (tcImports:TcImports, tcGlobals:TcGlobals) =
let GetInitialOptimizationEnv (tcImports: TcImports, tcGlobals: TcGlobals) =
let ccuinfos = tcImports.GetImportedAssemblies()
let optEnv = Optimizer.IncrementalOptimizationEnv.Empty
let optEnv = List.fold (AddExternalCcuToOptimizationEnv tcGlobals) optEnv ccuinfos
optEnv
let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importMap, isIncrementalFragment, optEnv, ccu:CcuThunk, implFiles) =
let ApplyAllOptimizations
(
tcConfig: TcConfig,
tcGlobals,
tcVal,
outfile,
importMap,
isIncrementalFragment,
optEnv,
ccu: CcuThunk,
implFiles
) =
// NOTE: optEnv - threads through
//
// Always optimize once - the results of this step give the x-module optimization
@ -52,7 +68,9 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
PrintWholeAssemblyImplementation tcGlobals tcConfig outfile "pass-start" implFiles
#if DEBUG
if tcConfig.showOptimizationData then
dprintf "Expression prior to optimization:\n%s\n" (LayoutRender.showL (Display.squashTo 192 (DebugPrint.implFilesL tcGlobals implFiles)))
dprintf
"Expression prior to optimization:\n%s\n"
(LayoutRender.showL (Display.squashTo 192 (DebugPrint.implFilesL tcGlobals implFiles)))
if tcConfig.showOptimizationData then
dprintf "CCU prior to optimization:\n%s\n" (LayoutRender.showL (Display.squashTo 192 (DebugPrint.entityL tcGlobals ccu.Contents)))
@ -63,8 +81,16 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
// Only do abstract_big_targets on the first pass! Only do it when TLR is on!
let optSettings = tcConfig.optSettings
let optSettings = { optSettings with abstractBigTargets = tcConfig.doTLR }
let optSettings = { optSettings with reportingPhase = true }
let optSettings =
{ optSettings with
abstractBigTargets = tcConfig.doTLR
}
let optSettings =
{ optSettings with
reportingPhase = true
}
let results, (optEnvFirstLoop, _, _, _) =
((optEnv0, optEnv0, optEnv0, SignatureHidingInfo.Empty), implFiles)
@ -73,18 +99,33 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
//ReportTime tcConfig ("Initial simplify")
let (optEnvFirstLoop, implFile, implFileOptData, hidden), optimizeDuringCodeGen =
Optimizer.OptimizeImplFile
(optSettings, ccu, tcGlobals, tcVal, importMap,
optEnvFirstLoop, isIncrementalFragment, tcConfig.fsiMultiAssemblyEmit,
tcConfig.emitTailcalls, hidden, implFile)
Optimizer.OptimizeImplFile(
optSettings,
ccu,
tcGlobals,
tcVal,
importMap,
optEnvFirstLoop,
isIncrementalFragment,
tcConfig.fsiMultiAssemblyEmit,
tcConfig.emitTailcalls,
hidden,
implFile
)
let implFile = LowerLocalMutables.TransformImplFile tcGlobals importMap implFile
// Only do this on the first pass!
let optSettings = { optSettings with abstractBigTargets = false; reportingPhase = false }
let optSettings =
{ optSettings with
abstractBigTargets = false
reportingPhase = false
}
#if DEBUG
if tcConfig.showOptimizationData then
dprintf "Optimization implFileOptData:\n%s\n" (LayoutRender.showL (Display.squashTo 192 (Optimizer.moduleInfoL tcGlobals implFileOptData)))
dprintf
"Optimization implFileOptData:\n%s\n"
(LayoutRender.showL (Display.squashTo 192 (Optimizer.moduleInfoL tcGlobals implFileOptData)))
#endif
let implFile, optEnvExtraLoop =
@ -92,10 +133,19 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
//ReportTime tcConfig ("Extra simplification loop")
let (optEnvExtraLoop, implFile, _, _), _ =
Optimizer.OptimizeImplFile
(optSettings, ccu, tcGlobals, tcVal, importMap,
optEnvExtraLoop, isIncrementalFragment, tcConfig.fsiMultiAssemblyEmit,
tcConfig.emitTailcalls, hidden, implFile)
Optimizer.OptimizeImplFile(
optSettings,
ccu,
tcGlobals,
tcVal,
importMap,
optEnvExtraLoop,
isIncrementalFragment,
tcConfig.fsiMultiAssemblyEmit,
tcConfig.emitTailcalls,
hidden,
implFile
)
//PrintWholeAssemblyImplementation tcConfig outfile (sprintf "extra-loop-%d" n) implFile
implFile, optEnvExtraLoop
@ -108,24 +158,36 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
let implFile = implFile |> Detuple.DetupleImplFile ccu tcGlobals
//PrintWholeAssemblyImplementation tcConfig outfile "post-detuple" implFile
implFile
else implFile
else
implFile
let implFile =
if tcConfig.doTLR then
implFile |> InnerLambdasToTopLevelFuncs.MakeTopLevelRepresentationDecisions ccu tcGlobals
else implFile
implFile
|> InnerLambdasToTopLevelFuncs.MakeTopLevelRepresentationDecisions ccu tcGlobals
else
implFile
let implFile =
LowerCalls.LowerImplFile tcGlobals implFile
let implFile = LowerCalls.LowerImplFile tcGlobals implFile
let implFile, optEnvFinalSimplify =
if tcConfig.doFinalSimplify then
//ReportTime tcConfig ("Final simplify pass")
let (optEnvFinalSimplify, implFile, _, _), _ =
Optimizer.OptimizeImplFile
(optSettings, ccu, tcGlobals, tcVal, importMap, optEnvFinalSimplify,
isIncrementalFragment, tcConfig.fsiMultiAssemblyEmit, tcConfig.emitTailcalls, hidden, implFile)
Optimizer.OptimizeImplFile(
optSettings,
ccu,
tcGlobals,
tcVal,
importMap,
optEnvFinalSimplify,
isIncrementalFragment,
tcConfig.fsiMultiAssemblyEmit,
tcConfig.emitTailcalls,
hidden,
implFile
)
//PrintWholeAssemblyImplementation tcConfig outfile "post-rec-opt" implFile
implFile, optEnvFinalSimplify
@ -133,8 +195,10 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
implFile, optEnvFinalSimplify
let implFile =
{ ImplFile = implFile
OptimizeDuringCodeGen = optimizeDuringCodeGen }
{
ImplFile = implFile
OptimizeDuringCodeGen = optimizeDuringCodeGen
}
(implFile, implFileOptData), (optEnvFirstLoop, optEnvExtraLoop, optEnvFinalSimplify, hidden))
@ -149,17 +213,20 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM
// ILX generation
//----------------------------------------------------------------------------
let CreateIlxAssemblyGenerator (_tcConfig:TcConfig, tcImports:TcImports, tcGlobals, tcVal, generatedCcu) =
let ilxGenerator = IlxAssemblyGenerator(tcImports.GetImportMap(), tcGlobals, tcVal, generatedCcu)
let CreateIlxAssemblyGenerator (_tcConfig: TcConfig, tcImports: TcImports, tcGlobals, tcVal, generatedCcu) =
let ilxGenerator =
IlxAssemblyGenerator(tcImports.GetImportMap(), tcGlobals, tcVal, generatedCcu)
let ccus = tcImports.GetCcusInDeclOrder()
ilxGenerator.AddExternalCcus ccus
ilxGenerator
let GenerateIlxCode (
let GenerateIlxCode
(
ilxBackend,
isInteractiveItExpr,
isInteractiveOnMono,
tcConfig:TcConfig,
tcConfig: TcConfig,
topAttrs: TopAttribs,
optimizedImpls,
fragName,
@ -167,35 +234,39 @@ let GenerateIlxCode (
) =
let mainMethodInfo =
if (tcConfig.target = CompilerTarget.Dll) || (tcConfig.target = CompilerTarget.Module) then
None
else Some topAttrs.mainMethodAttrs
if (tcConfig.target = CompilerTarget.Dll)
|| (tcConfig.target = CompilerTarget.Module) then
None
else
Some topAttrs.mainMethodAttrs
let ilxGenOpts: IlxGenOptions =
{ generateFilterBlocks = tcConfig.generateFilterBlocks
emitConstantArraysUsingStaticDataBlobs = not isInteractiveOnMono
workAroundReflectionEmitBugs = tcConfig.isInteractive
generateDebugSymbols = tcConfig.debuginfo
fragName = fragName
localOptimizationsEnabled= tcConfig.optSettings.LocalOptimizationsEnabled
testFlagEmitFeeFeeAs100001 = tcConfig.testFlagEmitFeeFeeAs100001
mainMethodInfo= mainMethodInfo
ilxBackend = ilxBackend
fsiMultiAssemblyEmit = tcConfig.fsiMultiAssemblyEmit
isInteractive = tcConfig.isInteractive
isInteractiveItExpr = isInteractiveItExpr
alwaysCallVirt = tcConfig.alwaysCallVirt }
{
generateFilterBlocks = tcConfig.generateFilterBlocks
emitConstantArraysUsingStaticDataBlobs = not isInteractiveOnMono
workAroundReflectionEmitBugs = tcConfig.isInteractive
generateDebugSymbols = tcConfig.debuginfo
fragName = fragName
localOptimizationsEnabled = tcConfig.optSettings.LocalOptimizationsEnabled
testFlagEmitFeeFeeAs100001 = tcConfig.testFlagEmitFeeFeeAs100001
mainMethodInfo = mainMethodInfo
ilxBackend = ilxBackend
fsiMultiAssemblyEmit = tcConfig.fsiMultiAssemblyEmit
isInteractive = tcConfig.isInteractive
isInteractiveItExpr = isInteractiveItExpr
alwaysCallVirt = tcConfig.alwaysCallVirt
}
ilxGenerator.GenerateCode (ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs)
ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs)
//----------------------------------------------------------------------------
// Assembly ref normalization: make sure all assemblies are referred to
// by the same references. Only used for static linking.
//----------------------------------------------------------------------------
let NormalizeAssemblyRefs (ctok, ilGlobals: ILGlobals, tcImports:TcImports) scoref =
let NormalizeAssemblyRefs (ctok, ilGlobals: ILGlobals, tcImports: TcImports) scoref =
let normalizeAssemblyRefByName nm =
match tcImports.TryFindDllInfo (ctok, Range.rangeStartup, nm, lookupOnly=false) with
match tcImports.TryFindDllInfo(ctok, Range.rangeStartup, nm, lookupOnly = false) with
| Some dllInfo -> dllInfo.ILScopeRef
| None -> scoref
@ -205,7 +276,12 @@ let NormalizeAssemblyRefs (ctok, ilGlobals: ILGlobals, tcImports:TcImports) scor
| ILScopeRef.PrimaryAssembly -> normalizeAssemblyRefByName ilGlobals.primaryAssemblyName
| ILScopeRef.Assembly aref -> normalizeAssemblyRefByName aref.Name
let GetGeneratedILModuleName (t:CompilerTarget) (s:string) =
let GetGeneratedILModuleName (t: CompilerTarget) (s: string) =
// return the name of the file as a module name
let ext = match t with CompilerTarget.Dll -> "dll" | CompilerTarget.Module -> "netmodule" | _ -> "exe"
let ext =
match t with
| CompilerTarget.Dll -> "dll"
| CompilerTarget.Module -> "netmodule"
| _ -> "exe"
s + "." + ext

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -73,26 +73,20 @@ type LoadClosure =
LoadClosureRootFileDiagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list
}
[<RequireQualifiedAccess>]
type CodeContext =
| CompilationAndEvaluation // in fsi.exe
| Compilation // in fsc.exe
| Compilation // in fsc.exe
| Editing // in VS
module ScriptPreprocessClosure =
/// Represents an input to the closure finding process
type ClosureSource =
ClosureSource of
fileName: string *
referenceRange: range *
sourceText: ISourceText *
parseRequired: bool
type ClosureSource = ClosureSource of fileName: string * referenceRange: range * sourceText: ISourceText * parseRequired: bool
/// Represents an output of the closure finding process
type ClosureFile =
ClosureFile of
| ClosureFile of
fileName: string *
range: range *
parsedInput: ParsedInput option *
@ -102,12 +96,11 @@ module ScriptPreprocessClosure =
type Observed() =
let seen = Dictionary<_, bool>()
member _.SetSeen check =
if not(seen.ContainsKey check) then
seen.Add(check, true)
member _.HaveSeen check =
seen.ContainsKey check
member _.SetSeen check =
if not (seen.ContainsKey check) then seen.Add(check, true)
member _.HaveSeen check = seen.ContainsKey check
/// Parse a script file (or any input file referenced by '#load')
let ParseScriptClosureInput
@ -127,19 +120,25 @@ module ScriptPreprocessClosure =
// .fsx -- EDITING + !COMPILED\INTERACTIVE
let defines =
match codeContext with
| CodeContext.CompilationAndEvaluation -> ["INTERACTIVE"]
| CodeContext.Compilation -> ["COMPILED"]
| CodeContext.Editing -> "EDITING" :: (if IsScript fileName then ["INTERACTIVE"] else ["COMPILED"])
| CodeContext.CompilationAndEvaluation -> [ "INTERACTIVE" ]
| CodeContext.Compilation -> [ "COMPILED" ]
| CodeContext.Editing ->
"EDITING"
:: (if IsScript fileName then
[ "INTERACTIVE" ]
else
[ "COMPILED" ])
let tcConfigB = tcConfig.CloneToBuilder()
let tcConfigB = tcConfig.CloneToBuilder()
tcConfigB.conditionalDefines <- defines @ tcConfig.conditionalDefines
let tcConfig = TcConfig.Create(tcConfigB, false)
let lexbuf = UnicodeLexing.SourceTextAsLexbuf(true, tcConfig.langVersion, sourceText)
let lexbuf =
UnicodeLexing.SourceTextAsLexbuf(true, tcConfig.langVersion, sourceText)
// The root compiland is last in the list of compilands.
let isLastCompiland = (IsScript fileName, tcConfig.target.IsExe)
ParseOneInputLexbuf (tcConfig, lexResourceManager, lexbuf, fileName, isLastCompiland, diagnosticsLogger)
ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, fileName, isLastCompiland, diagnosticsLogger)
/// Create a TcConfig for load closure starting from a single .fsx file
let CreateScriptTextTcConfig
@ -164,8 +163,10 @@ module ScriptPreprocessClosure =
let isInvalidationSupported = (codeContext = CodeContext.Editing)
let rangeForErrors = mkFirstLineOfFile fileName
let tcConfigB =
TcConfigBuilder.CreateNew(legacyReferenceResolver,
TcConfigBuilder.CreateNew(
legacyReferenceResolver,
defaultFSharpBinariesDir,
reduceMemoryUsage,
projectDir,
@ -174,8 +175,16 @@ module ScriptPreprocessClosure =
CopyFSharpCoreFlag.No,
tryGetMetadataSnapshot,
sdkDirOverride,
rangeForErrors)
tcConfigB.SetPrimaryAssembly (if assumeDotNetFramework then PrimaryAssembly.Mscorlib else PrimaryAssembly.System_Runtime)
rangeForErrors
)
let primaryAssembly =
if assumeDotNetFramework then
PrimaryAssembly.Mscorlib
else
PrimaryAssembly.System_Runtime
tcConfigB.SetPrimaryAssembly primaryAssembly
tcConfigB.SetUseSdkRefs useSdkRefs
applyCommandLineArgs tcConfigB
@ -186,13 +195,21 @@ module ScriptPreprocessClosure =
match basicReferences with
| None ->
let diagnosticsLogger = CapturingDiagnosticsLogger("ScriptDefaultReferences")
use unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind (fun _ -> diagnosticsLogger)
let references, useDotNetFramework = tcConfigB.FxResolver.GetDefaultReferences useFsiAuxLib
use unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind(fun _ -> diagnosticsLogger)
let references, useDotNetFramework =
tcConfigB.FxResolver.GetDefaultReferences useFsiAuxLib
// If the user requested .NET Core scripting but something went wrong and we reverted to
// .NET Framework scripting then we must adjust both the primaryAssembly and fxResolver
if useDotNetFramework <> assumeDotNetFramework then
tcConfigB.SetPrimaryAssembly (if useDotNetFramework then PrimaryAssembly.Mscorlib else PrimaryAssembly.System_Runtime)
let primaryAssembly =
if useDotNetFramework then
PrimaryAssembly.Mscorlib
else
PrimaryAssembly.System_Runtime
tcConfigB.SetPrimaryAssembly primaryAssembly
// Add script references
for reference in references do
@ -203,6 +220,7 @@ module ScriptPreprocessClosure =
| Some (rs, diagnostics) ->
for m, reference in rs do
tcConfigB.AddReferencedAssemblyByPath(m, reference)
diagnostics
tcConfigB.resolutionEnvironment <-
@ -221,18 +239,20 @@ module ScriptPreprocessClosure =
tcConfigB.SetUseSdkRefs useSdkRefs
TcConfig.Create(tcConfigB, validate=true), scriptDefaultReferencesDiagnostics
TcConfig.Create(tcConfigB, validate = true), scriptDefaultReferencesDiagnostics
let ClosureSourceOfFilename(fileName, m, inputCodePage, parseRequired) =
let ClosureSourceOfFilename (fileName, m, inputCodePage, parseRequired) =
try
let fileName = FileSystem.GetFullPathShim fileName
use stream = FileSystem.OpenFileForReadShim(fileName)
use reader =
match inputCodePage with
| None -> new StreamReader(stream, true)
| Some (n: int) -> new StreamReader(stream, Encoding.GetEncoding n)
let source = reader.ReadToEnd()
[ClosureSource(fileName, m, SourceText.ofString source, parseRequired)]
[ ClosureSource(fileName, m, SourceText.ofString source, parseRequired) ]
with exn ->
errorRecovery exn m
[]
@ -247,27 +267,39 @@ module ScriptPreprocessClosure =
let tcConfigB = tcConfig.CloneToBuilder()
let mutable nowarns = []
let getWarningNumber = fun () (m, s) -> nowarns <- (s, m) :: nowarns
let addReferenceDirective = fun () (m, s, directive) -> tcConfigB.AddReferenceDirective(dependencyProvider, m, s, directive)
let addLoadedSource = fun () (m, s) -> tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource)
let getWarningNumber () (m, s) = nowarns <- (s, m) :: nowarns
let addReferenceDirective () (m, s, directive) =
tcConfigB.AddReferenceDirective(dependencyProvider, m, s, directive)
let addLoadedSource () (m, s) =
tcConfigB.AddLoadedSource(m, s, pathOfMetaCommandSource)
try
ProcessMetaCommandsFromInput (getWarningNumber, addReferenceDirective, addLoadedSource) (tcConfigB, inp, pathOfMetaCommandSource, ())
ProcessMetaCommandsFromInput
(getWarningNumber, addReferenceDirective, addLoadedSource)
(tcConfigB, inp, pathOfMetaCommandSource, ())
with ReportedError _ ->
// Recover by using whatever did end up in the tcConfig
()
try
TcConfig.Create(tcConfigB, validate=false), nowarns
TcConfig.Create(tcConfigB, validate = false), nowarns
with ReportedError _ ->
// Recover by using a default TcConfig.
let tcConfigB = tcConfig.CloneToBuilder()
TcConfig.Create(tcConfigB, validate=false), nowarns
TcConfig.Create(tcConfigB, validate = false), nowarns
let getDirective d =
match d with
| Directive.Resolution -> "r"
| Directive.Include -> "i"
let FindClosureFiles
(
mainFile,
closureSources,
origTcConfig:TcConfig,
origTcConfig: TcConfig,
codeContext,
lexResourceManager: Lexhelp.LexResourceManager,
dependencyProvider: DependencyProvider
@ -281,165 +313,273 @@ module ScriptPreprocessClosure =
// Resolve the packages
let rec resolveDependencyManagerSources scriptName =
if not (loadScripts.Contains scriptName) then
[ for kv in tcConfig.packageManagerLines do
let packageManagerKey, packageManagerLines = kv.Key, kv.Value
match packageManagerLines with
| [] -> ()
| { Directive=_; LineStatus=_; Line=_; Range=m } :: _ ->
let reportError =
ResolvingErrorReport (fun errorType err msg ->
let error = err, msg
match errorType with
| ErrorReportType.Warning -> warning(Error(error, m))
| ErrorReportType.Error -> errorR(Error(error, m)))
[
if not (loadScripts.Contains scriptName) then
for kv in tcConfig.packageManagerLines do
let packageManagerKey, packageManagerLines = kv.Key, kv.Value
match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with
| Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> ()
| _ ->
let outputDir = tcConfig.outputDir |> Option.defaultValue ""
match dependencyProvider.TryFindDependencyManagerByKey(tcConfig.compilerToolPaths, outputDir, reportError, packageManagerKey) with
| Null ->
errorR(Error(dependencyProvider.CreatePackageManagerUnknownError(tcConfig.compilerToolPaths, outputDir, packageManagerKey, reportError), m))
match packageManagerLines with
| [] -> ()
| packageManagerLine :: _ ->
let m = packageManagerLine.Range
yield! processPackageManagerLines m packageManagerLines scriptName packageManagerKey
]
| NonNull dependencyManager ->
let directive d =
match d with
| Directive.Resolution -> "r"
| Directive.Include -> "i"
and reportError m =
ResolvingErrorReport(fun errorType err msg ->
let error = err, msg
let packageManagerTextLines = packageManagerLines |> List.map(fun l -> directive l.Directive, l.Line)
let tfm, rid = tcConfig.FxResolver.GetTfmAndRid()
let result = dependencyProvider.Resolve(dependencyManager, ".fsx", packageManagerTextLines, reportError, tfm, rid, tcConfig.implicitIncludeDir, mainFile, scriptName)
if result.Success then
// Resolution produced no errors
//Write outputs in F# Interactive and compiler
if codeContext <> CodeContext.Editing then
for line in result.StdOut do Console.Out.WriteLine(line)
for line in result.StdError do Console.Error.WriteLine(line)
match errorType with
| ErrorReportType.Warning -> warning (Error(error, m))
| ErrorReportType.Error -> errorR (Error(error, m)))
packageReferences[m] <- [ for script in result.SourceFiles do yield! FileSystem.OpenFileForReadShim(script).ReadLines() ]
if not (Seq.isEmpty result.Roots) then
let tcConfigB = tcConfig.CloneToBuilder()
for folder in result.Roots do
tcConfigB.AddIncludePath(m, folder, "")
tcConfigB.packageManagerLines <- PackageManagerLine.SetLinesAsProcessed packageManagerKey tcConfigB.packageManagerLines
tcConfig <- TcConfig.Create(tcConfigB, validate=false)
and processPackageManagerLines m packageManagerLines scriptName packageManagerKey =
[
if not (Seq.isEmpty result.Resolutions) then
let tcConfigB = tcConfig.CloneToBuilder()
for resolution in result.Resolutions do
tcConfigB.AddReferencedAssemblyByPath(m, resolution)
tcConfig <- TcConfig.Create(tcConfigB, validate = false)
match origTcConfig.packageManagerLines |> Map.tryFind packageManagerKey with
| Some oldDependencyManagerLines when oldDependencyManagerLines = packageManagerLines -> ()
| _ ->
let outputDir = tcConfig.outputDir |> Option.defaultValue ""
for script in result.SourceFiles do
use stream = FileSystem.OpenFileForReadShim(script)
let scriptText = stream.ReadAllText()
loadScripts.Add script |> ignore
let iSourceText = SourceText.ofString scriptText
yield! loop (ClosureSource(script, m, iSourceText, true))
let managerOpt =
dependencyProvider.TryFindDependencyManagerByKey(
tcConfig.compilerToolPaths,
outputDir,
reportError m,
packageManagerKey
)
else
// Send outputs via diagnostics
if (result.StdOut.Length > 0 || result.StdError.Length > 0) then
for line in Array.append result.StdOut result.StdError do
errorR(Error(FSComp.SR.packageManagerError(line), m))
// Resolution produced errors update packagerManagerLines entries to note these failure
// failed resolutions will no longer be considered
let tcConfigB = tcConfig.CloneToBuilder()
tcConfigB.packageManagerLines <- PackageManagerLine.RemoveUnprocessedLines packageManagerKey tcConfigB.packageManagerLines
tcConfig <- TcConfig.Create(tcConfigB, validate=false)]
else []
match managerOpt with
| Null ->
let err =
dependencyProvider.CreatePackageManagerUnknownError(
tcConfig.compilerToolPaths,
outputDir,
packageManagerKey,
reportError m
)
and loop (ClosureSource(fileName, m, sourceText, parseRequired)) =
[ if not (observedSources.HaveSeen(fileName)) then
errorR (Error(err, m))
| NonNull dependencyManager ->
yield! resolvePackageManagerLines m packageManagerLines scriptName packageManagerKey dependencyManager
]
and resolvePackageManagerLines m packageManagerLines scriptName packageManagerKey dependencyManager =
[
let packageManagerTextLines =
packageManagerLines |> List.map (fun l -> getDirective l.Directive, l.Line)
let tfm, rid = tcConfig.FxResolver.GetTfmAndRid()
let result =
dependencyProvider.Resolve(
dependencyManager,
".fsx",
packageManagerTextLines,
reportError m,
tfm,
rid,
tcConfig.implicitIncludeDir,
mainFile,
scriptName
)
if result.Success then
// Resolution produced no errors
//Write outputs in F# Interactive and compiler
if codeContext <> CodeContext.Editing then
for line in result.StdOut do
Console.Out.WriteLine(line)
for line in result.StdError do
Console.Error.WriteLine(line)
packageReferences[m] <-
[
for script in result.SourceFiles do
yield! FileSystem.OpenFileForReadShim(script).ReadLines()
]
if not (Seq.isEmpty result.Roots) then
let tcConfigB = tcConfig.CloneToBuilder()
for folder in result.Roots do
tcConfigB.AddIncludePath(m, folder, "")
tcConfigB.packageManagerLines <-
PackageManagerLine.SetLinesAsProcessed packageManagerKey tcConfigB.packageManagerLines
tcConfig <- TcConfig.Create(tcConfigB, validate = false)
if not (Seq.isEmpty result.Resolutions) then
let tcConfigB = tcConfig.CloneToBuilder()
for resolution in result.Resolutions do
tcConfigB.AddReferencedAssemblyByPath(m, resolution)
tcConfig <- TcConfig.Create(tcConfigB, validate = false)
for script in result.SourceFiles do
use stream = FileSystem.OpenFileForReadShim(script)
let scriptText = stream.ReadAllText()
loadScripts.Add script |> ignore
let iSourceText = SourceText.ofString scriptText
yield! processClosureSource (ClosureSource(script, m, iSourceText, true))
else
// Send outputs via diagnostics
if (result.StdOut.Length > 0 || result.StdError.Length > 0) then
for line in Array.append result.StdOut result.StdError do
errorR (Error(FSComp.SR.packageManagerError (line), m))
// Resolution produced errors update packagerManagerLines entries to note these failure
// failed resolutions will no longer be considered
let tcConfigB = tcConfig.CloneToBuilder()
tcConfigB.packageManagerLines <-
PackageManagerLine.RemoveUnprocessedLines packageManagerKey tcConfigB.packageManagerLines
tcConfig <- TcConfig.Create(tcConfigB, validate = false)
]
and processClosureSource (ClosureSource (fileName, m, sourceText, parseRequired)) =
[
if not (observedSources.HaveSeen(fileName)) then
observedSources.SetSeen(fileName)
//printfn "visiting %s" fileName
if IsScript fileName || parseRequired then
let parseResult, parseDiagnostics =
let diagnosticsLogger = CapturingDiagnosticsLogger("FindClosureParse")
use _unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind (fun _ -> diagnosticsLogger)
let result = ParseScriptClosureInput (fileName, sourceText, tcConfig, codeContext, lexResourceManager, diagnosticsLogger)
use _unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind(fun _ -> diagnosticsLogger)
let result =
ParseScriptClosureInput(fileName, sourceText, tcConfig, codeContext, lexResourceManager, diagnosticsLogger)
result, diagnosticsLogger.Diagnostics
let diagnosticsLogger = CapturingDiagnosticsLogger("FindClosureMetaCommands")
use _unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind (fun _ -> diagnosticsLogger)
use _unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind(fun _ -> diagnosticsLogger)
let pathOfMetaCommandSource = Path.GetDirectoryName fileName
let preSources = tcConfig.GetAvailableLoadedSources()
let tcConfigResult, noWarns = ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn (tcConfig, parseResult, pathOfMetaCommandSource, dependencyProvider)
let tcConfigResult, noWarns =
ApplyMetaCommandsFromInputToTcConfigAndGatherNoWarn(
tcConfig,
parseResult,
pathOfMetaCommandSource,
dependencyProvider
)
tcConfig <- tcConfigResult // We accumulate the tcConfig in order to collect assembly references
yield! resolveDependencyManagerSources fileName
let postSources = tcConfig.GetAvailableLoadedSources()
let sources = if preSources.Length < postSources.Length then postSources[preSources.Length..] else []
let sources =
if preSources.Length < postSources.Length then
postSources[preSources.Length ..]
else
[]
yield! resolveDependencyManagerSources fileName
for m, subFile in sources do
if IsScript subFile then
for subSource in ClosureSourceOfFilename(subFile, m, tcConfigResult.inputCodePage, false) do
yield! loop subSource
yield! processClosureSource subSource
else
yield ClosureFile(subFile, m, None, [], [], [])
yield ClosureFile(fileName, m, Some parseResult, parseDiagnostics, diagnosticsLogger.Diagnostics, noWarns)
ClosureFile(subFile, m, None, [], [], [])
ClosureFile(fileName, m, Some parseResult, parseDiagnostics, diagnosticsLogger.Diagnostics, noWarns)
else
// Don't traverse into .fs leafs.
printfn "yielding non-script source %s" fileName
yield ClosureFile(fileName, m, None, [], [], []) ]
ClosureFile(fileName, m, None, [], [], [])
]
let sources = closureSources |> List.collect processClosureSource
let packageReferences =
packageReferences |> Seq.map (fun kvp -> kvp.Key, kvp.Value) |> Seq.toArray
let sources = closureSources |> List.collect loop
let packageReferences = packageReferences |> Seq.map (fun kvp -> kvp.Key, kvp.Value) |> Seq.toArray
sources, tcConfig, packageReferences
/// Mark the last file as isLastCompiland.
let MarkLastCompiland (tcConfig: TcConfig, lastClosureFile) =
let (ClosureFile (fileName, m, lastParsedInput, parseDiagnostics, metaDiagnostics, nowarns)) =
lastClosureFile
match lastParsedInput with
| Some (ParsedInput.ImplFile lastParsedImplFile) ->
let (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, _, trivia)) =
lastParsedImplFile
let isLastCompiland = (true, tcConfig.target.IsExe)
let lastParsedImplFileR =
ParsedImplFileInput(name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, isLastCompiland, trivia)
let lastClosureFileR =
ClosureFile(fileName, m, Some(ParsedInput.ImplFile lastParsedImplFileR), parseDiagnostics, metaDiagnostics, nowarns)
lastClosureFileR
| _ -> lastClosureFile
/// Reduce the full directive closure into LoadClosure
let GetLoadClosure(rootFilename, closureFiles, tcConfig: TcConfig, codeContext, packageReferences, earlierDiagnostics) =
let GetLoadClosure (rootFilename, closureFiles, tcConfig: TcConfig, codeContext, packageReferences, earlierDiagnostics) =
// Mark the last file as isLastCompiland.
let closureFiles =
if isNil closureFiles then
closureFiles
else
match List.frontAndBack closureFiles with
| rest, ClosureFile
(fileName, m,
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, _, trivia))),
parseDiagnostics, metaDiagnostics, nowarns) ->
let isLastCompiland = (true, tcConfig.target.IsExe)
rest @ [ClosureFile
(fileName, m,
Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, isLastCompiland, trivia))),
parseDiagnostics, metaDiagnostics, nowarns)]
| _ -> closureFiles
match List.tryFrontAndBack closureFiles with
| None -> closureFiles
| Some (rest, lastClosureFile) ->
let lastClosureFileR = MarkLastCompiland(tcConfig, lastClosureFile)
rest @ [ lastClosureFileR ]
// Get all source files.
let sourceFiles = [ for ClosureFile(fileName, m, _, _, _, _) in closureFiles -> (fileName, m) ]
let sourceFiles =
[ for ClosureFile (fileName, m, _, _, _, _) in closureFiles -> (fileName, m) ]
let sourceInputs =
[ for ClosureFile(fileName, _, input, parseDiagnostics, metaDiagnostics, _nowarns) in closureFiles ->
({ FileName=fileName
SyntaxTree=input
ParseDiagnostics=parseDiagnostics
MetaCommandDiagnostics=metaDiagnostics } : LoadClosureInput) ]
[
for closureFile in closureFiles ->
let (ClosureFile (fileName, _, input, parseDiagnostics, metaDiagnostics, _nowarns)) =
closureFile
let globalNoWarns = closureFiles |> List.collect (fun (ClosureFile(_, _, _, _, _, noWarns)) -> noWarns)
let closureInput: LoadClosureInput =
{
FileName = fileName
SyntaxTree = input
ParseDiagnostics = parseDiagnostics
MetaCommandDiagnostics = metaDiagnostics
}
closureInput
]
let globalNoWarns =
closureFiles
|> List.collect (fun (ClosureFile (_, _, _, _, _, noWarns)) -> noWarns)
// Resolve all references.
let references, unresolvedReferences, resolutionDiagnostics =
let diagnosticsLogger = CapturingDiagnosticsLogger("GetLoadClosure")
use unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind (fun _ -> diagnosticsLogger)
let references, unresolvedReferences = TcAssemblyResolutions.GetAssemblyResolutionInformation(tcConfig)
use unwindEL = PushDiagnosticsLoggerPhaseUntilUnwind(fun _ -> diagnosticsLogger)
let references, unresolvedReferences =
TcAssemblyResolutions.GetAssemblyResolutionInformation(tcConfig)
let references = references |> List.map (fun ar -> ar.resolvedPath, ar)
references, unresolvedReferences, diagnosticsLogger.Diagnostics
// Root errors and warnings - look at the last item in the closureFiles list
let loadClosureRootDiagnostics, allRootDiagnostics =
match List.rev closureFiles with
| ClosureFile(_, _, _, parseDiagnostics, metaDiagnostics, _) :: _ ->
| ClosureFile (_, _, _, parseDiagnostics, metaDiagnostics, _) :: _ ->
(earlierDiagnostics @ metaDiagnostics @ resolutionDiagnostics),
(parseDiagnostics @ earlierDiagnostics @ metaDiagnostics @ resolutionDiagnostics)
| _ -> [], [] // When no file existed.
@ -448,8 +588,13 @@ module ScriptPreprocessClosure =
match GetRangeOfDiagnostic exn with
| Some m ->
// Return true if the error was *not* from a #load-ed file.
let isArgParameterWhileNotEditing = (codeContext <> CodeContext.Editing) && (equals m range0 || equals m rangeStartup || equals m rangeCmdArgs)
let isThisFileName = (0 = String.Compare(rootFilename, m.FileName, StringComparison.OrdinalIgnoreCase))
let isArgParameterWhileNotEditing =
(codeContext <> CodeContext.Editing)
&& (equals m range0 || equals m rangeStartup || equals m rangeCmdArgs)
let isThisFileName =
(0 = String.Compare(rootFilename, m.FileName, StringComparison.OrdinalIgnoreCase))
isArgParameterWhileNotEditing || isThisFileName
| None -> true
@ -457,18 +602,20 @@ module ScriptPreprocessClosure =
let allRootDiagnostics = allRootDiagnostics |> List.filter (fst >> isRootRange)
let result: LoadClosure =
{ SourceFiles = List.groupBy fst sourceFiles |> List.map (map2Of2 (List.map snd))
References = List.groupBy fst references |> List.map (map2Of2 (List.map snd))
PackageReferences = packageReferences
UseDesktopFramework = (tcConfig.primaryAssembly = PrimaryAssembly.Mscorlib)
SdkDirOverride = tcConfig.sdkDirOverride
UnresolvedReferences = unresolvedReferences
Inputs = sourceInputs
NoWarns = List.groupBy fst globalNoWarns |> List.map (map2Of2 (List.map snd))
OriginalLoadReferences = tcConfig.loadedSources
ResolutionDiagnostics = resolutionDiagnostics
AllRootFileDiagnostics = allRootDiagnostics
LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics }
{
SourceFiles = List.groupBy fst sourceFiles |> List.map (map2Of2 (List.map snd))
References = List.groupBy fst references |> List.map (map2Of2 (List.map snd))
PackageReferences = packageReferences
UseDesktopFramework = (tcConfig.primaryAssembly = PrimaryAssembly.Mscorlib)
SdkDirOverride = tcConfig.sdkDirOverride
UnresolvedReferences = unresolvedReferences
Inputs = sourceInputs
NoWarns = List.groupBy fst globalNoWarns |> List.map (map2Of2 (List.map snd))
OriginalLoadReferences = tcConfig.loadedSources
ResolutionDiagnostics = resolutionDiagnostics
AllRootFileDiagnostics = allRootDiagnostics
LoadClosureRootFileDiagnostics = loadClosureRootDiagnostics
}
result
@ -498,42 +645,81 @@ module ScriptPreprocessClosure =
// first, then #I and other directives are processed.
let references0, assumeDotNetFramework, scriptDefaultReferencesDiagnostics =
let tcConfig, scriptDefaultReferencesDiagnostics =
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir,
fileName, codeContext, useSimpleResolution,
useFsiAuxLib, None, applyCommandLineArgs, assumeDotNetFramework,
useSdkRefs, sdkDirOverride, tryGetMetadataSnapshot, reduceMemoryUsage)
CreateScriptTextTcConfig(
legacyReferenceResolver,
defaultFSharpBinariesDir,
fileName,
codeContext,
useSimpleResolution,
useFsiAuxLib,
None,
applyCommandLineArgs,
assumeDotNetFramework,
useSdkRefs,
sdkDirOverride,
tryGetMetadataSnapshot,
reduceMemoryUsage
)
let resolutions0, _unresolvedReferences =
TcAssemblyResolutions.GetAssemblyResolutionInformation(tcConfig)
let references0 =
resolutions0
|> List.map (fun r -> r.originalReference.Range, r.resolvedPath)
|> Seq.distinct
|> List.ofSeq
let resolutions0, _unresolvedReferences = TcAssemblyResolutions.GetAssemblyResolutionInformation(tcConfig)
let references0 = resolutions0 |> List.map (fun r->r.originalReference.Range, r.resolvedPath) |> Seq.distinct |> List.ofSeq
references0, tcConfig.assumeDotNetFramework, scriptDefaultReferencesDiagnostics
let tcConfig, scriptDefaultReferencesDiagnostics =
CreateScriptTextTcConfig(legacyReferenceResolver, defaultFSharpBinariesDir, fileName,
codeContext, useSimpleResolution, useFsiAuxLib, Some (references0, scriptDefaultReferencesDiagnostics),
applyCommandLineArgs, assumeDotNetFramework, useSdkRefs, sdkDirOverride,
tryGetMetadataSnapshot, reduceMemoryUsage)
CreateScriptTextTcConfig(
legacyReferenceResolver,
defaultFSharpBinariesDir,
fileName,
codeContext,
useSimpleResolution,
useFsiAuxLib,
Some(references0, scriptDefaultReferencesDiagnostics),
applyCommandLineArgs,
assumeDotNetFramework,
useSdkRefs,
sdkDirOverride,
tryGetMetadataSnapshot,
reduceMemoryUsage
)
let closureSources = [ ClosureSource(fileName, range0, sourceText, true) ]
let closureFiles, tcConfig, packageReferences =
FindClosureFiles(fileName, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider)
let closureSources = [ClosureSource(fileName, range0, sourceText, true)]
let closureFiles, tcConfig, packageReferences = FindClosureFiles(fileName, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider)
GetLoadClosure(fileName, closureFiles, tcConfig, codeContext, packageReferences, scriptDefaultReferencesDiagnostics)
/// Given source file fileName, find the full load closure
/// Used from fsi.fs and fsc.fs, for #load and command line
let GetFullClosureOfScriptFiles
(
tcConfig:TcConfig,
files:(string*range) list,
tcConfig: TcConfig,
files: (string * range) list,
codeContext,
lexResourceManager: Lexhelp.LexResourceManager,
dependencyProvider
) =
let mainFile, _mainFileRange = List.last files
let closureSources = files |> List.collect (fun (fileName, m) -> ClosureSourceOfFilename(fileName, m,tcConfig.inputCodePage,true))
let closureFiles, tcConfig, packageReferences = FindClosureFiles(mainFile, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider)
let closureSources =
files
|> List.collect (fun (fileName, m) -> ClosureSourceOfFilename(fileName, m, tcConfig.inputCodePage, true))
let closureFiles, tcConfig, packageReferences =
FindClosureFiles(mainFile, closureSources, tcConfig, codeContext, lexResourceManager, dependencyProvider)
GetLoadClosure(mainFile, closureFiles, tcConfig, codeContext, packageReferences, [])
type LoadClosure with
/// Analyze a script text and find the closure of its references.
/// Used from FCS, when editing a script file.
///
@ -559,20 +745,34 @@ type LoadClosure with
) =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
ScriptPreprocessClosure.GetFullClosureOfScriptText
(legacyReferenceResolver, defaultFSharpBinariesDir, fileName, sourceText,
implicitDefines, useSimpleResolution, useFsiAuxLib, useSdkRefs, sdkDir, lexResourceManager,
applyCompilerOptions, assumeDotNetFramework, tryGetMetadataSnapshot, reduceMemoryUsage, dependencyProvider)
ScriptPreprocessClosure.GetFullClosureOfScriptText(
legacyReferenceResolver,
defaultFSharpBinariesDir,
fileName,
sourceText,
implicitDefines,
useSimpleResolution,
useFsiAuxLib,
useSdkRefs,
sdkDir,
lexResourceManager,
applyCompilerOptions,
assumeDotNetFramework,
tryGetMetadataSnapshot,
reduceMemoryUsage,
dependencyProvider
)
/// Analyze a set of script files and find the closure of their references.
static member ComputeClosureOfScriptFiles
(
tcConfig: TcConfig,
files:(string*range) list,
files: (string * range) list,
implicitDefines,
lexResourceManager: Lexhelp.LexResourceManager,
dependencyProvider
) =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse
ScriptPreprocessClosure.GetFullClosureOfScriptFiles (tcConfig, files, implicitDefines, lexResourceManager, dependencyProvider)
ScriptPreprocessClosure.GetFullClosureOfScriptFiles(tcConfig, files, implicitDefines, lexResourceManager, dependencyProvider)

Просмотреть файл

@ -25,7 +25,7 @@ open FSharp.Compiler.TypeProviders
#endif
// Handles TypeForwarding for the generated IL model
type TypeForwarding (tcImports: TcImports) =
type TypeForwarding(tcImports: TcImports) =
// Make a dictionary of ccus passed to the compiler will be looked up by qualified assembly name
let ccuThunksQualifiedName =
@ -40,18 +40,20 @@ type TypeForwarding (tcImports: TcImports) =
if String.IsNullOrEmpty(ccuThunk.AssemblyName) then
None
else
Some (ccuThunk.AssemblyName, ccuThunk))
Some(ccuThunk.AssemblyName, ccuThunk))
|> dict
let followTypeForwardForILTypeRef (tref:ILTypeRef) =
let followTypeForwardForILTypeRef (tref: ILTypeRef) =
let typename =
let parts = tref.FullName.Split([|'.'|])
let parts = tref.FullName.Split([| '.' |])
match parts.Length with
| 0 -> None
| 1 -> Some (Array.empty<string>, parts[0])
| n -> Some (parts[0..n-2], parts[n-1])
| 1 -> Some(Array.empty<string>, parts[0])
| n -> Some(parts[0 .. n - 2], parts[n - 1])
let scoref = tref.Scope
let scoref = tref.Scope
match scoref with
| ILScopeRef.Assembly scope ->
match ccuThunksQualifiedName.TryGetValue(scope.QualifiedName) with
@ -59,10 +61,12 @@ type TypeForwarding (tcImports: TcImports) =
match typename with
| Some (parts, name) ->
let forwarded = ccu.TryForward(parts, name)
let result =
match forwarded with
| Some fwd -> fwd.CompilationPath.ILScopeRef
| None -> scoref
result
| None -> scoref
| false, _ ->
@ -72,10 +76,12 @@ type TypeForwarding (tcImports: TcImports) =
match typename with
| Some (parts, name) ->
let forwarded = ccu.TryForward(parts, name)
let result =
match forwarded with
| Some fwd -> fwd.CompilationPath.ILScopeRef
| None -> scoref
result
| None -> scoref
| false, _ -> scoref
@ -84,55 +90,83 @@ type TypeForwarding (tcImports: TcImports) =
let typeForwardILTypeRef (tref: ILTypeRef) =
let scoref1 = tref.Scope
let scoref2 = followTypeForwardForILTypeRef tref
if scoref1 === scoref2 then tref
else ILTypeRef.Create (scoref2, tref.Enclosing, tref.Name)
if scoref1 === scoref2 then
tref
else
ILTypeRef.Create(scoref2, tref.Enclosing, tref.Name)
member _.TypeForwardILTypeRef tref = typeForwardILTypeRef tref
let debugStaticLinking = condition "FSHARP_DEBUG_STATIC_LINKING"
let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules: (CcuThunk option * ILModuleDef) list) =
let StaticLinkILModules
(
tcConfig: TcConfig,
ilGlobals,
tcImports,
ilxMainModule,
dependentILModules: (CcuThunk option * ILModuleDef) list
) =
if isNil dependentILModules then
ilxMainModule, id
else
let typeForwarding = TypeForwarding(tcImports)
// Check no dependent assemblies use quotations
let dependentCcuUsingQuotations = dependentILModules |> List.tryPick (function Some ccu, _ when ccu.UsesFSharp20PlusQuotations -> Some ccu | _ -> None)
let dependentCcuUsingQuotations =
dependentILModules
|> List.tryPick (function
| Some ccu, _ when ccu.UsesFSharp20PlusQuotations -> Some ccu
| _ -> None)
match dependentCcuUsingQuotations with
| Some ccu -> error(Error(FSComp.SR.fscQuotationLiteralsStaticLinking(ccu.AssemblyName), rangeStartup))
| Some ccu -> error (Error(FSComp.SR.fscQuotationLiteralsStaticLinking (ccu.AssemblyName), rangeStartup))
| None -> ()
// Check we're not static linking a .EXE
if dependentILModules |> List.exists (fun (_, x) -> not x.IsDLL) then
error(Error(FSComp.SR.fscStaticLinkingNoEXE(), rangeStartup))
if dependentILModules |> List.exists (fun (_, x) -> not x.IsDLL) then
error (Error(FSComp.SR.fscStaticLinkingNoEXE (), rangeStartup))
// Check we're not static linking something that is not pure IL
if dependentILModules |> List.exists (fun (_, x) -> not x.IsILOnly) then
error(Error(FSComp.SR.fscStaticLinkingNoMixedDLL(), rangeStartup))
if dependentILModules |> List.exists (fun (_, x) -> not x.IsILOnly) then
error (Error(FSComp.SR.fscStaticLinkingNoMixedDLL (), rangeStartup))
// The set of short names for the all dependent assemblies
let assems =
set [ for _, m in dependentILModules do
match m.Manifest with
| Some m -> yield m.Name
| _ -> () ]
set
[
for _, m in dependentILModules do
match m.Manifest with
| Some m -> m.Name
| _ -> ()
]
// A rewriter which rewrites scope references to things in dependent assemblies to be local references
let rewriteExternalRefsToLocalRefs x =
if assems.Contains (getNameOfScopeRef x) then ILScopeRef.Local else x
if assems.Contains(getNameOfScopeRef x) then
ILScopeRef.Local
else
x
let savedManifestAttrs =
[ for _, depILModule in dependentILModules do
match depILModule.Manifest with
| Some m ->
for ca in m.CustomAttrs.AsArray() do
if ca.Method.MethodRef.DeclaringTypeRef.FullName = typeof<CompilationMappingAttribute>.FullName then
yield ca
| _ -> () ]
[
for _, depILModule in dependentILModules do
match depILModule.Manifest with
| Some m ->
for ca in m.CustomAttrs.AsArray() do
if ca.Method.MethodRef.DeclaringTypeRef.FullName = typeof<CompilationMappingAttribute>.FullName then
ca
| _ -> ()
]
let savedResources =
let allResources = [ for ccu, m in dependentILModules do for r in m.Resources.AsList() do yield (ccu, r) ]
let allResources =
[
for ccu, m in dependentILModules do
for r in m.Resources.AsList() do
(ccu, r)
]
// Don't save interface, optimization or resource definitions for provider-generated assemblies.
// These are "fake".
let isProvided (ccu: CcuThunk option) =
@ -146,21 +180,29 @@ let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule,
#endif
// Save only the interface/optimization attributes of generated data
let intfDataResources, others = allResources |> List.partition (snd >> IsSignatureDataResource)
let intfDataResources =
[ for ccu, r in intfDataResources do
if tcConfig.GenerateSignatureData && not (isProvided ccu) then
yield r ]
let intfDataResources, others =
allResources |> List.partition (snd >> IsSignatureDataResource)
let intfDataResources =
[
for ccu, r in intfDataResources do
if tcConfig.GenerateSignatureData && not (isProvided ccu) then
r
]
let optDataResources, others =
others |> List.partition (snd >> IsOptimizationDataResource)
let optDataResources, others = others |> List.partition (snd >> IsOptimizationDataResource)
let optDataResources =
[ for ccu, r in optDataResources do
if tcConfig.GenerateOptimizationData && not (isProvided ccu) then
yield r ]
[
for ccu, r in optDataResources do
if tcConfig.GenerateOptimizationData && not (isProvided ccu) then
r
]
let otherResources = others |> List.map snd
let result = intfDataResources@optDataResources@otherResources
let result = intfDataResources @ optDataResources @ otherResources
result
let moduls = ilxMainModule :: (List.map snd dependentILModules)
@ -168,39 +210,62 @@ let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule,
let savedNativeResources =
[ //yield! ilxMainModule.NativeResources
for m in moduls do
yield! m.NativeResources ]
yield! m.NativeResources
]
let topTypeDefs, normalTypeDefs =
moduls
|> List.map (fun m -> m.TypeDefs.AsList() |> List.partition (fun td -> isTypeNameForGlobalFunctions td.Name))
|> List.map (fun m ->
m.TypeDefs.AsList()
|> List.partition (fun td -> isTypeNameForGlobalFunctions td.Name))
|> List.unzip
let topTypeDef =
let topTypeDefs = List.concat topTypeDefs
mkILTypeDefForGlobalFunctions ilGlobals
mkILTypeDefForGlobalFunctions
ilGlobals
(mkILMethods (topTypeDefs |> List.collect (fun td -> td.Methods.AsList())),
mkILFields (topTypeDefs |> List.collect (fun td -> td.Fields.AsList())))
mkILFields (topTypeDefs |> List.collect (fun td -> td.Fields.AsList())))
let oldManifest = ilxMainModule.ManifestOfAssembly
let newManifest =
{ oldManifest with
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (oldManifest.CustomAttrs.AsList() @ savedManifestAttrs))
}
let ilxMainModule =
let main =
{ ilxMainModule with
Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList() @ savedManifestAttrs)) })
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray() ])
Manifest = Some newManifest
CustomAttrsStored =
storeILCustomAttrs (
mkILCustomAttrs
[
for m in moduls do
yield! m.CustomAttrs.AsArray()
]
)
TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs)
Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList())
NativeResources = savedNativeResources }
NativeResources = savedNativeResources
}
Morphs.morphILTypeRefsInILModuleMemoized typeForwarding.TypeForwardILTypeRef main
ilxMainModule, rewriteExternalRefsToLocalRefs
[<NoEquality; NoComparison>]
type Node =
{ name: string
data: ILModuleDef
ccu: CcuThunk option
refs: ILReferences
mutable edges: Node list
mutable visited: bool }
{
name: string
data: ILModuleDef
ccu: CcuThunk option
refs: ILReferences
mutable edges: Node list
mutable visited: bool
}
// Find all IL modules that are to be statically linked given the static linking roots.
let FindDependentILModulesForStaticLinking (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlobals, ilxMainModule) =
@ -209,130 +274,217 @@ let FindDependentILModulesForStaticLinking (ctok, tcConfig: TcConfig, tcImports:
else
// Recursively find all referenced modules and add them to a module graph
let depModuleTable = HashMultiMap(0, HashIdentity.Structural)
let dummyEntry nm =
{ refs = emptyILRefs
name=nm
ccu=None
data=ilxMainModule // any old module
edges = []
visited = true }
let assumedIndependentSet = set [ "mscorlib"; "System"; "System.Core"; "System.Xml"; "Microsoft.Build.Framework"; "Microsoft.Build.Utilities"; "netstandard" ]
{
refs = emptyILRefs
name = nm
ccu = None
data = ilxMainModule // any old module
edges = []
visited = true
}
begin
let mutable remaining = (computeILRefs ilGlobals ilxMainModule).AssemblyReferences |> Array.toList
while not (isNil remaining) do
let ilAssemRef = List.head remaining
remaining <- List.tail remaining
if assumedIndependentSet.Contains ilAssemRef.Name || (ilAssemRef.PublicKey = Some ecmaPublicKey) then
depModuleTable[ilAssemRef.Name] <- dummyEntry ilAssemRef.Name
else
if not (depModuleTable.ContainsKey ilAssemRef.Name) then
match tcImports.TryFindDllInfo(ctok, rangeStartup, ilAssemRef.Name, lookupOnly=false) with
| Some dllInfo ->
let ccu =
match tcImports.FindCcuFromAssemblyRef (ctok, rangeStartup, ilAssemRef) with
| ResolvedCcu ccu -> Some ccu
| UnresolvedCcu(_ccuName) -> None
let assumedIndependentSet =
set
[
"mscorlib"
"System"
"System.Core"
"System.Xml"
"Microsoft.Build.Framework"
"Microsoft.Build.Utilities"
"netstandard"
]
let fileName = dllInfo.FileName
let modul =
let pdbDirPathOption =
// We open the pdb file if one exists parallel to the binary we
// are reading, so that --standalone will preserve debug information.
if tcConfig.openDebugInformationForLaterStaticLinking then
let pdbDir = (try FileSystem.GetDirectoryNameShim fileName with _ -> ".")
let pdbFile = (try FileSystemUtils.chopExtension fileName with _ -> fileName)+".pdb"
if FileSystem.FileExistsShim pdbFile then
Some pdbDir
else
None
else
None
let mutable remaining =
(computeILRefs ilGlobals ilxMainModule).AssemblyReferences |> Array.toList
let opts : ILReaderOptions =
{ metadataOnly = MetadataOnlyFlag.No // turn this off here as we need the actual IL code
reduceMemoryUsage = tcConfig.reduceMemoryUsage
pdbDirPath = pdbDirPathOption
tryGetMetadataSnapshot = (fun _ -> None) }
while not (isNil remaining) do
let ilAssemRef = List.head remaining
remaining <- List.tail remaining
let reader = OpenILModuleReader dllInfo.FileName opts
reader.ILModuleDef
if assumedIndependentSet.Contains ilAssemRef.Name
|| (ilAssemRef.PublicKey = Some ecmaPublicKey) then
depModuleTable[ilAssemRef.Name] <- dummyEntry ilAssemRef.Name
else if not (depModuleTable.ContainsKey ilAssemRef.Name) then
match tcImports.TryFindDllInfo(ctok, rangeStartup, ilAssemRef.Name, lookupOnly = false) with
| Some dllInfo ->
let ccu =
match tcImports.FindCcuFromAssemblyRef(ctok, rangeStartup, ilAssemRef) with
| ResolvedCcu ccu -> Some ccu
| UnresolvedCcu (_ccuName) -> None
let refs =
if ilAssemRef.Name = GetFSharpCoreLibraryName() then
emptyILRefs
elif not modul.IsILOnly then
warning(Error(FSComp.SR.fscIgnoringMixedWhenLinking ilAssemRef.Name, rangeStartup))
emptyILRefs
let fileName = dllInfo.FileName
let modul =
let pdbDirPathOption =
// We open the pdb file if one exists parallel to the binary we
// are reading, so that --standalone will preserve debug information.
if tcConfig.openDebugInformationForLaterStaticLinking then
let pdbDir =
(try
FileSystem.GetDirectoryNameShim fileName
with _ ->
".")
let pdbFile =
(try
FileSystemUtils.chopExtension fileName
with _ ->
fileName)
+ ".pdb"
if FileSystem.FileExistsShim pdbFile then
Some pdbDir
else
{ AssemblyReferences = dllInfo.ILAssemblyRefs |> List.toArray
ModuleReferences = [| |]
TypeReferences = [| |]
MethodReferences = [| |]
FieldReferences = [||] }
None
else
None
depModuleTable[ilAssemRef.Name] <-
{ refs=refs
name=ilAssemRef.Name
ccu=ccu
data=modul
edges = []
visited = false }
let opts: ILReaderOptions =
{
metadataOnly = MetadataOnlyFlag.No // turn this off here as we need the actual IL code
reduceMemoryUsage = tcConfig.reduceMemoryUsage
pdbDirPath = pdbDirPathOption
tryGetMetadataSnapshot = (fun _ -> None)
}
// Push the new work items
remaining <- Array.toList refs.AssemblyReferences @ remaining
let reader = OpenILModuleReader dllInfo.FileName opts
reader.ILModuleDef
| None ->
warning(Error(FSComp.SR.fscAssumeStaticLinkContainsNoDependencies(ilAssemRef.Name), rangeStartup))
depModuleTable[ilAssemRef.Name] <- dummyEntry ilAssemRef.Name
done
end
let refs =
if ilAssemRef.Name = GetFSharpCoreLibraryName() then
emptyILRefs
elif not modul.IsILOnly then
warning (Error(FSComp.SR.fscIgnoringMixedWhenLinking ilAssemRef.Name, rangeStartup))
emptyILRefs
else
{
AssemblyReferences = dllInfo.ILAssemblyRefs |> List.toArray
ModuleReferences = [||]
TypeReferences = [||]
MethodReferences = [||]
FieldReferences = [||]
}
depModuleTable[ilAssemRef.Name] <-
{
refs = refs
name = ilAssemRef.Name
ccu = ccu
data = modul
edges = []
visited = false
}
// Push the new work items
remaining <- Array.toList refs.AssemblyReferences @ remaining
| None ->
warning (Error(FSComp.SR.fscAssumeStaticLinkContainsNoDependencies (ilAssemRef.Name), rangeStartup))
depModuleTable[ilAssemRef.Name] <- dummyEntry ilAssemRef.Name
ReportTime tcConfig "Find dependencies"
// Add edges from modules to the modules that depend on them
for KeyValue(_, n) in depModuleTable do
for KeyValue (_, n) in depModuleTable do
for aref in n.refs.AssemblyReferences do
let n2 = depModuleTable[aref.Name]
n2.edges <- n :: n2.edges
// Find everything that depends on FSharp.Core
let roots =
[ if tcConfig.standalone && depModuleTable.ContainsKey (GetFSharpCoreLibraryName()) then
yield depModuleTable[GetFSharpCoreLibraryName()]
for n in tcConfig.extraStaticLinkRoots do
match depModuleTable.TryFind n with
| Some x -> yield x
| None -> error(Error(FSComp.SR.fscAssemblyNotFoundInDependencySet n, rangeStartup))
[
if tcConfig.standalone && depModuleTable.ContainsKey(GetFSharpCoreLibraryName()) then
depModuleTable[GetFSharpCoreLibraryName()]
for n in tcConfig.extraStaticLinkRoots do
match depModuleTable.TryFind n with
| Some x -> x
| None -> error (Error(FSComp.SR.fscAssemblyNotFoundInDependencySet n, rangeStartup))
]
let mutable remaining = roots
[ while not (isNil remaining) do
let n = List.head remaining
remaining <- List.tail remaining
if not n.visited then
n.visited <- true
remaining <- n.edges @ remaining
yield (n.ccu, n.data) ]
[
while not (isNil remaining) do
let n = List.head remaining
remaining <- List.tail remaining
if not n.visited then
n.visited <- true
remaining <- n.edges @ remaining
(n.ccu, n.data)
]
// Add all provider-generated assemblies into the static linking set
let FindProviderGeneratedILModules (ctok, tcImports: TcImports, providerGeneratedAssemblies: (ImportedBinary * _) list) =
[ for importedBinary, provAssemStaticLinkInfo in providerGeneratedAssemblies do
let ilAssemRef =
match importedBinary.ILScopeRef with
| ILScopeRef.Assembly aref -> aref
| _ -> failwith "Invalid ILScopeRef, expected ILScopeRef.Assembly"
if debugStaticLinking then printfn "adding provider-generated assembly '%s' into static linking set" ilAssemRef.Name
match tcImports.TryFindDllInfo(ctok, rangeStartup, ilAssemRef.Name, lookupOnly=false) with
| Some dllInfo ->
let ccu =
match tcImports.FindCcuFromAssemblyRef (ctok, rangeStartup, ilAssemRef) with
| ResolvedCcu ccu -> Some ccu
| UnresolvedCcu(_ccuName) -> None
[
for importedBinary, provAssemStaticLinkInfo in providerGeneratedAssemblies do
let ilAssemRef =
match importedBinary.ILScopeRef with
| ILScopeRef.Assembly aref -> aref
| _ -> failwith "Invalid ILScopeRef, expected ILScopeRef.Assembly"
let modul = dllInfo.RawMetadata.TryGetILModuleDef().Value
yield (ccu, dllInfo.ILScopeRef, modul), (ilAssemRef.Name, provAssemStaticLinkInfo)
| None -> () ]
if debugStaticLinking then
printfn "adding provider-generated assembly '%s' into static linking set" ilAssemRef.Name
match tcImports.TryFindDllInfo(ctok, rangeStartup, ilAssemRef.Name, lookupOnly = false) with
| Some dllInfo ->
let ccu =
match tcImports.FindCcuFromAssemblyRef(ctok, rangeStartup, ilAssemRef) with
| ResolvedCcu ccu -> Some ccu
| UnresolvedCcu (_ccuName) -> None
let modul = dllInfo.RawMetadata.TryGetILModuleDef().Value
(ccu, dllInfo.ILScopeRef, modul), (ilAssemRef.Name, provAssemStaticLinkInfo)
| None -> ()
]
/// Split the list into left, middle and right parts at the first element satisfying 'p'. If no element matches return
/// 'None' for the middle part.
let trySplitFind p xs =
let rec loop xs acc =
match xs with
| [] -> List.rev acc, None, []
| h :: t -> if p h then List.rev acc, Some h, t else loop t (h :: acc)
loop xs []
/// Implant the (nested) type definition 'td' at path 'enc' in 'tdefs'.
let rec implantTypeDef ilGlobals isNested (tdefs: ILTypeDefs) (enc: string list) (td: ILTypeDef) =
match enc with
| [] -> addILTypeDef td tdefs
| h :: t ->
let tdefs = tdefs.AsList()
let ltdefs, htd, rtdefs =
match tdefs |> trySplitFind (fun td -> td.Name = h) with
| ltdefs, None, rtdefs ->
let access =
if isNested then
ILTypeDefAccess.Nested ILMemberAccess.Public
else
ILTypeDefAccess.Public
let fresh =
mkILSimpleClass
ilGlobals
(h,
access,
emptyILMethods,
emptyILFields,
emptyILTypeDefs,
emptyILProperties,
emptyILEvents,
emptyILCustomAttrs,
ILTypeInit.OnAny)
(ltdefs, fresh, rtdefs)
| ltdefs, Some htd, rtdefs -> (ltdefs, htd, rtdefs)
let htd = htd.With(nestedTypes = implantTypeDef ilGlobals true htd.NestedTypes t td)
mkILTypeDefs (ltdefs @ [ htd ] @ rtdefs)
// Compute a static linker. This only captures tcImports (a large data structure) if
// static linking is enabled. Normally this is not the case, which lets us collect tcImports
@ -343,181 +495,231 @@ let StaticLink (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlo
let providerGeneratedAssemblies =
[ // Add all EST-generated assemblies into the static linking set
for KeyValue(_, importedBinary: ImportedBinary) in tcImports.DllTable do
for KeyValue (_, importedBinary: ImportedBinary) in tcImports.DllTable do
if importedBinary.IsProviderGenerated then
match importedBinary.ProviderGeneratedStaticLinkMap with
| None -> ()
| Some provAssemStaticLinkInfo -> yield (importedBinary, provAssemStaticLinkInfo) ]
| Some provAssemStaticLinkInfo -> (importedBinary, provAssemStaticLinkInfo)
]
#endif
if not tcConfig.standalone && tcConfig.extraStaticLinkRoots.IsEmpty
if not tcConfig.standalone
&& tcConfig.extraStaticLinkRoots.IsEmpty
#if !NO_TYPEPROVIDERS
&& providerGeneratedAssemblies.IsEmpty
&& providerGeneratedAssemblies.IsEmpty
#endif
then
then
id
else
(fun ilxMainModule ->
(fun ilxMainModule ->
match tcConfig.emitMetadataAssembly with
| MetadataAssemblyGeneration.None -> ()
| _ ->
error(Error(FSComp.SR.optsInvalidRefAssembly(), rangeCmdArgs))
| _ -> error (Error(FSComp.SR.optsInvalidRefAssembly (), rangeCmdArgs))
ReportTime tcConfig "Find assembly references"
let dependentILModules = FindDependentILModulesForStaticLinking (ctok, tcConfig, tcImports, ilGlobals, ilxMainModule)
let dependentILModules =
FindDependentILModulesForStaticLinking(ctok, tcConfig, tcImports, ilGlobals, ilxMainModule)
ReportTime tcConfig "Static link"
#if !NO_TYPEPROVIDERS
Morphs.enableMorphCustomAttributeData()
let providerGeneratedILModules = FindProviderGeneratedILModules (ctok, tcImports, providerGeneratedAssemblies)
Morphs.enableMorphCustomAttributeData ()
let providerGeneratedILModules =
FindProviderGeneratedILModules(ctok, tcImports, providerGeneratedAssemblies)
// Transform the ILTypeRefs references in the IL of all provider-generated assemblies so that the references
// are now local.
let providerGeneratedILModules =
providerGeneratedILModules |> List.map (fun ((ccu, ilOrigScopeRef, ilModule), (_, localProvAssemStaticLinkInfo)) ->
providerGeneratedILModules
|> List.map (fun ((ccu, ilOrigScopeRef, ilModule), (_, localProvAssemStaticLinkInfo)) ->
let ilAssemStaticLinkMap =
dict [ for _, (_, provAssemStaticLinkInfo) in providerGeneratedILModules do
for KeyValue(k, v) in provAssemStaticLinkInfo.ILTypeMap do
yield (k, v)
for KeyValue(k, v) in localProvAssemStaticLinkInfo.ILTypeMap do
yield (ILTypeRef.Create(ILScopeRef.Local, k.Enclosing, k.Name), v) ]
dict
[
for _, (_, provAssemStaticLinkInfo) in providerGeneratedILModules do
for KeyValue (k, v) in provAssemStaticLinkInfo.ILTypeMap do
(k, v)
for KeyValue (k, v) in localProvAssemStaticLinkInfo.ILTypeMap do
(ILTypeRef.Create(ILScopeRef.Local, k.Enclosing, k.Name), v)
]
let ilModule =
ilModule |> Morphs.morphILTypeRefsInILModuleMemoized (fun tref ->
if debugStaticLinking then printfn "deciding whether to rewrite type ref %A" tref.QualifiedName
let ok, v = ilAssemStaticLinkMap.TryGetValue tref
if ok then
if debugStaticLinking then printfn "rewriting type ref %A to %A" tref.QualifiedName v.QualifiedName
v
else
tref)
ilModule
|> Morphs.morphILTypeRefsInILModuleMemoized (fun tref ->
if debugStaticLinking then
printfn "deciding whether to rewrite type ref %A" tref.QualifiedName
match ilAssemStaticLinkMap.TryGetValue tref with
| true, v ->
if debugStaticLinking then
printfn "rewriting type ref %A to %A" tref.QualifiedName v.QualifiedName
v
| _ -> tref)
(ccu, ilOrigScopeRef, ilModule))
// Relocate provider generated type definitions into the expected shape for the [<Generate>] declarations in an assembly
let providerGeneratedILModules, ilxMainModule =
// Build a dictionary of all remapped IL type defs
let ilOrigTyRefsForProviderGeneratedTypesToRelocate =
let rec walk acc (ProviderGeneratedType(ilOrigTyRef, _, xs) as node) = List.fold walk ((ilOrigTyRef, node) :: acc) xs
dict (Seq.fold walk [] tcImports.ProviderGeneratedTypeRoots)
// Build a dictionary of all remapped IL type defs
let ilOrigTyRefsForProviderGeneratedTypesToRelocate =
let rec walk acc (ProviderGeneratedType (ilOrigTyRef, _, xs) as node) =
List.fold walk ((ilOrigTyRef, node) :: acc) xs
// Build a dictionary of all IL type defs, mapping ilOrigTyRef --> ilTypeDef
let allTypeDefsInProviderGeneratedAssemblies =
let rec loop ilOrigTyRef (ilTypeDef: ILTypeDef) =
seq { yield (ilOrigTyRef, ilTypeDef)
for ntdef in ilTypeDef.NestedTypes do
yield! loop (mkILTyRefInTyRef (ilOrigTyRef, ntdef.Name)) ntdef }
dict [
for _ccu, ilOrigScopeRef, ilModule in providerGeneratedILModules do
for td in ilModule.TypeDefs do
yield! loop (mkILTyRef (ilOrigScopeRef, td.Name)) td ]
dict (Seq.fold walk [] tcImports.ProviderGeneratedTypeRoots)
// Build a dictionary of all IL type defs, mapping ilOrigTyRef --> ilTypeDef
let allTypeDefsInProviderGeneratedAssemblies =
let rec loop ilOrigTyRef (ilTypeDef: ILTypeDef) =
seq {
(ilOrigTyRef, ilTypeDef)
// Debugging output
if debugStaticLinking then
for ProviderGeneratedType(ilOrigTyRef, _, _) in tcImports.ProviderGeneratedTypeRoots do
printfn "Have [<Generate>] root '%s'" ilOrigTyRef.QualifiedName
for ntdef in ilTypeDef.NestedTypes do
yield! loop (mkILTyRefInTyRef (ilOrigTyRef, ntdef.Name)) ntdef
}
// Build the ILTypeDefs for generated types, starting with the roots
let generatedILTypeDefs =
let rec buildRelocatedGeneratedType (ProviderGeneratedType(ilOrigTyRef, ilTgtTyRef, ch)) =
let isNested = not (isNil ilTgtTyRef.Enclosing)
match allTypeDefsInProviderGeneratedAssemblies.TryGetValue ilOrigTyRef with
| true, ilOrigTypeDef ->
if debugStaticLinking then printfn "Relocating %s to %s " ilOrigTyRef.QualifiedName ilTgtTyRef.QualifiedName
let ilOrigTypeDef =
dict
[
for _ccu, ilOrigScopeRef, ilModule in providerGeneratedILModules do
for td in ilModule.TypeDefs do
yield! loop (mkILTyRef (ilOrigScopeRef, td.Name)) td
]
// Debugging output
if debugStaticLinking then
for ProviderGeneratedType (ilOrigTyRef, _, _) in tcImports.ProviderGeneratedTypeRoots do
printfn "Have [<Generate>] root '%s'" ilOrigTyRef.QualifiedName
// Build the ILTypeDefs for generated types, starting with the roots
let generatedILTypeDefs =
let rec buildRelocatedGeneratedType (ProviderGeneratedType (ilOrigTyRef, ilTgtTyRef, ch)) =
let isNested = not (isNil ilTgtTyRef.Enclosing)
match allTypeDefsInProviderGeneratedAssemblies.TryGetValue ilOrigTyRef with
| true, ilOrigTypeDef ->
if debugStaticLinking then
printfn "Relocating %s to %s " ilOrigTyRef.QualifiedName ilTgtTyRef.QualifiedName
let ilOrigTypeDef =
if isNested then
ilOrigTypeDef.WithAccess(
match ilOrigTypeDef.Access with
| ILTypeDefAccess.Public -> ILTypeDefAccess.Nested ILMemberAccess.Public
| ILTypeDefAccess.Private -> ILTypeDefAccess.Nested ILMemberAccess.Private
| _ -> ilOrigTypeDef.Access
)
else
ilOrigTypeDef
.WithAccess(match ilOrigTypeDef.Access with
| ILTypeDefAccess.Public -> ILTypeDefAccess.Nested ILMemberAccess.Public
| ILTypeDefAccess.Private -> ILTypeDefAccess.Nested ILMemberAccess.Private
| _ -> ilOrigTypeDef.Access)
else ilOrigTypeDef
ilOrigTypeDef.With(name = ilTgtTyRef.Name,
nestedTypes = mkILTypeDefs (List.map buildRelocatedGeneratedType ch))
| _ ->
// If there is no matching IL type definition, then make a simple container class
if debugStaticLinking then
printfn "Generating simple class '%s' because we didn't find an original type '%s' in a provider generated assembly"
ilTgtTyRef.QualifiedName ilOrigTyRef.QualifiedName
let access = (if isNested then ILTypeDefAccess.Nested ILMemberAccess.Public else ILTypeDefAccess.Public)
let tdefs = mkILTypeDefs (List.map buildRelocatedGeneratedType ch)
mkILSimpleClass ilGlobals (ilTgtTyRef.Name, access, emptyILMethods, emptyILFields, tdefs, emptyILProperties, emptyILEvents, emptyILCustomAttrs, ILTypeInit.OnAny)
ilOrigTypeDef.With(name = ilTgtTyRef.Name, nestedTypes = mkILTypeDefs (List.map buildRelocatedGeneratedType ch))
| _ ->
// If there is no matching IL type definition, then make a simple container class
if debugStaticLinking then
printfn
"Generating simple class '%s' because we didn't find an original type '%s' in a provider generated assembly"
ilTgtTyRef.QualifiedName
ilOrigTyRef.QualifiedName
[ for ProviderGeneratedType(_, ilTgtTyRef, _) as node in tcImports.ProviderGeneratedTypeRoots do
yield (ilTgtTyRef, buildRelocatedGeneratedType node) ]
let access =
(if isNested then
ILTypeDefAccess.Nested ILMemberAccess.Public
else
ILTypeDefAccess.Public)
// Implant all the generated type definitions into the ilxMainModule (generating a new ilxMainModule)
let ilxMainModule =
let tdefs = mkILTypeDefs (List.map buildRelocatedGeneratedType ch)
/// Split the list into left, middle and right parts at the first element satisfying 'p'. If no element matches return
/// 'None' for the middle part.
let trySplitFind p xs =
let rec loop xs acc =
match xs with
| [] -> List.rev acc, None, []
| h :: t -> if p h then List.rev acc, Some h, t else loop t (h :: acc)
loop xs []
mkILSimpleClass
ilGlobals
(ilTgtTyRef.Name,
access,
emptyILMethods,
emptyILFields,
tdefs,
emptyILProperties,
emptyILEvents,
emptyILCustomAttrs,
ILTypeInit.OnAny)
/// Implant the (nested) type definition 'td' at path 'enc' in 'tdefs'.
let rec implantTypeDef isNested (tdefs: ILTypeDefs) (enc: string list) (td: ILTypeDef) =
match enc with
| [] -> addILTypeDef td tdefs
| h :: t ->
let tdefs = tdefs.AsList()
let ltdefs, htd, rtdefs =
match tdefs |> trySplitFind (fun td -> td.Name = h) with
| ltdefs, None, rtdefs ->
let access = if isNested then ILTypeDefAccess.Nested ILMemberAccess.Public else ILTypeDefAccess.Public
let fresh = mkILSimpleClass ilGlobals (h, access, emptyILMethods, emptyILFields, emptyILTypeDefs, emptyILProperties, emptyILEvents, emptyILCustomAttrs, ILTypeInit.OnAny)
(ltdefs, fresh, rtdefs)
| ltdefs, Some htd, rtdefs ->
(ltdefs, htd, rtdefs)
let htd = htd.With(nestedTypes = implantTypeDef true htd.NestedTypes t td)
mkILTypeDefs (ltdefs @ [htd] @ rtdefs)
[
for ProviderGeneratedType (_, ilTgtTyRef, _) as node in tcImports.ProviderGeneratedTypeRoots do
(ilTgtTyRef, buildRelocatedGeneratedType node)
]
let newTypeDefs =
(ilxMainModule.TypeDefs, generatedILTypeDefs) ||> List.fold (fun acc (ilTgtTyRef, td) ->
if debugStaticLinking then printfn "implanting '%s' at '%s'" td.Name ilTgtTyRef.QualifiedName
implantTypeDef false acc ilTgtTyRef.Enclosing td)
{ ilxMainModule with TypeDefs = newTypeDefs }
// Implant all the generated type definitions into the ilxMainModule (generating a new ilxMainModule)
let ilxMainModule =
// Remove any ILTypeDefs from the provider generated modules if they have been relocated because of a [<Generate>] declaration.
let providerGeneratedILModules =
providerGeneratedILModules |> List.map (fun (ccu, ilOrigScopeRef, ilModule) ->
let ilTypeDefsAfterRemovingRelocatedTypes =
let rec rw enc (tdefs: ILTypeDefs) =
mkILTypeDefs
[ for tdef in tdefs do
let ilOrigTyRef = mkILNestedTyRef (ilOrigScopeRef, enc, tdef.Name)
if not (ilOrigTyRefsForProviderGeneratedTypesToRelocate.ContainsKey ilOrigTyRef) then
if debugStaticLinking then printfn "Keep provided type %s in place because it wasn't relocated" ilOrigTyRef.QualifiedName
yield tdef.With(nestedTypes = rw (enc@[tdef.Name]) tdef.NestedTypes) ]
rw [] ilModule.TypeDefs
(ccu, { ilModule with TypeDefs = ilTypeDefsAfterRemovingRelocatedTypes }))
let newTypeDefs =
(ilxMainModule.TypeDefs, generatedILTypeDefs)
||> List.fold (fun acc (ilTgtTyRef, td) ->
if debugStaticLinking then
printfn "implanting '%s' at '%s'" td.Name ilTgtTyRef.QualifiedName
providerGeneratedILModules, ilxMainModule
implantTypeDef ilGlobals false acc ilTgtTyRef.Enclosing td)
Morphs.disableMorphCustomAttributeData()
{ ilxMainModule with
TypeDefs = newTypeDefs
}
// Remove any ILTypeDefs from the provider generated modules if they have been relocated because of a [<Generate>] declaration.
let providerGeneratedILModules =
providerGeneratedILModules
|> List.map (fun (ccu, ilOrigScopeRef, ilModule) ->
let ilTypeDefsAfterRemovingRelocatedTypes =
let rec rw enc (tdefs: ILTypeDefs) =
mkILTypeDefs
[
for tdef in tdefs do
let ilOrigTyRef = mkILNestedTyRef (ilOrigScopeRef, enc, tdef.Name)
if not (ilOrigTyRefsForProviderGeneratedTypesToRelocate.ContainsKey ilOrigTyRef) then
if debugStaticLinking then
printfn
"Keep provided type %s in place because it wasn't relocated"
ilOrigTyRef.QualifiedName
tdef.With(nestedTypes = rw (enc @ [ tdef.Name ]) tdef.NestedTypes)
]
rw [] ilModule.TypeDefs
(ccu,
{ ilModule with
TypeDefs = ilTypeDefsAfterRemovingRelocatedTypes
}))
providerGeneratedILModules, ilxMainModule
Morphs.disableMorphCustomAttributeData ()
#else
let providerGeneratedILModules = []
#endif
// Glue all this stuff into ilxMainModule
let ilxMainModule, rewriteExternalRefsToLocalRefs =
StaticLinkILModules (tcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules @ providerGeneratedILModules)
StaticLinkILModules(tcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules @ providerGeneratedILModules)
// Rewrite type and assembly references
let ilxMainModule =
let isMscorlib = ilGlobals.primaryAssemblyName = PrimaryAssembly.Mscorlib.Name
let validateTargetPlatform (scopeRef : ILScopeRef) =
let name = getNameOfScopeRef scopeRef
if (not isMscorlib && name = PrimaryAssembly.Mscorlib.Name) then
error (Error(FSComp.SR.fscStaticLinkingNoProfileMismatches(), rangeCmdArgs))
scopeRef
let rewriteAssemblyRefsToMatchLibraries = NormalizeAssemblyRefs (ctok, ilGlobals, tcImports)
Morphs.morphILTypeRefsInILModuleMemoized (Morphs.morphILScopeRefsInILTypeRef (validateTargetPlatform >> rewriteExternalRefsToLocalRefs >> rewriteAssemblyRefsToMatchLibraries)) ilxMainModule
let isMscorlib = ilGlobals.primaryAssemblyName = PrimaryAssembly.Mscorlib.Name
let validateTargetPlatform (scopeRef: ILScopeRef) =
let name = getNameOfScopeRef scopeRef
if (not isMscorlib && name = PrimaryAssembly.Mscorlib.Name) then
error (Error(FSComp.SR.fscStaticLinkingNoProfileMismatches (), rangeCmdArgs))
scopeRef
let rewriteAssemblyRefsToMatchLibraries =
NormalizeAssemblyRefs(ctok, ilGlobals, tcImports)
Morphs.morphILTypeRefsInILModuleMemoized
(Morphs.morphILScopeRefsInILTypeRef (
validateTargetPlatform
>> rewriteExternalRefsToLocalRefs
>> rewriteAssemblyRefsToMatchLibraries
))
ilxMainModule
ilxMainModule)

Просмотреть файл

@ -25,31 +25,31 @@ module XmlDocWriter =
let doTyconSig ptext (tc: Tycon) =
if hasDoc tc.XmlDoc then
tc.XmlDocSig <- XmlDocSigOfTycon [ptext; tc.CompiledName]
tc.XmlDocSig <- XmlDocSigOfTycon [ ptext; tc.CompiledName ]
for vref in tc.MembersOfFSharpTyconSorted do
doValSig ptext vref.Deref
for uc in tc.UnionCasesArray do
if hasDoc uc.XmlDoc then
uc.XmlDocSig <- XmlDocSigOfUnionCase [ptext; tc.CompiledName; uc.Id.idText]
uc.XmlDocSig <- XmlDocSigOfUnionCase [ ptext; tc.CompiledName; uc.Id.idText ]
for field in uc.RecdFieldsArray do
if hasDoc field.XmlDoc then
// union case fields are exposed as properties
field.XmlDocSig <- XmlDocSigOfProperty [ptext; tc.CompiledName; uc.Id.idText; field.Id.idText]
field.XmlDocSig <- XmlDocSigOfProperty [ ptext; tc.CompiledName; uc.Id.idText; field.Id.idText ]
for rf in tc.AllFieldsArray do
if hasDoc rf.XmlDoc then
rf.XmlDocSig <-
if tc.IsRecordTycon && not rf.IsStatic then
// represents a record field, which is exposed as a property
XmlDocSigOfProperty [ptext; tc.CompiledName; rf.Id.idText]
XmlDocSigOfProperty [ ptext; tc.CompiledName; rf.Id.idText ]
else
XmlDocSigOfField [ptext; tc.CompiledName; rf.Id.idText]
XmlDocSigOfField [ ptext; tc.CompiledName; rf.Id.idText ]
let doModuleMemberSig path (m: ModuleOrNamespace) =
m.XmlDocSig <- XmlDocSigOfSubModul [path]
m.XmlDocSig <- XmlDocSigOfSubModul [ path ]
let rec doModuleSig path (mspec: ModuleOrNamespace) =
let mtype = mspec.ModuleOrNamespaceType
@ -59,17 +59,16 @@ module XmlDocWriter =
match path with
| None -> Some ""
| Some "" -> Some mspec.LogicalName
| Some p -> Some (p+"."+mspec.LogicalName)
| Some p -> Some(p + "." + mspec.LogicalName)
let ptext = defaultArg path ""
if mspec.IsModule then
doModuleMemberSig ptext mspec
if mspec.IsModule then doModuleMemberSig ptext mspec
let vals =
mtype.AllValsAndMembers
|> Seq.toList
|> List.filter (fun x -> not x.IsCompilerGenerated)
|> List.filter (fun x -> not x.IsCompilerGenerated)
|> List.filter (fun x -> x.MemberInfo.IsNone || x.IsExtensionMember)
mtype.ModuleAndNamespaceDefinitions |> List.iter (doModuleSig path)
@ -80,8 +79,8 @@ module XmlDocWriter =
doModuleSig None generatedCcu.Contents
let WriteXmlDocFile (g, assemblyName, generatedCcu: CcuThunk, xmlFile) =
if not (FileSystemUtils.checkSuffix xmlFile "xml" ) then
error(Error(FSComp.SR.docfileNoXmlSuffix(), Range.rangeStartup))
if not (FileSystemUtils.checkSuffix xmlFile "xml") then
error (Error(FSComp.SR.docfileNoXmlSuffix (), Range.rangeStartup))
let mutable members = []
@ -90,18 +89,17 @@ module XmlDocWriter =
let doc = xmlDoc.GetXmlText()
members <- (id, doc) :: members
let doVal (v: Val) =
addMember v.XmlDocSig v.XmlDoc
let doVal (v: Val) = addMember v.XmlDocSig v.XmlDoc
let doField (rf: RecdField) =
addMember rf.XmlDocSig rf.XmlDoc
let doField (rf: RecdField) = addMember rf.XmlDocSig rf.XmlDoc
let doUnionCase (uc: UnionCase) =
addMember uc.XmlDocSig uc.XmlDoc
for field in uc.RecdFieldsArray do
addMember field.XmlDocSig field.XmlDoc
let doTycon (tc: Tycon) =
let doTycon (tc: Tycon) =
addMember tc.XmlDocSig tc.XmlDoc
for vref in tc.MembersOfFSharpTyconSorted do
@ -114,18 +112,16 @@ module XmlDocWriter =
for rf in tc.AllFieldsArray do
doField rf
let modulMember (m: ModuleOrNamespace) =
addMember m.XmlDocSig m.XmlDoc
let modulMember (m: ModuleOrNamespace) = addMember m.XmlDocSig m.XmlDoc
let rec doModule (mspec: ModuleOrNamespace) =
let mtype = mspec.ModuleOrNamespaceType
if mspec.IsModule then
modulMember mspec
if mspec.IsModule then modulMember mspec
let vals =
mtype.AllValsAndMembers
|> Seq.toList
|> List.filter (fun x -> not x.IsCompilerGenerated)
|> List.filter (fun x -> not x.IsCompilerGenerated)
|> List.filter (fun x -> x.MemberInfo.IsNone || x.IsExtensionMember)
List.iter doModule mtype.ModuleAndNamespaceDefinitions
@ -143,9 +139,9 @@ module XmlDocWriter =
fprintfn os "<members>"
for (nm, doc) in members do
fprintfn os "<member name=\"%s\">" nm
fprintfn os "%s" doc
fprintfn os "</member>"
fprintfn os "<member name=\"%s\">" nm
fprintfn os "%s" doc
fprintfn os "</member>"
fprintfn os "</members>"
fprintfn os "</doc>"

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1906,7 +1906,8 @@ type internal FsiDynamicCompiler(
match fsiOptions.DependencyProvider.TryFindDependencyManagerByKey(tcConfigB.compilerToolPaths, getOutputDir tcConfigB, reportError m, packageManagerKey) with
| Null ->
errorR(Error(fsiOptions.DependencyProvider.CreatePackageManagerUnknownError(tcConfigB.compilerToolPaths, outputDir, packageManagerKey, reportError m), m))
let err = fsiOptions.DependencyProvider.CreatePackageManagerUnknownError(tcConfigB.compilerToolPaths, outputDir, packageManagerKey, reportError m)
errorR(Error(err, m))
istate
| NonNull dependencyManager ->
let directive d =

Просмотреть файл

@ -80,10 +80,7 @@ let jaro (s1: string) (s2: string) =
/ 3.0
// This is for cases where |s1|, |s2| or m are zero
if Double.IsNaN result then
0.0
else
result
if Double.IsNaN result then 0.0 else result
/// Calculates the Jaro-Winkler edit distance between two strings.
/// The edit distance is a metric that allows to measure the amount of similarity between two strings.

Просмотреть файл

@ -127,8 +127,7 @@ type ByteArrayMemory(bytes: byte[], offset, length) =
ByteArrayMemory(Array.empty, 0, 0) :> ByteMemory
override _.CopyTo stream =
if length > 0 then
stream.Write(bytes, offset, length)
if length > 0 then stream.Write(bytes, offset, length)
override _.Copy(srcOffset, dest, destOffset, count) =
checkCount count
@ -381,12 +380,11 @@ module MemoryMappedFileExtensions =
use stream = mmf.CreateViewStream(0L, length, MemoryMappedFileAccess.ReadWrite)
copyTo stream
Some mmf
with
| _ ->
with _ ->
mmf.Dispose()
None
with
| _ -> None
with _ ->
None
type MemoryMappedFile with
@ -414,8 +412,7 @@ module internal FileSystemUtils =
let checkSuffix (path: string) (suffix: string) = path.EndsWithOrdinalIgnoreCase(suffix)
let hasExtensionWithValidate (validate: bool) (s: string) =
if validate then
(checkPathForIllegalChars s)
if validate then (checkPathForIllegalChars s)
let sLen = s.Length
@ -440,8 +437,7 @@ module internal FileSystemUtils =
Path.GetFileName(path)
let fileNameWithoutExtensionWithValidate (validate: bool) path =
if validate then
checkPathForIllegalChars path
if validate then checkPathForIllegalChars path
Path.GetFileNameWithoutExtension(path)
@ -567,8 +563,7 @@ type DefaultFileSystem() as this =
let stream = new MemoryMappedStream(mmf, length)
if not stream.CanRead then
invalidOp "Cannot read file"
if not stream.CanRead then invalidOp "Cannot read file"
stream :> Stream
@ -615,8 +610,8 @@ type DefaultFileSystem() as this =
ifs.GetFullPathShim path
else
path
with
| _ -> path
with _ ->
path
abstract IsInvalidPathShim: path: string -> bool
@ -886,8 +881,7 @@ type internal ByteStream =
}
member b.ReadByte() =
if b.pos >= b.max then
failwith "end of stream"
if b.pos >= b.max then failwith "end of stream"
let res = b.bytes[b.pos]
b.pos <- b.pos + 1
@ -954,8 +948,7 @@ type internal ByteBuffer =
Bytes.blit old 0 buf.bbArray 0 buf.bbCurrent
if buf.useArrayPool then
ArrayPool.Shared.Return old
if buf.useArrayPool then ArrayPool.Shared.Return old
member buf.AsMemory() =
buf.CheckDisposed()

Просмотреть файл

@ -170,8 +170,7 @@ type internal HashMultiMap<'Key, 'Value>(size: int, comparer: IEqualityComparer<
member s.Remove(x) =
match s.TryFind x.Key with
| Some v ->
if Unchecked.equals v x.Value then
s.Remove(x.Key)
if Unchecked.equals v x.Value then s.Remove(x.Key)
true
| _ -> false

Просмотреть файл

@ -18,8 +18,7 @@ module ImmutableArray =
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(f 0)
| n ->
if n < 0 then
invalidArg "n" "Below zero."
if n < 0 then invalidArg "n" "Below zero."
let builder = ImmutableArray.CreateBuilder(n)
@ -144,12 +143,9 @@ module ImmutableArray =
let tryFind predicate (arr: ImmutableArray<'T>) =
let rec loop i =
if i >= arr.Length then
None
else if predicate arr[i] then
Some arr[i]
else
loop (i + 1)
if i >= arr.Length then None
else if predicate arr[i] then Some arr[i]
else loop (i + 1)
loop 0
@ -184,8 +180,7 @@ module ImmutableArray =
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
if predicate arr[i] then
builder.Add(arr[i])
if predicate arr[i] then builder.Add(arr[i])
builder.Capacity <- builder.Count
builder.MoveToImmutable()
@ -204,8 +199,7 @@ module ImmutableArray =
for i = 0 to arr.Length - 1 do
let result = chooser arr[i]
if result.IsSome then
builder.Add(result.Value)
if result.IsSome then builder.Add(result.Value)
builder.Capacity <- builder.Count
builder.MoveToImmutable()

Просмотреть файл

@ -142,11 +142,7 @@ type internal AgedLookup<'Token, 'Key, 'Value when 'Value: not struct>(keepStron
member al.Put(tok, key, value) =
let data = FilterAndHold(tok)
let data =
if Exists(data, key) then
RemoveImpl(data, key)
else
data
let data = if Exists(data, key) then RemoveImpl(data, key) else data
let data = Add(data, key, value)
AssignWithStrength(tok, data) // This will remove extras
@ -201,11 +197,7 @@ type internal MruCache<'Token, 'Key, 'Value when 'Value: not struct>
member bc.TryGetAny(tok, key) =
match cache.TryPeekKeyValue(tok, key) with
| Some (similarKey, value) ->
if areSame (similarKey, key) then
Some(value)
else
None
| Some (similarKey, value) -> if areSame (similarKey, key) then Some(value) else None
| None -> None
member bc.TryGet(tok, key) =
@ -224,11 +216,7 @@ type internal MruCache<'Token, 'Key, 'Value when 'Value: not struct>
member bc.TryGetSimilar(tok, key) =
match cache.TryGetKeyValue(tok, key) with
| Some (_, value) ->
if isStillValid (key, value) then
Some value
else
None
| Some (_, value) -> if isStillValid (key, value) then Some value else None
| None -> None
member bc.Set(tok, key: 'Key, value: 'Value) = cache.Put(tok, key, value)

Просмотреть файл

@ -27,10 +27,7 @@ type internal QueueList<'T>(firstElementsIn: 'T list, lastElementsRevIn: 'T list
// Compute the last elements on demand.
let lastElements () =
if push then
[]
else
List.rev lastElementsRev
if push then [] else List.rev lastElementsRev
static let empty = QueueList<'T>([], [], 0)

Просмотреть файл

@ -26,8 +26,7 @@ module internal ResizeArray =
if start2 < 0 then
invalidArg "start2" "index must be positive"
if len < 0 then
invalidArg "len" "length must be positive"
if len < 0 then invalidArg "len" "length must be positive"
if start1 + len > length arr1 then
invalidArg "start1" "(start1+len) out of range"
@ -53,8 +52,7 @@ module internal ResizeArray =
if start < 0 then
invalidArg "start" "index must be positive"
if len < 0 then
invalidArg "len" "length must be positive"
if len < 0 then invalidArg "len" "length must be positive"
if start + len > length arr then
invalidArg "len" "length must be positive"
@ -65,8 +63,7 @@ module internal ResizeArray =
if start < 0 then
invalidArg "start" "index must be positive"
if len < 0 then
invalidArg "len" "length must be positive"
if len < 0 then invalidArg "len" "length must be positive"
if start + len > length arr then
invalidArg "len" "length must be positive"

Просмотреть файл

@ -106,12 +106,9 @@ module SetTree =
// nb. no check for rebalance needed for small trees, also be sure to reuse node already allocated
let c = comparer.Compare(k, t.Key)
if c < 0 then
SetTreeNode(k, empty, t, 2) :> SetTree<'T>
elif c = 0 then
t
else
SetTreeNode(k, t, empty, 2) :> SetTree<'T>
if c < 0 then SetTreeNode(k, empty, t, 2) :> SetTree<'T>
elif c = 0 then t
else SetTreeNode(k, t, empty, 2) :> SetTree<'T>
let rec balance comparer (t1: SetTree<'T>) k (t2: SetTree<'T>) =
// Given t1 < k < t2 where t1 and t2 are "balanced",
@ -211,12 +208,9 @@ module SetTree =
match t with
| :? SetTreeNode<'T> as tn ->
if c < 0 then
contains comparer k tn.Left
elif c = 0 then
true
else
contains comparer k tn.Right
if c < 0 then contains comparer k tn.Left
elif c = 0 then true
else contains comparer k tn.Right
| _ -> (c = 0)
let rec iter f (t: SetTree<'T>) =
@ -266,18 +260,10 @@ module SetTree =
else
match t with
| :? SetTreeNode<'T> as tn ->
let acc =
if f tn.Key then
add comparer tn.Key acc
else
acc
let acc = if f tn.Key then add comparer tn.Key acc else acc
filterAux comparer f tn.Left (filterAux comparer f tn.Right acc)
| _ ->
if f t.Key then
add comparer t.Key acc
else
acc
| _ -> if f t.Key then add comparer t.Key acc else acc
let filter comparer f s = filterAux comparer f s empty
@ -495,10 +481,7 @@ module SetTree =
| _, [] -> 1
| x1 :: t1, x2 :: t2 ->
if isEmpty x1 then
if isEmpty x2 then
compareStacks comparer t1 t2
else
cont ()
if isEmpty x2 then compareStacks comparer t1 t2 else cont ()
elif isEmpty x2 then
cont ()
else
@ -540,10 +523,7 @@ module SetTree =
| _ ->
let c = comparer.Compare(x1.Key, x2.Key)
if c <> 0 then
c
else
compareStacks comparer t1 t2
if c <> 0 then c else compareStacks comparer t1 t2
let compare comparer (t1: SetTree<'T>) (t2: SetTree<'T>) =
if isEmpty t1 then
@ -648,20 +628,14 @@ type internal Set<'T, 'ComparerTag> when 'ComparerTag :> IComparer<'T>(comparer:
SetTree.intersection a.Comparer a.Tree b.Tree |> refresh a
static member Union(a: Set<'T, 'ComparerTag>, b: Set<'T, 'ComparerTag>) : Set<'T, 'ComparerTag> =
if SetTree.isEmpty b.Tree then
a (* A U 0 = A *)
else if SetTree.isEmpty a.Tree then
b (* 0 U B = B *)
else
SetTree.union a.Comparer a.Tree b.Tree |> refresh a
if SetTree.isEmpty b.Tree then a (* A U 0 = A *)
else if SetTree.isEmpty a.Tree then b (* 0 U B = B *)
else SetTree.union a.Comparer a.Tree b.Tree |> refresh a
static member Difference(a: Set<'T, 'ComparerTag>, b: Set<'T, 'ComparerTag>) : Set<'T, 'ComparerTag> =
if SetTree.isEmpty a.Tree then
a (* 0 - B = 0 *)
else if SetTree.isEmpty b.Tree then
a (* A - 0 = A *)
else
SetTree.diff a.Comparer a.Tree b.Tree |> refresh a
if SetTree.isEmpty a.Tree then a (* 0 - B = 0 *)
else if SetTree.isEmpty b.Tree then a (* A - 0 = A *)
else SetTree.diff a.Comparer a.Tree b.Tree |> refresh a
static member Equality(a: Set<'T, 'ComparerTag>, b: Set<'T, 'ComparerTag>) =
(SetTree.compare a.Comparer a.Tree b.Tree = 0)
@ -852,18 +826,12 @@ module MapTree =
let find (comparer: IComparer<'Key>) k (m: MapTree<'Key, 'Value>) =
let mutable v = Unchecked.defaultof<'Value>
if tryGetValue comparer k &v m then
v
else
indexNotFound ()
if tryGetValue comparer k &v m then v else indexNotFound ()
let tryFind (comparer: IComparer<'Key>) k (m: MapTree<'Key, 'Value>) =
let mutable v = Unchecked.defaultof<'Value>
if tryGetValue comparer k &v m then
Some v
else
None
if tryGetValue comparer k &v m then Some v else None
let partition1 (comparer: IComparer<'Key>) (f: OptimizedClosures.FSharpFunc<_, _, _>) k v (acc1, acc2) =
if f.Invoke(k, v) then
@ -886,10 +854,7 @@ module MapTree =
partitionAux comparer (OptimizedClosures.FSharpFunc<_, _, _>.Adapt f) m (empty, empty)
let filter1 (comparer: IComparer<'Key>) (f: OptimizedClosures.FSharpFunc<_, _, _>) k v acc =
if f.Invoke(k, v) then
add comparer k v acc
else
acc
if f.Invoke(k, v) then add comparer k v acc else acc
let rec filterAux (comparer: IComparer<'Key>) (f: OptimizedClosures.FSharpFunc<_, _, _>) (m: MapTree<'Key, 'Value>) acc =
if isEmpty m then
@ -1061,11 +1026,7 @@ module MapTree =
let cLoKey = comparer.Compare(lo, mn.Key)
let cKeyHi = comparer.Compare(mn.Key, hi)
let x =
if cLoKey < 0 then
foldFromTo f mn.Left x
else
x
let x = if cLoKey < 0 then foldFromTo f mn.Left x else x
let x =
if cLoKey <= 0 && cKeyHi <= 0 then
@ -1073,11 +1034,7 @@ module MapTree =
else
x
let x =
if cKeyHi < 0 then
foldFromTo f mn.Right x
else
x
let x = if cKeyHi < 0 then foldFromTo f mn.Right x else x
x
| _ ->
@ -1092,10 +1049,7 @@ module MapTree =
x
if comparer.Compare(lo, hi) = 1 then
x
else
foldFromTo f m x
if comparer.Compare(lo, hi) = 1 then x else foldFromTo f m x
let foldSection (comparer: IComparer<'Key>) lo hi f m x =
foldSectionOpt comparer lo hi (OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt f) m x

Просмотреть файл

@ -71,8 +71,7 @@ module internal PervasiveAutoOpens =
// "How can I detect if am running in Mono?" section
try
Type.GetType "Mono.Runtime" <> null
with
| _ ->
with _ ->
// Must be robust in the case that someone else has installed a handler into System.AppDomain.OnTypeResolveEvent
// that is not reliable.
// This is related to bug 5506--the issue is actually a bug in VSTypeResolutionService.EnsurePopulated which is
@ -197,8 +196,7 @@ module Array =
let mutable i = 0
while eq && i < len do
if not (inp[i] === res[i]) then
eq <- false
if not (inp[i] === res[i]) then eq <- false
i <- i + 1
@ -373,8 +371,8 @@ module Option =
let attempt (f: unit -> 'T) =
try
Some(f ())
with
| _ -> None
with _ ->
None
module List =
@ -404,11 +402,7 @@ module List =
let rec findi n f l =
match l with
| [] -> None
| h :: t ->
if f h then
Some(h, n)
else
findi (n + 1) f t
| h :: t -> if f h then Some(h, n) else findi (n + 1) f t
let splitChoose select l =
let rec ch acc1 acc2 l =
@ -438,10 +432,7 @@ module List =
let h2a = f h1a
let h2b = f h1b
if h1a === h2a && h1b === h2b then
inp
else
[ h2a; h2b ]
if h1a === h2a && h1b === h2b then inp else [ h2a; h2b ]
| [ h1a; h1b; h1c ] ->
let h2a = f h1a
let h2b = f h1b
@ -466,15 +457,16 @@ module List =
loop [] l
let tryFrontAndBack l =
match l with
| [] -> None
| _ -> Some(frontAndBack l)
let tryRemove f inp =
let rec loop acc l =
match l with
| [] -> None
| h :: t ->
if f h then
Some(h, List.rev acc @ t)
else
loop (h :: acc) t
| h :: t -> if f h then Some(h, List.rev acc @ t) else loop (h :: acc) t
loop [] inp
@ -499,11 +491,7 @@ module List =
let rec loop acc l =
match l with
| [] -> List.rev acc, []
| x :: xs ->
if p x then
List.rev acc, l
else
loop (x :: acc) xs
| x :: xs -> if p x then List.rev acc, l else loop (x :: acc) xs
loop [] l
@ -544,11 +532,7 @@ module List =
let rec mn i =
function
| [] -> []
| x :: xs ->
if i = n then
f x :: xs
else
x :: mn (i + 1) xs
| x :: xs -> if i = n then f x :: xs else x :: mn (i + 1) xs
mn 0 xs
@ -746,20 +730,14 @@ module String =
let split options (separator: string[]) (value: string) = value.Split(separator, options)
let (|StartsWith|_|) pattern value =
if String.IsNullOrWhiteSpace value then
None
elif value.StartsWithOrdinal pattern then
Some()
else
None
if String.IsNullOrWhiteSpace value then None
elif value.StartsWithOrdinal pattern then Some()
else None
let (|Contains|_|) pattern value =
if String.IsNullOrWhiteSpace value then
None
elif value.Contains pattern then
Some()
else
None
if String.IsNullOrWhiteSpace value then None
elif value.Contains pattern then Some()
else None
let getLines (str: string) =
use reader = new StringReader(str)
@ -991,8 +969,8 @@ module Cancellable =
match f ct with
| ValueOrCancelled.Value res -> ValueOrCancelled.Value(Choice1Of2 res)
| ValueOrCancelled.Cancelled exn -> ValueOrCancelled.Cancelled exn
with
| err -> ValueOrCancelled.Value(Choice2Of2 err))
with err ->
ValueOrCancelled.Value(Choice2Of2 err))
/// Implement try/finally for a cancellable computation
let inline tryFinally comp compensation =
@ -1162,8 +1140,7 @@ type LazyWithContext<'T, 'Ctxt> =
x.value <- res
x.funcOrException <- null
res
with
| exn ->
with exn ->
x.funcOrException <- box (LazyWithContextFailure(exn))
reraise ()
| _ -> failwith "unreachable"
@ -1281,8 +1258,8 @@ module NameMap =
(fun n x2 acc ->
try
f n (Map.find n m1) x2 acc
with
| :? KeyNotFoundException -> errf n x2)
with :? KeyNotFoundException ->
errf n x2)
m2
acc

Просмотреть файл

@ -154,6 +154,8 @@ module internal List =
val frontAndBack: l: 'a list -> 'a list * 'a
val tryFrontAndBack: l: 'a list -> ('a list * 'a) option
val tryRemove: f: ('a -> bool) -> inp: 'a list -> ('a * 'a list) option
val zip4: l1: 'a list -> l2: 'b list -> l3: 'c list -> l4: 'd list -> ('a * 'b * 'c * 'd) list
@ -531,18 +533,21 @@ module internal NameMap =
val layer: m1: NameMap<'T> -> m2: Map<string, 'T> -> Map<string, 'T>
/// Not a very useful function - only called in one place - should be changed
val layerAdditive: addf: ('a list -> 'b -> 'a list) -> m1: Map<'c, 'b> -> m2: Map<'c, 'a list> -> Map<'c, 'a list>
when 'c: comparison
val layerAdditive:
addf: ('a list -> 'b -> 'a list) -> m1: Map<'c, 'b> -> m2: Map<'c, 'a list> -> Map<'c, 'a list>
when 'c: comparison
/// Union entries by identical key, using the provided function to union sets of values
val union: unionf: (seq<'a> -> 'b) -> ms: seq<NameMap<'a>> -> Map<string, 'b>
/// For every entry in m2 find an entry in m1 and fold
val subfold2: errf: ('a -> 'b -> 'c) -> f: ('a -> 'd -> 'b -> 'c -> 'c) -> m1: Map<'a, 'd> -> m2: Map<'a, 'b> -> acc: 'c -> 'c
when 'a: comparison
val subfold2:
errf: ('a -> 'b -> 'c) -> f: ('a -> 'd -> 'b -> 'c -> 'c) -> m1: Map<'a, 'd> -> m2: Map<'a, 'b> -> acc: 'c -> 'c
when 'a: comparison
val suball2: errf: ('a -> 'b -> bool) -> p: ('c -> 'b -> bool) -> m1: Map<'a, 'c> -> m2: Map<'a, 'b> -> bool
when 'a: comparison
val suball2:
errf: ('a -> 'b -> bool) -> p: ('c -> 'b -> bool) -> m1: Map<'a, 'c> -> m2: Map<'a, 'b> -> bool
when 'a: comparison
val mapFold: f: ('a -> string -> 'T -> 'b * 'a) -> s: 'a -> l: NameMap<'T> -> Map<string, 'b> * 'a

Просмотреть файл

@ -363,8 +363,8 @@ type Range(code1: int64, code2: int64) =
|> Seq.take (m.EndLine - m.StartLine + 1)
|> String.concat "\n"
|> fun s -> s.Substring(startCol + 1, s.LastIndexOf("\n", StringComparison.Ordinal) + 1 - startCol + endCol)
with
| e -> e.ToString()
with e ->
e.ToString()
member m.ToShortString() =
sprintf "(%d,%d--%d,%d)" m.StartLine m.StartColumn m.EndLine m.EndColumn
@ -542,5 +542,5 @@ module Range =
match nonEmptyLine with
| Some (i, s) -> mkRange file (mkPos (i + 1) 0) (mkPos (i + 1) s.Length)
| None -> mkRange file (mkPos 1 0) (mkPos 1 80)
with
| _ -> mkRange file (mkPos 1 0) (mkPos 1 80)
with _ ->
mkRange file (mkPos 1 0) (mkPos 1 80)

Просмотреть файл

@ -12,10 +12,7 @@ type Rational =
}
let rec gcd a (b: BigInteger) =
if b = BigInteger.Zero then
a
else
gcd b (a % b)
if b = BigInteger.Zero then a else gcd b (a % b)
let lcm a b = (a * b) / (gcd a b)
@ -27,11 +24,7 @@ let mkRational p q =
let g = gcd q p in
p / g, q / g
let p, q =
if q > BigInteger.Zero then
p, q
else
-p, -q
let p, q = if q > BigInteger.Zero then p, q else -p, -q
in
@ -73,9 +66,6 @@ let GetNumerator p = int p.numerator
let GetDenominator p = int p.denominator
let SignRational p =
if p.numerator < BigInteger.Zero then
-1
else if p.numerator > BigInteger.Zero then
1
else
0
if p.numerator < BigInteger.Zero then -1
else if p.numerator > BigInteger.Zero then 1
else 0

Просмотреть файл

@ -589,14 +589,14 @@ module Display =
ty.GetMethod("ToString", BindingFlags.Public ||| BindingFlags.Instance, null, [||], null)
methInfo.DeclaringType = typeof<Object>
with
| _e -> false
with _e ->
false
let catchExn f =
try
Choice1Of2(f ())
with
| e -> Choice2Of2 e
with e ->
Choice2Of2 e
// An implementation of break stack.
// Uses mutable state, relying on linear threading of the state.
@ -630,16 +630,11 @@ module Display =
Breaks(next + 1, outer, stack)
let popBreak (Breaks (next, outer, stack)) =
if next = 0 then
raise (Failure "popBreak: underflow")
if next = 0 then raise (Failure "popBreak: underflow")
let topBroke = stack[next - 1] < 0
let outer =
if outer = next then
outer - 1
else
outer // if all broken, unwind
let outer = if outer = next then outer - 1 else outer // if all broken, unwind
let next = next - 1
Breaks(next, outer, stack), topBroke
@ -977,10 +972,7 @@ module Display =
let exceededPrintSize () = size <= 0
let countNodes n =
if size > 0 then
size <- size - n
else
() // no need to keep decrementing (and avoid wrap around)
if size > 0 then size <- size - n else () // no need to keep decrementing (and avoid wrap around)
let stopShort _ = exceededPrintSize () // for unfoldL
@ -1039,8 +1031,7 @@ module Display =
path.Remove(x) |> ignore
res
with
| e ->
with e ->
countNodes 1
wordL (tagText ("Error: " + e.Message))
@ -1157,8 +1148,8 @@ module Display =
)
)
)
with
| _ -> None
with _ ->
None
// Seed with an empty layout with a space to the left for formatting purposes
buildObjMessageL txt [ leftL (tagText "") ]
@ -1296,10 +1287,7 @@ module Display =
|> makeListL
let project1 x =
if x >= (b1 + n1) then
None
else
Some(x, x + 1)
if x >= (b1 + n1) then None else Some(x, x + 1)
let rowsL = boundedUnfoldL rowL project1 stopShort b1 opts.PrintLength
@ -1341,11 +1329,7 @@ module Display =
let itemLs =
boundedUnfoldL
possibleKeyValueL
(fun () ->
if it.MoveNext() then
Some(it.Current, ())
else
None)
(fun () -> if it.MoveNext() then Some(it.Current, ()) else None)
stopShort
()
(1 + opts.PrintLength / 12)
@ -1463,12 +1447,11 @@ module Display =
tagProperty m.Name),
(try
Some(nestedObjL nDepth Precedence.BracketIfTuple ((getProperty ty obj m.Name), ty))
with
| _ ->
with _ ->
try
Some(nestedObjL nDepth Precedence.BracketIfTuple ((getField obj (m :?> FieldInfo)), ty))
with
| _ -> None)))
with _ ->
None)))
|> Array.toList
|> makePropertiesL)
@ -1594,8 +1577,7 @@ module Display =
match text with
| null -> ""
| _ -> text
with
| e ->
with e ->
// If a .ToString() call throws an exception, catch it and use the message as the result.
// This may be informative, e.g. division by zero etc...
"<ToString exception: " + e.Message + ">"

Просмотреть файл

@ -35,8 +35,8 @@ type CreateFSharpManifestResourceName public () =
let runningOnMono =
try
System.Type.GetType("Mono.Runtime") <> null
with
| e -> false
with e ->
false
let fileName =
if

Просмотреть файл

@ -118,8 +118,7 @@ module internal {1} =
File.WriteAllText(sourcePath, body.ToString())
printMessage <| sprintf "Done: %s" sourcePath
Some(sourcePath)
with
| e ->
with e ->
printf "An exception occurred when processing '%s'\n%s" resx (e.ToString())
None

Просмотреть файл

@ -236,8 +236,7 @@ type FSharpEmbedResourceText() =
let str =
try
System.String.Format(Unquote(txt.Substring i)) // Format turns e.g '\n' into that char, but also requires that we 'escape' curlies in the original .txt file, e.g. "{{"
with
| e ->
with e ->
Err(
fileName,
lineNum,
@ -551,8 +550,7 @@ open Printf
xd.Save outXmlStream
printMessage (sprintf "Done %s" outFileName)
Some(fileName, outFileName, outXmlFileName)
with
| e ->
with e ->
PrintErr(fileName, 0, sprintf "An exception occurred when processing '%s'\n%s" fileName (e.ToString()))
None

Просмотреть файл

@ -68,8 +68,8 @@ type public Fsc() as this =
let locationOfThisDll =
try
Some(Path.GetDirectoryName(typeof<Fsc>.Assembly.Location))
with
| _ -> None
with _ ->
None
match FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(locationOfThisDll) with
| Some s -> s
@ -677,8 +677,7 @@ type public Fsc() as this =
try
invokeCompiler baseCallDelegate
with
| e ->
with e ->
Debug.Fail(
"HostObject received by Fsc task did not have a Compile method or the compile method threw an exception. "
+ (e.ToString())

Просмотреть файл

@ -51,8 +51,8 @@ type public Fsi() as this =
let locationOfThisDll =
try
Some(Path.GetDirectoryName(typeof<Fsi>.Assembly.Location))
with
| _ -> None
with _ ->
None
match FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(locationOfThisDll) with
| Some s -> s
@ -361,8 +361,7 @@ type public Fsi() as this =
try
invokeCompiler baseCallDelegate
with
| e ->
with e ->
Debug.Assert(
false,
"HostObject received by Fsi task did not have a Compile method or the compile method threw an exception. "

Просмотреть файл

@ -87,8 +87,8 @@ type SubstituteText() =
Directory.CreateDirectory(directory) |> ignore
File.WriteAllText(targetPath, contents)
with
| _ -> ()
with _ ->
()
copiedFiles.Add(item)

Просмотреть файл

@ -166,7 +166,6 @@ type WriteCodeFragment() =
_outputFile <- outputFileItem
true
with
| e ->
with e ->
printf "Error writing code fragment: %s" (e.ToString())
false

Просмотреть файл

@ -52,8 +52,8 @@ type internal SimpleEventLoop() =
result <-
try
Some(f ())
with
| _ -> None)
with _ ->
None)
setSignal doneSignal
run ()

Просмотреть файл

@ -0,0 +1,6 @@
# FSharp.Core uses more "conservative" settings - more lines etc.
[*.fs]
max_line_length=120
fsharp_max_function_binding_width=1
fsharp_max_if_then_else_short_width=40

Просмотреть файл

@ -7,170 +7,210 @@ open Microsoft.FSharp.Core
// ----------------------------------------------------------------------------
// Mutable Tuples - used when translating queries that use F# tuples
// and records. We replace tuples/records with anonymous types which
// and records. We replace tuples/records with anonymous types which
// are handled correctly by LINQ to SQL/Entities and other providers.
//
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
//
// The terminology "mutable tuple" is now incorrect in this code -
// The terminology "mutable tuple" is now incorrect in this code -
// "immutable anonymous tuple-like types" are used instead. The key thing in this
// code is that the anonymous types used conform to the shape and style
// expected by LINQ providers, and we pass the correspondence between constructor
// arguments and properties to the magic "members" argument of the Expression.New
// constructor in Linq.fs.
//
// This terminology mistake also runs all the way through Query.fs.
// This terminology mistake also runs all the way through Query.fs.
// ----------------------------------------------------------------------------
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
new (Item1) = { item1 = Item1 }
new(Item1) = { item1 = Item1 }
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
new (Item1, Item2) = { item1 = Item1; item2 = Item2 }
new(Item1, Item2) = { item1 = Item1; item2 = Item2 }
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
new (Item1, Item2, Item3) = { item1 = Item1; item2 = Item2; item3 = Item3 }
new(Item1, Item2, Item3) =
{
item1 = Item1
item2 = Item2
item3 = Item3
}
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3, 'T4> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
val private item4 : 'T4
val private item4: 'T4
member x.Item4 = x.item4
new (Item1, Item2, Item3, Item4) = { item1 = Item1; item2 = Item2; item3 = Item3; item4 = Item4 }
new(Item1, Item2, Item3, Item4) =
{
item1 = Item1
item2 = Item2
item3 = Item3
item4 = Item4
}
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3, 'T4, 'T5> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
val private item4 : 'T4
val private item4: 'T4
member x.Item4 = x.item4
val private item5 : 'T5
val private item5: 'T5
member x.Item5 = x.item5
new (Item1, Item2, Item3, Item4, Item5) = { item1 = Item1; item2 = Item2; item3 = Item3; item4 = Item4 ; item5 = Item5 }
new(Item1, Item2, Item3, Item4, Item5) =
{
item1 = Item1
item2 = Item2
item3 = Item3
item4 = Item4
item5 = Item5
}
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3, 'T4, 'T5, 'T6> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
val private item4 : 'T4
val private item4: 'T4
member x.Item4 = x.item4
val private item5 : 'T5
val private item5: 'T5
member x.Item5 = x.item5
val private item6 : 'T6
val private item6: 'T6
member x.Item6 = x.item6
new (Item1, Item2, Item3, Item4, Item5, Item6) = { item1 = Item1; item2 = Item2; item3 = Item3; item4 = Item4 ; item5 = Item5 ; item6 = Item6 }
new(Item1, Item2, Item3, Item4, Item5, Item6) =
{
item1 = Item1
item2 = Item2
item3 = Item3
item4 = Item4
item5 = Item5
item6 = Item6
}
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3, 'T4, 'T5, 'T6, 'T7> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
val private item4 : 'T4
val private item4: 'T4
member x.Item4 = x.item4
val private item5 : 'T5
val private item5: 'T5
member x.Item5 = x.item5
val private item6 : 'T6
val private item6: 'T6
member x.Item6 = x.item6
val private item7 : 'T7
val private item7: 'T7
member x.Item7 = x.item7
new (Item1, Item2, Item3, Item4, Item5, Item6, Item7) = { item1 = Item1; item2 = Item2; item3 = Item3; item4 = Item4 ; item5 = Item5 ; item6 = Item6 ; item7 = Item7 }
new(Item1, Item2, Item3, Item4, Item5, Item6, Item7) =
{
item1 = Item1
item2 = Item2
item3 = Item3
item4 = Item4
item5 = Item5
item6 = Item6
item7 = Item7
}
/// <summary>This type shouldn't be used directly from user code.</summary>
/// <exclude />
type AnonymousObject<'T1, 'T2, 'T3, 'T4, 'T5, 'T6, 'T7, 'T8> =
val private item1 : 'T1
member x.Item1 = x.item1
val private item1: 'T1
member x.Item1 = x.item1
val private item2 : 'T2
val private item2: 'T2
member x.Item2 = x.item2
val private item3 : 'T3
val private item3: 'T3
member x.Item3 = x.item3
val private item4 : 'T4
val private item4: 'T4
member x.Item4 = x.item4
val private item5 : 'T5
val private item5: 'T5
member x.Item5 = x.item5
val private item6 : 'T6
val private item6: 'T6
member x.Item6 = x.item6
val private item7 : 'T7
val private item7: 'T7
member x.Item7 = x.item7
val private item8 : 'T8
val private item8: 'T8
member x.Item8 = x.item8
new (Item1, Item2, Item3, Item4, Item5, Item6, Item7, Item8) = { item1 = Item1; item2 = Item2; item3 = Item3; item4 = Item4 ; item5 = Item5 ; item6 = Item6 ; item7 = Item7; item8 = Item8 }
new(Item1, Item2, Item3, Item4, Item5, Item6, Item7, Item8) =
{
item1 = Item1
item2 = Item2
item3 = Item3
item4 = Item4
item5 = Item5
item6 = Item6
item7 = Item7
item8 = Item8
}

Просмотреть файл

@ -9,134 +9,297 @@ open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
module NullableOperators =
let (?>=) (x : Nullable<'T>) (y: 'T) = x.HasValue && x.Value >= y
let (?>=) (x: Nullable<'T>) (y: 'T) =
x.HasValue && x.Value >= y
let (?>) (x : Nullable<'T>) (y: 'T) = x.HasValue && x.Value > y
let (?>) (x: Nullable<'T>) (y: 'T) =
x.HasValue && x.Value > y
let (?<=) (x : Nullable<'T>) (y: 'T) = x.HasValue && x.Value <= y
let (?<=) (x: Nullable<'T>) (y: 'T) =
x.HasValue && x.Value <= y
let (?<) (x : Nullable<'T>) (y: 'T) = x.HasValue && x.Value < y
let (?<) (x: Nullable<'T>) (y: 'T) =
x.HasValue && x.Value < y
let (?=) (x : Nullable<'T>) (y: 'T) = x.HasValue && x.Value = y
let (?=) (x: Nullable<'T>) (y: 'T) =
x.HasValue && x.Value = y
let (?<>) (x : Nullable<'T>) (y: 'T) = not (x ?= y)
let (?<>) (x: Nullable<'T>) (y: 'T) =
not (x ?= y)
let (>=?) (x : 'T) (y: Nullable<'T>) = y.HasValue && x >= y.Value
let (>=?) (x: 'T) (y: Nullable<'T>) =
y.HasValue && x >= y.Value
let (>?) (x : 'T) (y: Nullable<'T>) = y.HasValue && x > y.Value
let (>?) (x: 'T) (y: Nullable<'T>) =
y.HasValue && x > y.Value
let (<=?) (x : 'T) (y: Nullable<'T>) = y.HasValue && x <= y.Value
let (<=?) (x: 'T) (y: Nullable<'T>) =
y.HasValue && x <= y.Value
let (<?) (x : 'T) (y: Nullable<'T>) = y.HasValue && x < y.Value
let (<?) (x: 'T) (y: Nullable<'T>) =
y.HasValue && x < y.Value
let (=?) (x : 'T) (y: Nullable<'T>) = y.HasValue && x = y.Value
let (=?) (x: 'T) (y: Nullable<'T>) =
y.HasValue && x = y.Value
let (<>?) (x : 'T) (y: Nullable<'T>) = not (x =? y)
let (<>?) (x: 'T) (y: Nullable<'T>) =
not (x =? y)
let (?>=?) (x : Nullable<'T>) (y: Nullable<'T>) = (x.HasValue && y.HasValue && x.Value >= y.Value)
let (?>=?) (x: Nullable<'T>) (y: Nullable<'T>) =
(x.HasValue && y.HasValue && x.Value >= y.Value)
let (?>?) (x : Nullable<'T>) (y: Nullable<'T>) = (x.HasValue && y.HasValue && x.Value > y.Value)
let (?>?) (x: Nullable<'T>) (y: Nullable<'T>) =
(x.HasValue && y.HasValue && x.Value > y.Value)
let (?<=?) (x : Nullable<'T>) (y: Nullable<'T>) = (x.HasValue && y.HasValue && x.Value <= y.Value)
let (?<=?) (x: Nullable<'T>) (y: Nullable<'T>) =
(x.HasValue && y.HasValue && x.Value <= y.Value)
let (?<?) (x : Nullable<'T>) (y: Nullable<'T>) = (x.HasValue && y.HasValue && x.Value < y.Value)
let (?<?) (x: Nullable<'T>) (y: Nullable<'T>) =
(x.HasValue && y.HasValue && x.Value < y.Value)
let (?=?) (x : Nullable<'T>) (y: Nullable<'T>) = (not x.HasValue && not y.HasValue) || (x.HasValue && y.HasValue && x.Value = y.Value)
let (?=?) (x: Nullable<'T>) (y: Nullable<'T>) =
(not x.HasValue && not y.HasValue)
|| (x.HasValue && y.HasValue && x.Value = y.Value)
let (?<>?) (x : Nullable<'T>) (y: Nullable<'T>) = not (x ?=? y)
let (?<>?) (x: Nullable<'T>) (y: Nullable<'T>) =
not (x ?=? y)
let inline (?+) (x : Nullable<_>) y = if x.HasValue then Nullable(x.Value + y) else Nullable()
let inline (?+) (x: Nullable<_>) y =
if x.HasValue then
Nullable(x.Value + y)
else
Nullable()
let inline (+?) x (y: Nullable<_>) = if y.HasValue then Nullable(x + y.Value) else Nullable()
let inline (+?) x (y: Nullable<_>) =
if y.HasValue then
Nullable(x + y.Value)
else
Nullable()
let inline (?+?) (x : Nullable<_>) (y: Nullable<_>) = if x.HasValue && y.HasValue then Nullable(x.Value + y.Value) else Nullable()
let inline (?+?) (x: Nullable<_>) (y: Nullable<_>) =
if x.HasValue && y.HasValue then
Nullable(x.Value + y.Value)
else
Nullable()
let inline (?-) (x : Nullable<_>) y = if x.HasValue then Nullable(x.Value - y) else Nullable()
let inline (?-) (x: Nullable<_>) y =
if x.HasValue then
Nullable(x.Value - y)
else
Nullable()
let inline (-?) x (y: Nullable<_>) = if y.HasValue then Nullable(x - y.Value) else Nullable()
let inline (-?) x (y: Nullable<_>) =
if y.HasValue then
Nullable(x - y.Value)
else
Nullable()
let inline (?-?) (x : Nullable<_>) (y: Nullable<_>) = if x.HasValue && y.HasValue then Nullable(x.Value - y.Value) else Nullable()
let inline (?-?) (x: Nullable<_>) (y: Nullable<_>) =
if x.HasValue && y.HasValue then
Nullable(x.Value - y.Value)
else
Nullable()
let inline ( ?* ) (x : Nullable<_>) y = if x.HasValue then Nullable(x.Value * y) else Nullable()
let inline (?*) (x: Nullable<_>) y =
if x.HasValue then
Nullable(x.Value * y)
else
Nullable()
let inline ( *? ) x (y: Nullable<_>) = if y.HasValue then Nullable(x * y.Value) else Nullable()
let inline ( *? ) x (y: Nullable<_>) =
if y.HasValue then
Nullable(x * y.Value)
else
Nullable()
let inline ( ?*? ) (x : Nullable<_>) (y: Nullable<_>) = if x.HasValue && y.HasValue then Nullable(x.Value * y.Value) else Nullable()
let inline (?*?) (x: Nullable<_>) (y: Nullable<_>) =
if x.HasValue && y.HasValue then
Nullable(x.Value * y.Value)
else
Nullable()
let inline ( ?% ) (x : Nullable<_>) y = if x.HasValue then Nullable(x.Value % y) else Nullable()
let inline (?%) (x: Nullable<_>) y =
if x.HasValue then
Nullable(x.Value % y)
else
Nullable()
let inline ( %? ) x (y: Nullable<_>) = if y.HasValue then Nullable(x % y.Value) else Nullable()
let inline (%?) x (y: Nullable<_>) =
if y.HasValue then
Nullable(x % y.Value)
else
Nullable()
let inline ( ?%? ) (x : Nullable<_>) (y: Nullable<_>) = if x.HasValue && y.HasValue then Nullable(x.Value % y.Value) else Nullable()
let inline (?%?) (x: Nullable<_>) (y: Nullable<_>) =
if x.HasValue && y.HasValue then
Nullable(x.Value % y.Value)
else
Nullable()
let inline ( ?/ ) (x : Nullable<_>) y = if x.HasValue then Nullable(x.Value / y) else Nullable()
let inline (?/) (x: Nullable<_>) y =
if x.HasValue then
Nullable(x.Value / y)
else
Nullable()
let inline ( /? ) x (y: Nullable<_>) = if y.HasValue then Nullable(x / y.Value) else Nullable()
let inline (/?) x (y: Nullable<_>) =
if y.HasValue then
Nullable(x / y.Value)
else
Nullable()
let inline ( ?/? ) (x : Nullable<_>) (y: Nullable<_>) = if x.HasValue && y.HasValue then Nullable(x.Value / y.Value) else Nullable()
let inline (?/?) (x: Nullable<_>) (y: Nullable<_>) =
if x.HasValue && y.HasValue then
Nullable(x.Value / y.Value)
else
Nullable()
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Nullable =
[<CompiledName("ToUInt8")>]
let inline uint8 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.byte value.Value) else Nullable()
let inline uint8 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.byte value.Value)
else
Nullable()
[<CompiledName("ToInt8")>]
let inline int8 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.sbyte value.Value) else Nullable()
let inline int8 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.sbyte value.Value)
else
Nullable()
[<CompiledName("ToByte")>]
let inline byte (value:Nullable<_>) = if value.HasValue then Nullable(Operators.byte value.Value) else Nullable()
let inline byte (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.byte value.Value)
else
Nullable()
[<CompiledName("ToSByte")>]
let inline sbyte (value:Nullable<_>) = if value.HasValue then Nullable(Operators.sbyte value.Value) else Nullable()
let inline sbyte (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.sbyte value.Value)
else
Nullable()
[<CompiledName("ToInt16")>]
let inline int16 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.int16 value.Value) else Nullable()
let inline int16 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.int16 value.Value)
else
Nullable()
[<CompiledName("ToUInt16")>]
let inline uint16 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.uint16 value.Value) else Nullable()
let inline uint16 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.uint16 value.Value)
else
Nullable()
[<CompiledName("ToInt")>]
let inline int (value:Nullable<_>) = if value.HasValue then Nullable(Operators.int value.Value) else Nullable()
let inline int (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.int value.Value)
else
Nullable()
[<CompiledName("ToUInt")>]
let inline uint (value: Nullable<_>) = if value.HasValue then Nullable(Operators.uint value.Value) else Nullable()
let inline uint (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.uint value.Value)
else
Nullable()
[<CompiledName("ToEnum")>]
let inline enum (value:Nullable< int32 >) = if value.HasValue then Nullable(Operators.enum value.Value) else Nullable()
let inline enum (value: Nullable<int32>) =
if value.HasValue then
Nullable(Operators.enum value.Value)
else
Nullable()
[<CompiledName("ToInt32")>]
let inline int32 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.int32 value.Value) else Nullable()
let inline int32 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.int32 value.Value)
else
Nullable()
[<CompiledName("ToUInt32")>]
let inline uint32 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.uint32 value.Value) else Nullable()
let inline uint32 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.uint32 value.Value)
else
Nullable()
[<CompiledName("ToInt64")>]
let inline int64 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.int64 value.Value) else Nullable()
let inline int64 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.int64 value.Value)
else
Nullable()
[<CompiledName("ToUInt64")>]
let inline uint64 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.uint64 value.Value) else Nullable()
let inline uint64 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.uint64 value.Value)
else
Nullable()
[<CompiledName("ToFloat32")>]
let inline float32 (value:Nullable<_>) = if value.HasValue then Nullable(Operators.float32 value.Value) else Nullable()
let inline float32 (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.float32 value.Value)
else
Nullable()
[<CompiledName("ToFloat")>]
let inline float (value:Nullable<_>) = if value.HasValue then Nullable(Operators.float value.Value) else Nullable()
let inline float (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.float value.Value)
else
Nullable()
[<CompiledName("ToSingle")>]
let inline single (value:Nullable<_>) = if value.HasValue then Nullable(Operators.float32 value.Value) else Nullable()
let inline single (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.float32 value.Value)
else
Nullable()
[<CompiledName("ToDouble")>]
let inline double (value:Nullable<_>) = if value.HasValue then Nullable(Operators.float value.Value) else Nullable()
let inline double (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.float value.Value)
else
Nullable()
[<CompiledName("ToIntPtr")>]
let inline nativeint (value:Nullable<_>) = if value.HasValue then Nullable(Operators.nativeint value.Value) else Nullable()
let inline nativeint (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.nativeint value.Value)
else
Nullable()
[<CompiledName("ToUIntPtr")>]
let inline unativeint (value:Nullable<_>) = if value.HasValue then Nullable(Operators.unativeint value.Value) else Nullable()
let inline unativeint (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.unativeint value.Value)
else
Nullable()
[<CompiledName("ToDecimal")>]
let inline decimal (value:Nullable<_>) = if value.HasValue then Nullable(Operators.decimal value.Value) else Nullable()
let inline decimal (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.decimal value.Value)
else
Nullable()
[<CompiledName("ToChar")>]
let inline char (value:Nullable<_>) = if value.HasValue then Nullable(Operators.char value.Value) else Nullable()
let inline char (value: Nullable<_>) =
if value.HasValue then
Nullable(Operators.char value.Value)
else
Nullable()

Просмотреть файл

@ -11,274 +11,336 @@ open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Linq.RuntimeHelpers
open System.Collections
open System.Collections.Concurrent
open System.Collections.Generic
open System.Linq
open System.Linq.Expressions
open System.Reflection
// ----------------------------------------------------------------------------
/// A type used to reconstruct a grouping after applying a mutable->immutable mapping transformation
/// A type used to reconstruct a grouping after applying a mutable->immutable mapping transformation
/// on a result of a query.
type Grouping<'K, 'T>(key:'K, values:seq<'T>) =
interface System.Linq.IGrouping<'K, 'T> with
type Grouping<'K, 'T>(key: 'K, values: seq<'T>) =
interface IGrouping<'K, 'T> with
member _.Key = key
interface System.Collections.IEnumerable with
member _.GetEnumerator() = values.GetEnumerator() :> System.Collections.IEnumerator
interface IEnumerable with
member _.GetEnumerator() =
values.GetEnumerator() :> IEnumerator
interface System.Collections.Generic.IEnumerable<'T> with
member _.GetEnumerator() = values.GetEnumerator()
interface Generic.IEnumerable<'T> with
member _.GetEnumerator() =
values.GetEnumerator()
module internal Adapters =
module internal Adapters =
let memoize f =
let d = new System.Collections.Concurrent.ConcurrentDictionary<Type,'b>(HashIdentity.Structural)
fun x -> d.GetOrAdd(x, fun r -> f r)
let memoize f =
let d = new ConcurrentDictionary<Type, 'b>(HashIdentity.Structural)
let isPartiallyImmutableRecord : Type -> bool =
memoize (fun t ->
FSharpType.IsRecord t &&
not (FSharpType.GetRecordFields t |> Array.forall (fun f -> f.CanWrite)) )
fun x -> d.GetOrAdd(x, (fun r -> f r))
let MemberInitializationHelperMeth =
let isPartiallyImmutableRecord: Type -> bool =
memoize (fun t ->
FSharpType.IsRecord t
&& not (FSharpType.GetRecordFields t |> Array.forall (fun f -> f.CanWrite)))
let MemberInitializationHelperMeth =
methodhandleof (fun x -> LeafExpressionConverter.MemberInitializationHelper x)
|> System.Reflection.MethodInfo.GetMethodFromHandle
:?> System.Reflection.MethodInfo
|> MethodInfo.GetMethodFromHandle
:?> MethodInfo
let NewAnonymousObjectHelperMeth =
let NewAnonymousObjectHelperMeth =
methodhandleof (fun x -> LeafExpressionConverter.NewAnonymousObjectHelper x)
|> System.Reflection.MethodInfo.GetMethodFromHandle
:?> System.Reflection.MethodInfo
|> MethodInfo.GetMethodFromHandle
:?> MethodInfo
// The following patterns are used to recognize object construction
// The following patterns are used to recognize object construction
// using the 'new O(Prop1 = <e>, Prop2 = <e>)' syntax
/// Recognize sequential series written as (... ((<e>; <e>); <e>); ...)
let (|LeftSequentialSeries|) e =
let rec leftSequentialSeries acc e =
match e with
| Patterns.Sequential(e1, e2) -> leftSequentialSeries (e2 :: acc) e1
match e with
| Patterns.Sequential (e1, e2) -> leftSequentialSeries (e2 :: acc) e1
| _ -> e :: acc
leftSequentialSeries [] e
/// Tests whether a list consists only of assignments of properties of the
/// Tests whether a list consists only of assignments of properties of the
/// given variable, null values (ignored) and ends by returning the given variable
/// (pattern returns only property assignments)
let (|PropSetList|_|) varArg (list:Expr list) =
let rec propSetList acc x =
match x with
let (|PropSetList|_|) varArg (list: Expr list) =
let rec propSetList acc x =
match x with
// detect " v.X <- y"
| ((Patterns.PropertySet(Some(Patterns.Var var), _, _, _)) as p) :: xs when var = varArg ->
| ((Patterns.PropertySet (Some (Patterns.Var var), _, _, _)) as p) :: xs when var = varArg ->
propSetList (p :: acc) xs
// skip unit values
| (Patterns.Value (v, _)) :: xs when v = null -> propSetList acc xs
// detect "v"
| [Patterns.Var var] when var = varArg -> Some acc
| [ Patterns.Var var ] when var = varArg -> Some acc
| _ -> None
propSetList [] list
/// Recognize object construction written using 'new O(Prop1 = <e>, Prop2 = <e>, ...)'
let (|ObjectConstruction|_|) e =
let (|ObjectConstruction|_|) e =
match e with
| Patterns.Let ( var, (Patterns.NewObject(_, []) as init), LeftSequentialSeries propSets ) ->
match propSets with
| Patterns.Let (var, (Patterns.NewObject (_, []) as init), LeftSequentialSeries propSets) ->
match propSets with
| PropSetList var propSets -> Some(var, init, propSets)
| _ -> None
| _ -> None
// Get arrays of types & map of transformations
let tupleTypes =
[| typedefof<System.Tuple<_>>, typedefof<AnonymousObject<_>>
typedefof<_ * _>, typedefof<AnonymousObject<_, _>>
typedefof<_ * _ * _>, typedefof<AnonymousObject<_, _, _>>
typedefof<_ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _>>
typedefof<_ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _, _, _>> |]
let tupleTypes =
[|
typedefof<System.Tuple<_>>, typedefof<AnonymousObject<_>>
typedefof<_ * _>, typedefof<AnonymousObject<_, _>>
typedefof<_ * _ * _>, typedefof<AnonymousObject<_, _, _>>
typedefof<_ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _>>
typedefof<_ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _, _>>
typedefof<_ * _ * _ * _ * _ * _ * _ * _>, typedefof<AnonymousObject<_, _, _, _, _, _, _, _>>
|]
let anonObjectTypes = tupleTypes |> Array.map snd
let tupleToAnonTypeMap =
let t = new Dictionary<Type,Type>()
for (k,v) in tupleTypes do t.[k] <- v
let tupleToAnonTypeMap =
let t = new Dictionary<Type, Type>()
for (k, v) in tupleTypes do
t.[k] <- v
t
let anonToTupleTypeMap =
let t = new Dictionary<Type,Type>()
for (k,v) in tupleTypes do t.[v] <- k
t
let anonToTupleTypeMap =
let t = new Dictionary<Type, Type>()
for (k, v) in tupleTypes do
t.[v] <- k
t
/// Recognize anonymous type construction written using 'new AnonymousObject(<e1>, <e2>, ...)'
let (|NewAnonymousObject|_|) e =
let (|NewAnonymousObject|_|) e =
match e with
| Patterns.NewObject(ctor,args) when
let dty = ctor.DeclaringType
dty.IsGenericType && anonToTupleTypeMap.ContainsKey (dty.GetGenericTypeDefinition()) ->
Some (ctor, args)
| Patterns.NewObject (ctor, args) when
let dty = ctor.DeclaringType
dty.IsGenericType
&& anonToTupleTypeMap.ContainsKey(dty.GetGenericTypeDefinition())
->
Some(ctor, args)
| _ -> None
let OneNewAnonymousObject (args:Expr list) =
let OneNewAnonymousObject (args: Expr list) =
// Will fit into a single tuple type
let typ = anonObjectTypes.[args.Length - 1]
let typ = typ.MakeGenericType [| for a in args -> a.Type |]
let ctor = typ.GetConstructors().[0]
let res = Expr.NewObject (ctor, args)
assert (match res with NewAnonymousObject _ -> true | _ -> false)
let res = Expr.NewObject(ctor, args)
assert
(match res with
| NewAnonymousObject _ -> true
| _ -> false)
res
let rec NewAnonymousObject (args:Expr list) : Expr =
match args with
let rec NewAnonymousObject (args: Expr list) : Expr =
match args with
| x1 :: x2 :: x3 :: x4 :: x5 :: x6 :: x7 :: x8 :: tail ->
// Too long to fit single tuple - nested tuple after first 7
OneNewAnonymousObject [ x1; x2; x3; x4; x5; x6; x7; NewAnonymousObject (x8 :: tail) ]
| args ->
OneNewAnonymousObject args
OneNewAnonymousObject [ x1; x2; x3; x4; x5; x6; x7; NewAnonymousObject(x8 :: tail) ]
| args -> OneNewAnonymousObject args
let AnonymousObjectGet (e:Expr,i:int) =
// Recursively generate tuple get
let AnonymousObjectGet (e: Expr, i: int) =
// Recursively generate tuple get
// (may be nested e.g. TupleGet(<e>, 9) ~> <e>.Item8.Item3)
let rec walk i (inst:Expr) (newType:Type) =
let rec walk i (inst: Expr) (newType: Type) =
// Get property (at most the last one)
let propInfo = newType.GetProperty ("Item" + string (1 + min i 7))
let res = Expr.PropertyGet (inst, propInfo)
let propInfo = newType.GetProperty("Item" + string (1 + min i 7))
let res = Expr.PropertyGet(inst, propInfo)
// Do we need to add another property get for the last property?
if i < 7 then res
else walk (i - 7) res (newType.GetGenericArguments().[7])
if i < 7 then
res
else
walk (i - 7) res (newType.GetGenericArguments().[7])
walk i e e.Type
let RewriteTupleType (ty:Type) conv =
// Tuples are generic, so lookup only for generic types
assert ty.IsGenericType
let RewriteTupleType (ty: Type) conv =
// Tuples are generic, so lookup only for generic types
assert ty.IsGenericType
let generic = ty.GetGenericTypeDefinition()
match tupleToAnonTypeMap.TryGetValue generic with
| true, mutableTupleType ->
// Recursively transform type arguments
mutableTupleType.MakeGenericType (ty.GetGenericArguments() |> Array.toList |> conv |> Array.ofList)
| _ ->
mutableTupleType.MakeGenericType(ty.GetGenericArguments() |> Array.toList |> conv |> Array.ofList)
| _ ->
assert false
failwith "unreachable"
let (|RecordFieldGetSimplification|_|) (expr:Expr) =
match expr with
| Patterns.PropertyGet(Some (Patterns.NewRecord(typ,els)),propInfo,[]) ->
let fields = Microsoft.FSharp.Reflection.FSharpType.GetRecordFields(typ,System.Reflection.BindingFlags.Public|||System.Reflection.BindingFlags.NonPublic)
match fields |> Array.tryFindIndex (fun p -> p = propInfo) with
| None -> None
| Some i -> if i < els.Length then Some els.[i] else None
| _ -> None
let (|RecordFieldGetSimplification|_|) (expr: Expr) =
match expr with
| Patterns.PropertyGet (Some (Patterns.NewRecord (typ, els)), propInfo, []) ->
let fields =
Microsoft.FSharp.Reflection.FSharpType.GetRecordFields(
typ,
BindingFlags.Public ||| BindingFlags.NonPublic
)
match fields |> Array.tryFindIndex (fun p -> p = propInfo) with
| None -> None
| Some i ->
if i < els.Length then
Some els.[i]
else
None
| _ -> None
/// The generic MethodInfo for Select function
/// Describes how we got from productions of immutable objects to productions of anonymous objects, with enough information
/// that we can invert the process in final query results.
[<NoComparison; NoEquality>]
type ConversionDescription =
type ConversionDescription =
| TupleConv of ConversionDescription list
| RecordConv of Type * ConversionDescription list
| GroupingConv of (* origKeyType: *) Type * (* origElemType: *) Type * ConversionDescription
| GroupingConv (* origKeyType: *) of Type (* origElemType: *) * Type * ConversionDescription
| SeqConv of ConversionDescription
| NoConv
/// Given an type involving immutable tuples and records, logically corresponding to the type produced at a
/// "yield" or "select", convert it to a type involving anonymous objects according to the conversion data.
let rec ConvImmutableTypeToMutableType conv ty =
match conv with
| TupleConv convs ->
let rec ConvImmutableTypeToMutableType conv ty =
match conv with
| TupleConv convs ->
assert (FSharpType.IsTuple ty)
match convs with
match convs with
| x1 :: x2 :: x3 :: x4 :: x5 :: x6 :: x7 :: x8 :: tail ->
RewriteTupleType ty (List.map2 ConvImmutableTypeToMutableType [x1;x2;x3;x4;x5;x6;x7;TupleConv (x8 :: tail)])
| _ ->
RewriteTupleType ty (List.map2 ConvImmutableTypeToMutableType convs)
| RecordConv (_,convs) ->
let els = [ x1; x2; x3; x4; x5; x6; x7; TupleConv(x8 :: tail) ]
RewriteTupleType ty (List.map2 ConvImmutableTypeToMutableType els)
| _ -> RewriteTupleType ty (List.map2 ConvImmutableTypeToMutableType convs)
| RecordConv (_, convs) ->
assert (isPartiallyImmutableRecord ty)
let types = [| for f in FSharpType.GetRecordFields ty -> f.PropertyType |]
ConvImmutableTypeToMutableType (TupleConv convs) (FSharpType.MakeTupleType types)
| GroupingConv (_keyTy,_elemTy,conv) ->
assert ty.IsGenericType
assert (ty.GetGenericTypeDefinition() = typedefof<System.Linq.IGrouping<_, _>>)
ConvImmutableTypeToMutableType (TupleConv convs) (FSharpType.MakeTupleType types)
| GroupingConv (_keyTy, _elemTy, conv) ->
assert ty.IsGenericType
assert (ty.GetGenericTypeDefinition() = typedefof<IGrouping<_, _>>)
let keyt1 = ty.GetGenericArguments().[0]
let valt1 = ty.GetGenericArguments().[1]
typedefof<System.Linq.IGrouping<_, _>>.MakeGenericType [| keyt1; ConvImmutableTypeToMutableType conv valt1 |]
| SeqConv conv ->
typedefof<IGrouping<_, _>>.MakeGenericType [| keyt1; ConvImmutableTypeToMutableType conv valt1 |]
| SeqConv conv ->
assert ty.IsGenericType
let isIQ = ty.GetGenericTypeDefinition() = typedefof<IQueryable<_>>
assert (ty.GetGenericTypeDefinition() = typedefof<seq<_>> || ty.GetGenericTypeDefinition() = typedefof<IQueryable<_>>)
assert
(ty.GetGenericTypeDefinition() = typedefof<seq<_>>
|| ty.GetGenericTypeDefinition() = typedefof<IQueryable<_>>)
let elemt1 = ty.GetGenericArguments().[0]
let args = [| ConvImmutableTypeToMutableType conv elemt1 |]
if isIQ then typedefof<IQueryable<_>>.MakeGenericType args else typedefof<seq<_>>.MakeGenericType args
if isIQ then
typedefof<IQueryable<_>>.MakeGenericType args
else
typedefof<seq<_>>.MakeGenericType args
| NoConv -> ty
let IsNewAnonymousObjectHelperQ =
let mhandle = (methodhandleof (fun x -> LeafExpressionConverter.NewAnonymousObjectHelper x))
let minfo = (System.Reflection.MethodInfo.GetMethodFromHandle mhandle) :?> System.Reflection.MethodInfo
let gmd = minfo.GetGenericMethodDefinition()
(fun tm ->
let IsNewAnonymousObjectHelperQ =
let mhandle =
(methodhandleof (fun x -> LeafExpressionConverter.NewAnonymousObjectHelper x))
let minfo = (MethodInfo.GetMethodFromHandle mhandle) :?> MethodInfo
let gmd = minfo.GetGenericMethodDefinition()
(fun tm ->
match tm with
| Patterns.Call(_obj,minfo2,_args) -> minfo2.IsGenericMethod && (gmd = minfo2.GetGenericMethodDefinition())
| Patterns.Call (_obj, minfo2, _args) ->
minfo2.IsGenericMethod && (gmd = minfo2.GetGenericMethodDefinition())
| _ -> false)
/// Cleanup the use of property-set object constructions in leaf expressions that form parts of F# queries.
let rec CleanupLeaf expr =
if IsNewAnonymousObjectHelperQ expr then expr else // this has already been cleaned up, don't do it twice
// rewrite bottom-up
let expr =
match expr with
| ExprShape.ShapeCombination(comb,args) -> match args with [] -> expr | _ -> ExprShape.RebuildShapeCombination(comb,List.map CleanupLeaf args)
| ExprShape.ShapeLambda(v,body) -> Expr.Lambda (v, CleanupLeaf body)
| ExprShape.ShapeVar _ -> expr
match expr with
// Detect all object construction expressions - wrap them in 'MemberInitializationHelper'
// so that it can be translated to Expression.MemberInit
| ObjectConstruction(var, init, propSets) ->
// Wrap object initialization into a value (
let methInfo = MemberInitializationHelperMeth.MakeGenericMethod [| var.Type |]
Expr.Call (methInfo, [ List.reduceBack (fun a b -> Expr.Sequential (a,b)) (propSets @ [init]) ])
// Detect all anonymous type constructions - wrap them in 'NewAnonymousObjectHelper'
// so that it can be translated to Expression.New with member arguments.
| NewAnonymousObject(ctor, args) ->
let methInfo = NewAnonymousObjectHelperMeth.MakeGenericMethod [| ctor.DeclaringType |]
Expr.Call (methInfo, [ Expr.NewObject (ctor,args) ])
| expr ->
let rec CleanupLeaf expr =
if IsNewAnonymousObjectHelperQ expr then
expr
else // this has already been cleaned up, don't do it twice
// rewrite bottom-up
let expr =
match expr with
| ExprShape.ShapeCombination (comb, args) ->
match args with
| [] -> expr
| _ -> ExprShape.RebuildShapeCombination(comb, List.map CleanupLeaf args)
| ExprShape.ShapeLambda (v, body) -> Expr.Lambda(v, CleanupLeaf body)
| ExprShape.ShapeVar _ -> expr
match expr with
// Detect all object construction expressions - wrap them in 'MemberInitializationHelper'
// so that it can be translated to Expression.MemberInit
| ObjectConstruction (var, init, propSets) ->
// Wrap object initialization into a value (
let methInfo = MemberInitializationHelperMeth.MakeGenericMethod [| var.Type |]
Expr.Call(methInfo, [ List.reduceBack (fun a b -> Expr.Sequential(a, b)) (propSets @ [ init ]) ])
// Detect all anonymous type constructions - wrap them in 'NewAnonymousObjectHelper'
// so that it can be translated to Expression.New with member arguments.
| NewAnonymousObject (ctor, args) ->
let methInfo =
NewAnonymousObjectHelperMeth.MakeGenericMethod [| ctor.DeclaringType |]
Expr.Call(methInfo, [ Expr.NewObject(ctor, args) ])
| expr -> expr
/// Simplify gets of tuples and gets of record fields.
let rec SimplifyConsumingExpr e =
let rec SimplifyConsumingExpr e =
// rewrite bottom-up
let e =
match e with
| ExprShape.ShapeCombination(comb,args) -> ExprShape.RebuildShapeCombination(comb,List.map SimplifyConsumingExpr args)
| ExprShape.ShapeLambda(v,body) -> Expr.Lambda (v, SimplifyConsumingExpr body)
let e =
match e with
| ExprShape.ShapeCombination (comb, args) ->
ExprShape.RebuildShapeCombination(comb, List.map SimplifyConsumingExpr args)
| ExprShape.ShapeLambda (v, body) -> Expr.Lambda(v, SimplifyConsumingExpr body)
| ExprShape.ShapeVar _ -> e
match e with
| Patterns.TupleGet(Patterns.NewTuple els,i) -> els.[i]
| RecordFieldGetSimplification newExpr -> newExpr
| Patterns.TupleGet (Patterns.NewTuple els, i) -> els.[i]
| RecordFieldGetSimplification newExpr -> newExpr
| _ -> e
/// Given the expression part of a "yield" or "select" which produces a result in terms of immutable tuples or immutable records,
/// generate an equivalent expression yielding anonymous objects. Also return the conversion for the immutable-to-mutable correspondence
/// so we can reverse this later.
let rec ProduceMoreMutables tipf expr =
let rec ProduceMoreMutables tipf expr =
match expr with
// Replace immutable tuples by anonymous objects
| Patterns.NewTuple exprs ->
let argExprsNow, argScripts = exprs |> List.map (ProduceMoreMutables tipf) |> List.unzip
NewAnonymousObject argExprsNow, TupleConv argScripts
match expr with
// Replace immutable tuples by anonymous objects
| Patterns.NewTuple exprs ->
let argExprsNow, argScripts =
exprs |> List.map (ProduceMoreMutables tipf) |> List.unzip
NewAnonymousObject argExprsNow, TupleConv argScripts
// Replace immutable records by anonymous objects
| Patterns.NewRecord (typ, args) when isPartiallyImmutableRecord typ ->
let argExprsNow, argScripts =
args |> List.map (ProduceMoreMutables tipf) |> List.unzip
// Replace immutable records by anonymous objects
| Patterns.NewRecord(typ, args) when isPartiallyImmutableRecord typ ->
let argExprsNow, argScripts = args |> List.map (ProduceMoreMutables tipf) |> List.unzip
NewAnonymousObject argExprsNow, RecordConv(typ, argScripts)
| expr ->
tipf expr
| expr -> tipf expr
let MakeSeqConv conv = match conv with NoConv -> NoConv | _ -> SeqConv conv
let MakeSeqConv conv =
match conv with
| NoConv -> NoConv
| _ -> SeqConv conv

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -8,41 +8,59 @@ open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.Operators
open System.Collections.Generic
module HashIdentity =
let inline Structural<'T when 'T : equality> : IEqualityComparer<'T> =
module HashIdentity =
let inline Structural<'T when 'T: equality> : IEqualityComparer<'T> =
LanguagePrimitives.FastGenericEqualityComparer<'T>
let inline LimitedStructural<'T when 'T : equality>(limit) : IEqualityComparer<'T> =
let inline LimitedStructural<'T when 'T: equality> (limit) : IEqualityComparer<'T> =
LanguagePrimitives.FastLimitedGenericEqualityComparer<'T>(limit)
let Reference<'T when 'T : not struct > : IEqualityComparer<'T> =
let Reference<'T when 'T: not struct> : IEqualityComparer<'T> =
{ new IEqualityComparer<'T> with
member _.GetHashCode(x) = LanguagePrimitives.PhysicalHash(x)
member _.Equals(x,y) = LanguagePrimitives.PhysicalEquality x y }
member _.GetHashCode(x) =
LanguagePrimitives.PhysicalHash(x)
let inline NonStructural< 'T when 'T : equality and 'T : (static member ( = ) : 'T * 'T -> bool) > =
member _.Equals(x, y) =
LanguagePrimitives.PhysicalEquality x y
}
let inline NonStructural<'T when 'T: equality and 'T: (static member (=): 'T * 'T -> bool)> =
{ new IEqualityComparer<'T> with
member _.GetHashCode(x) = NonStructuralComparison.hash x
member _.Equals(x, y) = NonStructuralComparison.(=) x y }
member _.GetHashCode(x) =
NonStructuralComparison.hash x
let inline FromFunctions hasher equality : IEqualityComparer<'T> =
let eq = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(equality)
{ new IEqualityComparer<'T> with
member _.GetHashCode(x) = hasher x
member _.Equals(x,y) = eq.Invoke(x,y) }
member _.Equals(x, y) =
NonStructuralComparison.(=) x y
}
module ComparisonIdentity =
let inline FromFunctions hasher equality : IEqualityComparer<'T> =
let eq = OptimizedClosures.FSharpFunc<_, _, _>.Adapt (equality)
let inline Structural<'T when 'T : comparison > : IComparer<'T> =
{ new IEqualityComparer<'T> with
member _.GetHashCode(x) =
hasher x
member _.Equals(x, y) =
eq.Invoke(x, y)
}
module ComparisonIdentity =
let inline Structural<'T when 'T: comparison> : IComparer<'T> =
LanguagePrimitives.FastGenericComparer<'T>
let inline NonStructural< 'T when 'T : (static member ( < ) : 'T * 'T -> bool) and 'T : (static member ( > ) : 'T * 'T -> bool) > : IComparer<'T> =
let inline NonStructural<'T
when 'T: (static member (<): 'T * 'T -> bool) and 'T: (static member (>): 'T * 'T -> bool)> : IComparer<'T> =
{ new IComparer<'T> with
member _.Compare(x,y) = NonStructuralComparison.compare x y }
member _.Compare(x, y) =
NonStructuralComparison.compare x y
}
let FromFunction comparer =
let comparer = OptimizedClosures.FSharpFunc<'T, 'T, int>.Adapt (comparer)
let FromFunction comparer =
let comparer = OptimizedClosures.FSharpFunc<'T,'T,int>.Adapt(comparer)
{ new IComparer<'T> with
member _.Compare(x,y) = comparer.Invoke(x,y) }
member _.Compare(x, y) =
comparer.Invoke(x, y)
}

Просмотреть файл

@ -8,8 +8,9 @@ open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Control
open System.Reflection
open System
open System.Diagnostics
open System.Reflection
module private Atomic =
open System.Threading
@ -17,138 +18,179 @@ module private Atomic =
let inline setWith (thunk: 'a -> 'a) (value: byref<'a>) =
let mutable exchanged = false
let mutable oldValue = value
while not exchanged do
let comparand = oldValue
let newValue = thunk comparand
oldValue <- Interlocked.CompareExchange(&value, newValue, comparand)
if obj.ReferenceEquals(comparand, oldValue) then
exchanged <- true
[<CompiledName("FSharpDelegateEvent`1")>]
type DelegateEvent<'Delegate when 'Delegate :> System.Delegate>() =
let mutable multicast : System.Delegate = null
member x.Trigger(args:obj[]) =
match multicast with
type DelegateEvent<'Delegate when 'Delegate :> System.Delegate>() =
let mutable multicast: System.Delegate = null
member x.Trigger(args: obj[]) =
match multicast with
| null -> ()
| d -> d.DynamicInvoke(args) |> ignore
member x.Publish =
{ new IDelegateEvent<'Delegate> with
member x.Publish =
{ new IDelegateEvent<'Delegate> with
member x.AddHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Combine(value, d)) &multicast
member x.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d)) &multicast }
Atomic.setWith (fun value -> System.Delegate.Remove(value, d)) &multicast
}
type EventDelegee<'Args>(observer: System.IObserver<'Args>) =
static let makeTuple =
static let makeTuple =
if Microsoft.FSharp.Reflection.FSharpType.IsTuple(typeof<'Args>) then
Microsoft.FSharp.Reflection.FSharpValue.PreComputeTupleConstructor(typeof<'Args>)
else
fun _ -> assert false; null // should not be called, one-argument case don't use makeTuple function
fun _ ->
assert false
null // should not be called, one-argument case don't use makeTuple function
member x.Invoke(_sender:obj, args: 'Args) =
observer.OnNext args
member x.Invoke(_sender:obj, a, b) =
let args = makeTuple([|a; b|]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender:obj, a, b, c) =
let args = makeTuple([|a; b; c|]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender:obj, a, b, c, d) =
let args = makeTuple([|a; b; c; d|]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender:obj, a, b, c, d, e) =
let args = makeTuple([|a; b; c; d; e|]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender:obj, a, b, c, d, e, f) =
let args = makeTuple([|a; b; c; d; e; f|]) :?> 'Args
member x.Invoke(_sender: obj, args: 'Args) =
observer.OnNext args
member x.Invoke(_sender: obj, a, b) =
let args = makeTuple ([| a; b |]) :?> 'Args
observer.OnNext args
type EventWrapper<'Delegate,'Args> = delegate of 'Delegate * obj * 'Args -> unit
member x.Invoke(_sender: obj, a, b, c) =
let args = makeTuple ([| a; b; c |]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender: obj, a, b, c, d) =
let args = makeTuple ([| a; b; c; d |]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender: obj, a, b, c, d, e) =
let args = makeTuple ([| a; b; c; d; e |]) :?> 'Args
observer.OnNext args
member x.Invoke(_sender: obj, a, b, c, d, e, f) =
let args = makeTuple ([| a; b; c; d; e; f |]) :?> 'Args
observer.OnNext args
type EventWrapper<'Delegate, 'Args> = delegate of 'Delegate * obj * 'Args -> unit
[<CompiledName("FSharpEvent`2")>]
type Event<'Delegate, 'Args when 'Delegate : delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct>() =
type Event<'Delegate, 'Args
when 'Delegate: delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct>() =
let mutable multicast : 'Delegate = Unchecked.defaultof<_>
let mutable multicast: 'Delegate = Unchecked.defaultof<_>
static let mi, argTypes =
let instanceBindingFlags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.DeclaredOnly
let mi = typeof<'Delegate>.GetMethod("Invoke",instanceBindingFlags)
static let mi, argTypes =
let instanceBindingFlags =
BindingFlags.Instance
||| BindingFlags.Public
||| BindingFlags.NonPublic
||| BindingFlags.DeclaredOnly
let mi = typeof<'Delegate>.GetMethod ("Invoke", instanceBindingFlags)
let actualTypes = mi.GetParameters() |> Array.map (fun p -> p.ParameterType)
mi, actualTypes.[1..]
// For the one-argument case, use an optimization that allows a fast call.
// For the one-argument case, use an optimization that allows a fast call.
// CreateDelegate creates a delegate that is fast to invoke.
static let invoker =
if argTypes.Length = 1 then
(System.Delegate.CreateDelegate(typeof<EventWrapper<'Delegate,'Args>>, mi) :?> EventWrapper<'Delegate,'Args>)
static let invoker =
if argTypes.Length = 1 then
(Delegate.CreateDelegate(typeof<EventWrapper<'Delegate, 'Args>>, mi) :?> EventWrapper<'Delegate, 'Args>)
else
null
// For the multi-arg case, use a slower DynamicInvoke.
static let invokeInfo =
let instanceBindingFlags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.DeclaredOnly
let mi =
typeof<EventDelegee<'Args>>.GetMethods(instanceBindingFlags)
|> Seq.filter(fun mi -> mi.Name = "Invoke" && mi.GetParameters().Length = argTypes.Length + 1)
let instanceBindingFlags =
BindingFlags.Instance
||| BindingFlags.Public
||| BindingFlags.NonPublic
||| BindingFlags.DeclaredOnly
let mi =
typeof<EventDelegee<'Args>>.GetMethods (instanceBindingFlags)
|> Seq.filter (fun mi -> mi.Name = "Invoke" && mi.GetParameters().Length = argTypes.Length + 1)
|> Seq.exactlyOne
if mi.IsGenericMethodDefinition then
mi.MakeGenericMethod argTypes
else
mi
else
mi
member x.Trigger(sender:obj,args: 'Args) =
// Copy multicast value into local variable to avoid changing during member call.
member x.Trigger(sender: obj, args: 'Args) =
// Copy multicast value into local variable to avoid changing during member call.
let multicast = multicast
match box multicast with
| null -> ()
| _ ->
match invoker with
| null ->
let args = Array.append [| sender |] (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(box args))
match box multicast with
| null -> ()
| _ ->
match invoker with
| null ->
let args =
Array.append [| sender |] (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(box args))
multicast.DynamicInvoke(args) |> ignore
| _ ->
// For the one-argument case, use an optimization that allows a fast call.
| _ ->
// For the one-argument case, use an optimization that allows a fast call.
// CreateDelegate creates a delegate that is fast to invoke.
invoker.Invoke(multicast, sender, args) |> ignore
member x.Publish =
{ new obj() with
member x.ToString() = "<published event>"
interface IEvent<'Delegate,'Args> with
member e.AddHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> 'Delegate) &multicast
member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> 'Delegate) &multicast
interface System.IObservable<'Args> with
member e.Subscribe(observer) =
let obj = new EventDelegee<'Args>(observer)
let h = System.Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> 'Delegate
(e :?> IDelegateEvent<'Delegate>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() = (e :?> IDelegateEvent<'Delegate>).RemoveHandler(h) } }
member x.ToString() =
"<published event>"
interface IEvent<'Delegate, 'Args> with
member e.AddHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> 'Delegate) &multicast
member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> 'Delegate) &multicast
interface System.IObservable<'Args> with
member e.Subscribe(observer) =
let obj = new EventDelegee<'Args>(observer)
let h = Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> 'Delegate
(e :?> IDelegateEvent<'Delegate>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() =
(e :?> IDelegateEvent<'Delegate>).RemoveHandler(h)
}
}
[<CompiledName("FSharpEvent`1")>]
type Event<'T> =
val mutable multicast : Handler<'T>
type Event<'T> =
val mutable multicast: Handler<'T>
new() = { multicast = null }
member x.Trigger(arg:'T) =
match x.multicast with
member x.Trigger(arg: 'T) =
match x.multicast with
| null -> ()
| d -> d.Invoke(null,arg) |> ignore
| d -> d.Invoke(null, arg) |> ignore
member x.Publish =
{ new obj() with
member x.ToString() = "<published event>"
interface IEvent<'T> with
member e.AddHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T>) &x.multicast
member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T>) &x.multicast
interface System.IObservable<'T> with
member e.Subscribe(observer) =
let h = new Handler<_>(fun sender args -> observer.OnNext(args))
(e :?> IEvent<_,_>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() = (e :?> IEvent<_,_>).RemoveHandler(h) } }
member x.ToString() =
"<published event>"
interface IEvent<'T> with
member e.AddHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T>) &x.multicast
member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T>) &x.multicast
interface System.IObservable<'T> with
member e.Subscribe(observer) =
let h = new Handler<_>(fun sender args -> observer.OnNext(args))
(e :?> IEvent<_, _>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() =
(e :?> IEvent<_, _>).RemoveHandler(h)
}
}

Просмотреть файл

@ -34,7 +34,8 @@ type DelegateEvent<'Delegate when 'Delegate :> System.Delegate> =
///
/// <category index="3">Events and Observables</category>
[<CompiledName("FSharpEvent`2")>]
type Event<'Delegate, 'Args when 'Delegate: delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct> =
type Event<'Delegate, 'Args
when 'Delegate: delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct> =
/// <summary>Creates an event object suitable for delegate types following the standard .NET Framework convention of a first 'sender' argument.</summary>
/// <returns>The created event.</returns>

Просмотреть файл

@ -9,73 +9,92 @@ open Microsoft.FSharp.Control
[<RequireQualifiedAccess>]
module Event =
[<CompiledName("Create")>]
let create<'T>() =
let ev = new Event<'T>()
let create<'T> () =
let ev = new Event<'T>()
ev.Trigger, ev.Publish
[<CompiledName("Map")>]
let map mapping (sourceEvent: IEvent<'Delegate,'T>) =
let ev = new Event<_>()
let map mapping (sourceEvent: IEvent<'Delegate, 'T>) =
let ev = new Event<_>()
sourceEvent.Add(fun x -> ev.Trigger(mapping x))
ev.Publish
[<CompiledName("Filter")>]
let filter predicate (sourceEvent: IEvent<'Delegate,'T>) =
let ev = new Event<_>()
let filter predicate (sourceEvent: IEvent<'Delegate, 'T>) =
let ev = new Event<_>()
sourceEvent.Add(fun x -> if predicate x then ev.Trigger x)
ev.Publish
[<CompiledName("Partition")>]
let partition predicate (sourceEvent: IEvent<'Delegate,'T>) =
let ev1 = new Event<_>()
let ev2 = new Event<_>()
sourceEvent.Add(fun x -> if predicate x then ev1.Trigger x else ev2.Trigger x)
ev1.Publish,ev2.Publish
let partition predicate (sourceEvent: IEvent<'Delegate, 'T>) =
let ev1 = new Event<_>()
let ev2 = new Event<_>()
sourceEvent.Add(fun x ->
if predicate x then
ev1.Trigger x
else
ev2.Trigger x)
ev1.Publish, ev2.Publish
[<CompiledName("Choose")>]
let choose chooser (sourceEvent: IEvent<'Delegate,'T>) =
let ev = new Event<_>()
sourceEvent.Add(fun x -> match chooser x with None -> () | Some r -> ev.Trigger r)
let choose chooser (sourceEvent: IEvent<'Delegate, 'T>) =
let ev = new Event<_>()
sourceEvent.Add(fun x ->
match chooser x with
| None -> ()
| Some r -> ev.Trigger r)
ev.Publish
[<CompiledName("Scan")>]
let scan collector state (sourceEvent: IEvent<'Delegate,'T>) =
let scan collector state (sourceEvent: IEvent<'Delegate, 'T>) =
let mutable state = state
let ev = new Event<_>()
let ev = new Event<_>()
sourceEvent.Add(fun msg ->
let z = state
let z = collector z msg
state <- z;
ev.Trigger(z))
let z = state
let z = collector z msg
state <- z
ev.Trigger(z))
ev.Publish
[<CompiledName("Add")>]
let add callback (sourceEvent: IEvent<'Delegate,'T>) = sourceEvent.Add(callback)
let add callback (sourceEvent: IEvent<'Delegate, 'T>) =
sourceEvent.Add(callback)
[<CompiledName("Pairwise")>]
let pairwise (sourceEvent : IEvent<'Delegate,'T>) : IEvent<'T * 'T> =
let ev = new Event<'T * 'T>()
let pairwise (sourceEvent: IEvent<'Delegate, 'T>) : IEvent<'T * 'T> =
let ev = new Event<'T * 'T>()
let mutable lastArgs = None
sourceEvent.Add(fun args2 ->
(match lastArgs with
| None -> ()
| Some args1 -> ev.Trigger(args1,args2))
sourceEvent.Add(fun args2 ->
(match lastArgs with
| None -> ()
| Some args1 -> ev.Trigger(args1, args2))
lastArgs <- Some args2)
ev.Publish
[<CompiledName("Merge")>]
let merge (event1: IEvent<'Del1,'T>) (event2: IEvent<'Del2,'T>) =
let ev = new Event<_>()
let merge (event1: IEvent<'Del1, 'T>) (event2: IEvent<'Del2, 'T>) =
let ev = new Event<_>()
event1.Add(fun x -> ev.Trigger(x))
event2.Add(fun x -> ev.Trigger(x))
ev.Publish
[<CompiledName("Split")>]
let split (splitter : 'T -> Choice<'U1,'U2>) (sourceEvent: IEvent<'Delegate,'T>) =
let ev1 = new Event<_>()
let ev2 = new Event<_>()
sourceEvent.Add(fun x -> match splitter x with Choice1Of2 y -> ev1.Trigger(y) | Choice2Of2 z -> ev2.Trigger(z))
ev1.Publish,ev2.Publish
let split (splitter: 'T -> Choice<'U1, 'U2>) (sourceEvent: IEvent<'Delegate, 'T>) =
let ev1 = new Event<_>()
let ev2 = new Event<_>()
sourceEvent.Add(fun x ->
match splitter x with
| Choice1Of2 y -> ev1.Trigger(y)
| Choice2Of2 z -> ev2.Trigger(z))
ev1.Publish, ev2.Publish

Просмотреть файл

@ -16,112 +16,145 @@ module ExtraTopLevelOperators =
open Microsoft.FSharp.Primitives.Basics
open Microsoft.FSharp.Core.CompilerServices
let inline checkNonNullNullArg argName arg =
match box arg with
| null -> nullArg argName
let inline checkNonNullNullArg argName arg =
match box arg with
| null -> nullArg argName
| _ -> ()
let inline checkNonNullInvalidArg argName message arg =
match box arg with
let inline checkNonNullInvalidArg argName message arg =
match box arg with
| null -> invalidArg argName message
| _ -> ()
[<CompiledName("CreateSet")>]
let set elements = Collections.Set.ofSeq elements
let set elements =
Collections.Set.ofSeq elements
let dummyArray = [||]
let inline dont_tail_call f =
let inline dont_tail_call f =
let result = f ()
dummyArray.Length |> ignore // pretty stupid way to avoid tail call, would be better if attribute existed, but this should be inlineable by the JIT
result
let inline ICollection_Contains<'collection,'item when 'collection :> ICollection<'item>> (collection:'collection) (item:'item) =
let inline ICollection_Contains<'collection, 'item when 'collection :> ICollection<'item>>
(collection: 'collection)
(item: 'item)
=
collection.Contains item
[<DebuggerDisplay("Count = {Count}")>]
[<DebuggerTypeProxy(typedefof<DictDebugView<_,_,_>>)>]
type DictImpl<'SafeKey,'Key,'T>(t : Dictionary<'SafeKey,'T>, makeSafeKey : 'Key->'SafeKey, getKey : 'SafeKey->'Key) =
[<DebuggerTypeProxy(typedefof<DictDebugView<_, _, _>>)>]
type DictImpl<'SafeKey, 'Key, 'T>
(
t: Dictionary<'SafeKey, 'T>,
makeSafeKey: 'Key -> 'SafeKey,
getKey: 'SafeKey -> 'Key
) =
#if NETSTANDARD
static let emptyEnumerator = (Array.empty<KeyValuePair<'Key, 'T>> :> seq<_>).GetEnumerator()
static let emptyEnumerator =
(Array.empty<KeyValuePair<'Key, 'T>> :> seq<_>).GetEnumerator()
#endif
member _.Count = t.Count
// Give a read-only view of the dictionary
interface IDictionary<'Key, 'T> with
member _.Item
member _.Item
with get x = dont_tail_call (fun () -> t.[makeSafeKey x])
and set _ _ = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
and set _ _ = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Keys =
member _.Keys =
let keys = t.Keys
{ new ICollection<'Key> with
member _.Add(x) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Clear() = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
{ new ICollection<'Key> with
member _.Add(x) =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Remove(x) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Clear() =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Contains(x) = t.ContainsKey (makeSafeKey x)
member _.Remove(x) =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.CopyTo(arr,i) =
let mutable n = 0
for k in keys do
arr.[i+n] <- getKey k
n <- n + 1
member _.Contains(x) =
t.ContainsKey(makeSafeKey x)
member _.IsReadOnly = true
member _.CopyTo(arr, i) =
let mutable n = 0
member _.Count = keys.Count
for k in keys do
arr.[i + n] <- getKey k
n <- n + 1
member _.IsReadOnly = true
member _.Count = keys.Count
interface IEnumerable<'Key> with
member _.GetEnumerator() = (keys |> Seq.map getKey).GetEnumerator()
member _.GetEnumerator() =
(keys |> Seq.map getKey).GetEnumerator()
interface System.Collections.IEnumerable with
member _.GetEnumerator() = ((keys |> Seq.map getKey) :> System.Collections.IEnumerable).GetEnumerator() }
member _.GetEnumerator() =
((keys |> Seq.map getKey) :> System.Collections.IEnumerable).GetEnumerator()
}
member _.Values = upcast t.Values
member _.Add(_,_) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Add(_, _) =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.ContainsKey(k) = dont_tail_call (fun () -> t.ContainsKey(makeSafeKey k))
member _.ContainsKey(k) =
dont_tail_call (fun () -> t.ContainsKey(makeSafeKey k))
member _.TryGetValue(k,r) =
member _.TryGetValue(k, r) =
let safeKey = makeSafeKey k
if t.ContainsKey(safeKey) then (r <- t.[safeKey]; true) else false
member _.Remove(_ : 'Key) = (raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated))) : bool)
if t.ContainsKey(safeKey) then
(r <- t.[safeKey]
true)
else
false
member _.Remove(_: 'Key) =
(raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated))): bool)
interface IReadOnlyDictionary<'Key, 'T> with
member _.Item with get key = t.[makeSafeKey key]
member _.Item
with get key = t.[makeSafeKey key]
member _.Keys = t.Keys |> Seq.map getKey
member _.TryGetValue(key, r) =
match t.TryGetValue (makeSafeKey key) with
match t.TryGetValue(makeSafeKey key) with
| false, _ -> false
| true, value ->
r <- value
true
member _.Values = (t :> IReadOnlyDictionary<_,_>).Values
member _.Values = (t :> IReadOnlyDictionary<_, _>).Values
member _.ContainsKey k = t.ContainsKey (makeSafeKey k)
member _.ContainsKey k =
t.ContainsKey(makeSafeKey k)
interface ICollection<KeyValuePair<'Key, 'T>> with
interface ICollection<KeyValuePair<'Key, 'T>> with
member _.Add(_) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Add(_) =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Clear() = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Clear() =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Remove(_) = raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Remove(_) =
raise (NotSupportedException(SR.GetString(SR.thisValueCannotBeMutated)))
member _.Contains(KeyValue(k,v)) = ICollection_Contains t (KeyValuePair<_,_>(makeSafeKey k,v))
member _.Contains(KeyValue (k, v)) =
ICollection_Contains t (KeyValuePair<_, _>(makeSafeKey k, v))
member _.CopyTo(arr,i) =
let mutable n = 0
for (KeyValue(k,v)) in t do
arr.[i+n] <- KeyValuePair<_,_>(getKey k,v)
member _.CopyTo(arr, i) =
let mutable n = 0
for (KeyValue (k, v)) in t do
arr.[i + n] <- KeyValuePair<_, _>(getKey k, v)
n <- n + 1
member _.IsReadOnly = true
@ -135,104 +168,129 @@ module ExtraTopLevelOperators =
member _.GetEnumerator() =
// We use an array comprehension here instead of seq {} as otherwise we get incorrect
// IEnumerator.Reset() and IEnumerator.Current semantics.
// IEnumerator.Reset() and IEnumerator.Current semantics.
// Coreclr has a bug with SZGenericEnumerators --- implement a correct enumerator. On desktop use the desktop implementation because it's ngened.
#if !NETSTANDARD
let kvps = [| for (KeyValue (k,v)) in t -> KeyValuePair (getKey k, v) |] :> seq<_>
#if !NETSTANDARD
let kvps = [| for (KeyValue (k, v)) in t -> KeyValuePair(getKey k, v) |] :> seq<_>
kvps.GetEnumerator()
#else
let endIndex = t.Count
if endIndex = 0 then emptyEnumerator
if endIndex = 0 then
emptyEnumerator
else
let kvps = [| for (KeyValue (k,v)) in t -> KeyValuePair (getKey k, v) |]
let kvps = [| for (KeyValue (k, v)) in t -> KeyValuePair(getKey k, v) |]
let mutable index = -1
let current () =
if index < 0 then raise <| InvalidOperationException(SR.GetString(SR.enumerationNotStarted))
if index >= endIndex then raise <| InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))
if index < 0 then
raise <| InvalidOperationException(SR.GetString(SR.enumerationNotStarted))
if index >= endIndex then
raise <| InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))
kvps.[index]
{new IEnumerator<_> with
{ new IEnumerator<_> with
member _.Current = current ()
interface System.Collections.IEnumerator with
member _.Current = box(current())
member _.Current = box (current ())
member _.MoveNext() =
if index < endIndex then
index <- index + 1
index < endIndex
else false
member _.MoveNext() =
if index < endIndex then
index <- index + 1
index < endIndex
else
false
member _.Reset() = index <- -1
interface System.IDisposable with
member _.Dispose() = () }
member _.Reset() =
index <- -1
interface System.IDisposable with
member _.Dispose() =
()
}
#endif
interface System.Collections.IEnumerable with
member _.GetEnumerator() =
// We use an array comprehension here instead of seq {} as otherwise we get incorrect
// IEnumerator.Reset() and IEnumerator.Current semantics.
let kvps = [| for (KeyValue (k,v)) in t -> KeyValuePair (getKey k, v) |] :> System.Collections.IEnumerable
// IEnumerator.Reset() and IEnumerator.Current semantics.
let kvps =
[| for (KeyValue (k, v)) in t -> KeyValuePair(getKey k, v) |] :> System.Collections.IEnumerable
kvps.GetEnumerator()
and DictDebugView<'SafeKey,'Key,'T>(d:DictImpl<'SafeKey,'Key,'T>) =
and DictDebugView<'SafeKey, 'Key, 'T>(d: DictImpl<'SafeKey, 'Key, 'T>) =
[<DebuggerBrowsable(DebuggerBrowsableState.RootHidden)>]
member _.Items = Array.ofSeq d
let inline dictImpl (comparer:IEqualityComparer<'SafeKey>) (makeSafeKey : 'Key->'SafeKey) (getKey : 'SafeKey->'Key) (l:seq<'Key*'T>) =
let inline dictImpl
(comparer: IEqualityComparer<'SafeKey>)
(makeSafeKey: 'Key -> 'SafeKey)
(getKey: 'SafeKey -> 'Key)
(l: seq<'Key * 'T>)
=
let t = Dictionary comparer
for (k,v) in l do
for (k, v) in l do
t.[makeSafeKey k] <- v
DictImpl(t, makeSafeKey, getKey)
// We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance
let dictValueType (l:seq<'Key*'T>) =
let dictValueType (l: seq<'Key * 'T>) =
dictImpl HashIdentity.Structural<'Key> id id l
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let dictRefType (l:seq<'Key*'T>) =
let dictRefType (l: seq<'Key * 'T>) =
dictImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun k -> RuntimeHelpers.StructBox k) (fun sb -> sb.Value) l
[<CompiledName("CreateDictionary")>]
let dict (keyValuePairs:seq<'Key*'T>) : IDictionary<'Key,'T> =
let dict (keyValuePairs: seq<'Key * 'T>) : IDictionary<'Key, 'T> =
if typeof<'Key>.IsValueType then
dictValueType keyValuePairs
else
dictRefType keyValuePairs
[<CompiledName("CreateReadOnlyDictionary")>]
let readOnlyDict (keyValuePairs:seq<'Key*'T>) : IReadOnlyDictionary<'Key,'T> =
let readOnlyDict (keyValuePairs: seq<'Key * 'T>) : IReadOnlyDictionary<'Key, 'T> =
if typeof<'Key>.IsValueType then
dictValueType keyValuePairs
else
dictRefType keyValuePairs
let getArray (vals : seq<'T>) =
let getArray (vals: seq<'T>) =
match vals with
| :? ('T[]) as arr -> arr
| _ -> Seq.toArray vals
[<CompiledName("CreateArray2D")>]
let array2D (rows : seq<#seq<'T>>) =
let array2D (rows: seq<#seq<'T>>) =
checkNonNullNullArg "rows" rows
let rowsArr = getArray rows
let m = rowsArr.Length
if m = 0
then Array2D.zeroCreate<'T> 0 0
if m = 0 then
Array2D.zeroCreate<'T> 0 0
else
checkNonNullInvalidArg "rows" (SR.GetString(SR.nullsNotAllowedInArray)) rowsArr.[0]
let firstRowArr = getArray rowsArr.[0]
let n = firstRowArr.Length
let res = Array2D.zeroCreate<'T> m n
for j in 0..(n-1) do
res.[0,j] <- firstRowArr.[j]
for i in 1..(m-1) do
for j in 0 .. (n - 1) do
res.[0, j] <- firstRowArr.[j]
for i in 1 .. (m - 1) do
checkNonNullInvalidArg "rows" (SR.GetString(SR.nullsNotAllowedInArray)) rowsArr.[i]
let rowiArr = getArray rowsArr.[i]
if rowiArr.Length <> n then invalidArg "vals" (SR.GetString(SR.arraysHadDifferentLengths))
for j in 0..(n-1) do
res.[i,j] <- rowiArr.[j]
if rowiArr.Length <> n then
invalidArg "vals" (SR.GetString(SR.arraysHadDifferentLengths))
for j in 0 .. (n - 1) do
res.[i, j] <- rowiArr.[j]
res
[<CompiledName("PrintFormatToString")>]
@ -244,28 +302,28 @@ module ExtraTopLevelOperators =
Printf.failwithf format
[<CompiledName("PrintFormatToTextWriter")>]
let fprintf (textWriter:TextWriter) format =
Printf.fprintf textWriter format
let fprintf (textWriter: TextWriter) format =
Printf.fprintf textWriter format
[<CompiledName("PrintFormatLineToTextWriter")>]
let fprintfn (textWriter:TextWriter) format =
Printf.fprintfn textWriter format
let fprintfn (textWriter: TextWriter) format =
Printf.fprintfn textWriter format
[<CompiledName("PrintFormat")>]
let printf format =
Printf.printf format
Printf.printf format
[<CompiledName("PrintFormatToError")>]
let eprintf format =
Printf.eprintf format
Printf.eprintf format
[<CompiledName("PrintFormatLine")>]
let printfn format =
Printf.printfn format
Printf.printfn format
[<CompiledName("PrintFormatLineToError")>]
let eprintfn format =
Printf.eprintfn format
Printf.eprintfn format
[<CompiledName("FailWith")>]
let failwith s =
@ -275,167 +333,205 @@ module ExtraTopLevelOperators =
let async = AsyncBuilder()
[<CompiledName("ToSingle")>]
let inline single value = float32 value
let inline single value =
float32 value
[<CompiledName("ToDouble")>]
let inline double value = float value
let inline double value =
float value
[<CompiledName("ToByte")>]
let inline uint8 value = byte value
let inline uint8 value =
byte value
[<CompiledName("ToSByte")>]
let inline int8 value = sbyte value
let inline int8 value =
sbyte value
module Checked =
module Checked =
[<CompiledName("ToByte")>]
let inline uint8 value = Checked.byte value
let inline uint8 value =
Checked.byte value
[<CompiledName("ToSByte")>]
let inline int8 value = Checked.sbyte value
let inline int8 value =
Checked.sbyte value
[<CompiledName("SpliceExpression")>]
let (~%) (expression:Microsoft.FSharp.Quotations.Expr<'T>) : 'T =
let (~%) (expression: Microsoft.FSharp.Quotations.Expr<'T>) : 'T =
ignore expression
raise (InvalidOperationException(SR.GetString(SR.firstClassUsesOfSplice)))
[<CompiledName("SpliceUntypedExpression")>]
let (~%%) (expression: Microsoft.FSharp.Quotations.Expr) : 'T =
ignore expression
raise (InvalidOperationException (SR.GetString(SR.firstClassUsesOfSplice)))
raise (InvalidOperationException(SR.GetString(SR.firstClassUsesOfSplice)))
[<assembly: AutoOpen("Microsoft.FSharp")>]
[<assembly: AutoOpen("Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators")>]
[<assembly: AutoOpen("Microsoft.FSharp.Core")>]
[<assembly: AutoOpen("Microsoft.FSharp.Collections")>]
[<assembly: AutoOpen("Microsoft.FSharp.Control")>]
#if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE
#if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE
[<assembly: AutoOpen("Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority")>]
[<assembly: AutoOpen("Microsoft.FSharp.Control.TaskBuilderExtensions.MediumPriority")>]
[<assembly: AutoOpen("Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority")>]
#endif
#endif
[<assembly: AutoOpen("Microsoft.FSharp.Linq.QueryRunExtensions.LowPriority")>]
[<assembly: AutoOpen("Microsoft.FSharp.Linq.QueryRunExtensions.HighPriority")>]
do()
do ()
[<CompiledName("LazyPattern")>]
let (|Lazy|) (input:Lazy<_>) =
let (|Lazy|) (input: Lazy<_>) =
input.Force()
let query = Microsoft.FSharp.Linq.QueryBuilder()
namespace Microsoft.FSharp.Core.CompilerServices
open System
open System.Reflection
open Microsoft.FSharp.Core
open Microsoft.FSharp.Control
open Microsoft.FSharp.Quotations
open System
open System.Reflection
open Microsoft.FSharp.Core
open Microsoft.FSharp.Control
open Microsoft.FSharp.Quotations
/// <summary>Represents the product of two measure expressions when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureProduct<'Measure1, 'Measure2>() = class end
/// <summary>Represents the product of two measure expressions when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureProduct<'Measure1, 'Measure2>() =
class
end
/// <summary>Represents the inverse of a measure expressions when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureInverse<'Measure> = class end
/// <summary>Represents the inverse of a measure expressions when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureInverse<'Measure> =
class
end
/// <summary>Represents the '1' measure expression when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureOne = class end
/// <summary>Represents the '1' measure expression when returned as a generic argument of a provided type.</summary>
[<Sealed>]
type MeasureOne =
class
end
[<AttributeUsage(AttributeTargets.Class, AllowMultiple = false)>]
type TypeProviderAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.Class, AllowMultiple = false)>]
type TypeProviderAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)>]
type TypeProviderAssemblyAttribute(assemblyName : string) =
inherit System.Attribute()
new () = TypeProviderAssemblyAttribute(null)
[<AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)>]
type TypeProviderAssemblyAttribute(assemblyName: string) =
inherit System.Attribute()
new() = TypeProviderAssemblyAttribute(null)
member _.AssemblyName = assemblyName
member _.AssemblyName = assemblyName
[<AttributeUsage(AttributeTargets.All, AllowMultiple = false)>]
type TypeProviderXmlDocAttribute(commentText: string) =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.All, AllowMultiple = false)>]
type TypeProviderXmlDocAttribute(commentText: string) =
inherit System.Attribute()
member _.CommentText = commentText
member _.CommentText = commentText
[<AttributeUsage(AttributeTargets.All, AllowMultiple = false)>]
type TypeProviderDefinitionLocationAttribute() =
inherit System.Attribute()
let mutable filePath : string = null
let mutable line : int = 0
let mutable column : int = 0
[<AttributeUsage(AttributeTargets.All, AllowMultiple = false)>]
type TypeProviderDefinitionLocationAttribute() =
inherit System.Attribute()
let mutable filePath: string = null
let mutable line: int = 0
let mutable column: int = 0
member _.FilePath with get() = filePath and set v = filePath <- v
member _.FilePath
with get () = filePath
and set v = filePath <- v
member _.Line with get() = line and set v = line <- v
member _.Line
with get () = line
and set v = line <- v
member _.Column with get() = column and set v = column <- v
member _.Column
with get () = column
and set v = column <- v
[<AttributeUsage(AttributeTargets.Class ||| AttributeTargets.Interface ||| AttributeTargets.Struct ||| AttributeTargets.Delegate, AllowMultiple = false)>]
type TypeProviderEditorHideMethodsAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.Class
||| AttributeTargets.Interface
||| AttributeTargets.Struct
||| AttributeTargets.Delegate,
AllowMultiple = false)>]
type TypeProviderEditorHideMethodsAttribute() =
inherit System.Attribute()
/// <summary>Additional type attribute flags related to provided types</summary>
type TypeProviderTypeAttributes =
| SuppressRelocate = 0x80000000
| IsErased = 0x40000000
/// <summary>Additional type attribute flags related to provided types</summary>
type TypeProviderTypeAttributes =
| SuppressRelocate = 0x80000000
| IsErased = 0x40000000
type TypeProviderConfig( systemRuntimeContainsType : string -> bool ) =
let mutable resolutionFolder: string = null
let mutable runtimeAssembly: string = null
let mutable referencedAssemblies: string[] = null
let mutable temporaryFolder: string = null
let mutable isInvalidationSupported: bool = false
let mutable useResolutionFolderAtRuntime: bool = false
let mutable systemRuntimeAssemblyVersion: System.Version = null
type TypeProviderConfig(systemRuntimeContainsType: string -> bool) =
let mutable resolutionFolder: string = null
let mutable runtimeAssembly: string = null
let mutable referencedAssemblies: string[] = null
let mutable temporaryFolder: string = null
let mutable isInvalidationSupported: bool = false
let mutable useResolutionFolderAtRuntime: bool = false
let mutable systemRuntimeAssemblyVersion: System.Version = null
member _.ResolutionFolder with get() = resolutionFolder and set v = resolutionFolder <- v
member _.ResolutionFolder
with get () = resolutionFolder
and set v = resolutionFolder <- v
member _.RuntimeAssembly with get() = runtimeAssembly and set v = runtimeAssembly <- v
member _.RuntimeAssembly
with get () = runtimeAssembly
and set v = runtimeAssembly <- v
member _.ReferencedAssemblies with get() = referencedAssemblies and set v = referencedAssemblies <- v
member _.ReferencedAssemblies
with get () = referencedAssemblies
and set v = referencedAssemblies <- v
member _.TemporaryFolder with get() = temporaryFolder and set v = temporaryFolder <- v
member _.TemporaryFolder
with get () = temporaryFolder
and set v = temporaryFolder <- v
member _.IsInvalidationSupported with get() = isInvalidationSupported and set v = isInvalidationSupported <- v
member _.IsInvalidationSupported
with get () = isInvalidationSupported
and set v = isInvalidationSupported <- v
member _.IsHostedExecution with get() = useResolutionFolderAtRuntime and set v = useResolutionFolderAtRuntime <- v
member _.IsHostedExecution
with get () = useResolutionFolderAtRuntime
and set v = useResolutionFolderAtRuntime <- v
member _.SystemRuntimeAssemblyVersion with get() = systemRuntimeAssemblyVersion and set v = systemRuntimeAssemblyVersion <- v
member _.SystemRuntimeAssemblyVersion
with get () = systemRuntimeAssemblyVersion
and set v = systemRuntimeAssemblyVersion <- v
member _.SystemRuntimeContainsType (typeName: string) = systemRuntimeContainsType typeName
member _.SystemRuntimeContainsType(typeName: string) =
systemRuntimeContainsType typeName
type IProvidedNamespace =
type IProvidedNamespace =
abstract NamespaceName: string
abstract NamespaceName: string
abstract GetNestedNamespaces: unit -> IProvidedNamespace[]
abstract GetNestedNamespaces: unit -> IProvidedNamespace[]
abstract GetTypes: unit -> Type[]
abstract GetTypes: unit -> Type[]
abstract ResolveTypeName: typeName: string -> Type
abstract ResolveTypeName: typeName: string -> Type
type ITypeProvider =
inherit System.IDisposable
type ITypeProvider =
inherit System.IDisposable
abstract GetNamespaces: unit -> IProvidedNamespace[]
abstract GetNamespaces: unit -> IProvidedNamespace[]
abstract GetStaticParameters: typeWithoutArguments: Type -> ParameterInfo[]
abstract GetStaticParameters: typeWithoutArguments: Type -> ParameterInfo[]
abstract ApplyStaticArguments: typeWithoutArguments: Type * typePathWithArguments: string[] * staticArguments:obj[] -> Type
abstract ApplyStaticArguments:
typeWithoutArguments: Type * typePathWithArguments: string[] * staticArguments: obj[] -> Type
abstract GetInvokerExpression: syntheticMethodBase:MethodBase * parameters:Expr[] -> Expr
abstract GetInvokerExpression: syntheticMethodBase: MethodBase * parameters: Expr[] -> Expr
[<CLIEvent>]
abstract Invalidate : IEvent<System.EventHandler, System.EventArgs>
abstract GetGeneratedAssemblyContents: assembly:System.Reflection.Assembly -> byte[]
[<CLIEvent>]
abstract Invalidate: IEvent<System.EventHandler, System.EventArgs>
type ITypeProvider2 =
abstract GetStaticParametersForMethod: methodWithoutArguments:MethodBase -> ParameterInfo[]
abstract GetGeneratedAssemblyContents: assembly: System.Reflection.Assembly -> byte[]
abstract ApplyStaticArgumentsForMethod: methodWithoutArguments:MethodBase * methodNameWithArguments:string * staticArguments:obj[] -> MethodBase
type ITypeProvider2 =
abstract GetStaticParametersForMethod: methodWithoutArguments: MethodBase -> ParameterInfo[]
abstract ApplyStaticArgumentsForMethod:
methodWithoutArguments: MethodBase * methodNameWithArguments: string * staticArguments: obj[] -> MethodBase

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -43,8 +43,9 @@ module internal List =
val distinctWithComparer: System.Collections.Generic.IEqualityComparer<'T> -> 'T list -> 'T list
val distinctByWithComparer: System.Collections.Generic.IEqualityComparer<'Key> -> ('T -> 'Key) -> list: 'T list -> 'T list
when 'Key: equality
val distinctByWithComparer:
System.Collections.Generic.IEqualityComparer<'Key> -> ('T -> 'Key) -> list: 'T list -> 'T list
when 'Key: equality
val init: int -> (int -> 'T) -> 'T list
val filter: predicate: ('T -> bool) -> 'T list -> 'T list

Просмотреть файл

@ -18,13 +18,22 @@ module AsyncHelpers =
async {
let resultCell = new ResultCell<_>()
let! cancellationToken = Async.CancellationToken
let start a f =
Async.StartWithContinuationsUsingDispatchInfo(a,
(fun res -> resultCell.RegisterResult(f res |> AsyncResult.Ok, reuseThread=false) |> ignore),
(fun edi -> resultCell.RegisterResult(edi |> AsyncResult.Error, reuseThread=false) |> ignore),
(fun oce -> resultCell.RegisterResult(oce |> AsyncResult.Canceled, reuseThread=false) |> ignore),
Async.StartWithContinuationsUsingDispatchInfo(
a,
(fun res ->
resultCell.RegisterResult(f res |> AsyncResult.Ok, reuseThread = false)
|> ignore),
(fun edi ->
resultCell.RegisterResult(edi |> AsyncResult.Error, reuseThread = false)
|> ignore),
(fun oce ->
resultCell.RegisterResult(oce |> AsyncResult.Canceled, reuseThread = false)
|> ignore),
cancellationToken = cancellationToken
)
)
start a1 Choice1Of2
start a2 Choice2Of2
// Note: It is ok to use "NoDirectCancel" here because the started computations use the same
@ -37,12 +46,14 @@ module AsyncHelpers =
let timeout msec cancellationToken =
assert (msec >= 0)
let resultCell = new ResultCell<_>()
Async.StartWithContinuations(
computation=Async.Sleep msec,
continuation=(fun () -> resultCell.RegisterResult((), reuseThread = false) |> ignore),
exceptionContinuation=ignore,
cancellationContinuation=ignore,
cancellationToken = cancellationToken)
computation = Async.Sleep msec,
continuation = (fun () -> resultCell.RegisterResult((), reuseThread = false) |> ignore),
exceptionContinuation = ignore,
cancellationContinuation = ignore,
cancellationToken = cancellationToken
)
// Note: It is ok to use "NoDirectCancel" here because the started computations use the same
// cancellation token and will register a cancelled result if cancellation occurs.
// Note: It is ok to use "NoDirectTimeout" here because the child compuation above looks after the timeout.
@ -51,7 +62,7 @@ module AsyncHelpers =
[<Sealed>]
[<AutoSerializable(false)>]
type Mailbox<'Msg>(cancellationSupported: bool) =
let mutable inboxStore = null
let mutable inboxStore = null
let arrivals = Queue<'Msg>()
let syncRoot = arrivals
@ -59,22 +70,21 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
// asynchronous receive, either
// -- "cont" is non-null and the reader is "activated" by re-scheduling cont in the thread pool; or
// -- "pulse" is non-null and the reader is "activated" by setting this event
let mutable savedCont : (bool -> AsyncReturn) option = None
let mutable savedCont: (bool -> AsyncReturn) option = None
// Readers who have a timeout use this event
let mutable pulse : AutoResetEvent = null
let mutable pulse: AutoResetEvent = null
// Make sure that the "pulse" value is created
let ensurePulse() =
let ensurePulse () =
match pulse with
| null ->
pulse <- new AutoResetEvent(false)
| _ ->
()
| null -> pulse <- new AutoResetEvent(false)
| _ -> ()
pulse
let waitOneNoTimeoutOrCancellation =
MakeAsync (fun ctxt ->
MakeAsync(fun ctxt ->
match savedCont with
| None ->
let descheduled =
@ -86,16 +96,16 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
true
else
false)
if descheduled then
Unchecked.defaultof<_>
else
// If we didn't deschedule then run the continuation immediately
ctxt.CallContinuation true
| Some _ ->
failwith "multiple waiting reader continuations for mailbox")
| Some _ -> failwith "multiple waiting reader continuations for mailbox")
let waitOneWithCancellation timeout =
Async.AwaitWaitHandle(ensurePulse(), millisecondsTimeout=timeout)
Async.AwaitWaitHandle(ensurePulse (), millisecondsTimeout = timeout)
let waitOne timeout =
if timeout < 0 && not cancellationSupported then
@ -107,16 +117,17 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
match inboxStore with
| null -> inboxStore <- new System.Collections.Generic.List<'Msg>(1)
| _ -> ()
inboxStore
member x.CurrentQueueLength =
lock syncRoot (fun () -> x.inbox.Count + arrivals.Count)
member x.CurrentQueueLength = lock syncRoot (fun () -> x.inbox.Count + arrivals.Count)
member x.ScanArrivalsUnsafe f =
if arrivals.Count = 0 then
None
else
let msg = arrivals.Dequeue()
match f msg with
| None ->
x.inbox.Add msg
@ -131,13 +142,16 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
match inboxStore with
| null -> None
| inbox ->
if n >= inbox.Count
then None
if n >= inbox.Count then
None
else
let msg = inbox.[n]
match f msg with
| None -> x.ScanInbox (f, n+1)
| res -> inbox.RemoveAt n; res
| None -> x.ScanInbox(f, n + 1)
| res ->
inbox.RemoveAt n
res
member x.ReceiveFromArrivalsUnsafe() =
if arrivals.Count = 0 then
@ -170,8 +184,7 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
match savedCont with
| None ->
match pulse with
| null ->
() // no one waiting, leaving the message in the queue is sufficient
| null -> () // no one waiting, leaving the message in the queue is sufficient
| ev ->
// someone is waiting on the wait handle
ev.Set() |> ignore
@ -180,16 +193,16 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
savedCont <- None
action true |> ignore)
member x.TryScan ((f: 'Msg -> (Async<'T>) option), timeout) : Async<'T option> =
let rec scan timeoutAsync (timeoutCts:CancellationTokenSource) =
member x.TryScan((f: 'Msg -> (Async<'T>) option), timeout) : Async<'T option> =
let rec scan timeoutAsync (timeoutCts: CancellationTokenSource) =
async {
match x.ScanArrivals f with
| None ->
// Deschedule and wait for a message. When it comes, rescan the arrivals
let! ok = AsyncHelpers.awaitEither waitOneNoTimeoutOrCancellation timeoutAsync
match ok with
| Choice1Of2 true ->
return! scan timeoutAsync timeoutCts
| Choice1Of2 true -> return! scan timeoutAsync timeoutCts
| Choice1Of2 false ->
return failwith "should not happen - waitOneNoTimeoutOrCancellation always returns true"
| Choice2Of2 () ->
@ -214,13 +227,15 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
let! res = resP
return Some res
}
let rec scanNoTimeout () =
async {
match x.ScanArrivals f with
| None ->
let! ok = waitOne Timeout.Infinite
if ok then
return! scanNoTimeout()
return! scanNoTimeout ()
else
return (failwith "Timed out with infinite timeout??")
| Some resP ->
@ -231,11 +246,13 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
// Look in the inbox first
async {
match x.ScanInbox(f, 0) with
| None when timeout < 0 ->
return! scanNoTimeout()
| None when timeout < 0 -> return! scanNoTimeout ()
| None ->
let! cancellationToken = Async.CancellationToken
let timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, CancellationToken.None)
let timeoutCts =
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, CancellationToken.None)
let timeoutAsync = AsyncHelpers.timeout timeout timeoutCts.Token
return! scan timeoutAsync timeoutCts
| Some resP ->
@ -246,13 +263,14 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
member x.Scan((f: 'Msg -> (Async<'T>) option), timeout) =
async {
let! resOpt = x.TryScan(f, timeout)
match resOpt with
| None -> return raise(TimeoutException(SR.GetString(SR.mailboxScanTimedOut)))
| None -> return raise (TimeoutException(SR.GetString(SR.mailboxScanTimedOut)))
| Some res -> return res
}
member x.TryReceive timeout =
let rec processFirstArrival() =
let rec processFirstArrival () =
async {
match x.ReceiveFromArrivals() with
| None ->
@ -261,13 +279,14 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
// check arrivals again.
match pulse with
| null when timeout >= 0 || cancellationSupported ->
ensurePulse() |> ignore
return! processFirstArrival()
ensurePulse () |> ignore
return! processFirstArrival ()
| _ ->
// Wait until we have been notified about a message. When that happens, rescan the arrivals
let! ok = waitOne timeout
if ok then
return! processFirstArrival()
return! processFirstArrival ()
else
return None
| res -> return res
@ -276,13 +295,13 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
// look in the inbox first
async {
match x.ReceiveFromInbox() with
| None -> return! processFirstArrival()
| None -> return! processFirstArrival ()
| res -> return res
}
member x.Receive timeout =
let rec processFirstArrival() =
let rec processFirstArrival () =
async {
match x.ReceiveFromArrivals() with
| None ->
@ -291,39 +310,40 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
// check arrivals again.
match pulse with
| null when timeout >= 0 || cancellationSupported ->
ensurePulse() |> ignore
return! processFirstArrival()
ensurePulse () |> ignore
return! processFirstArrival ()
| _ ->
// Wait until we have been notified about a message. When that happens, rescan the arrivals
let! ok = waitOne timeout
if ok then
return! processFirstArrival()
return! processFirstArrival ()
else
return raise(TimeoutException(SR.GetString(SR.mailboxReceiveTimedOut)))
return raise (TimeoutException(SR.GetString(SR.mailboxReceiveTimedOut)))
| Some res -> return res
}
// look in the inbox first
async {
match x.ReceiveFromInbox() with
| None -> return! processFirstArrival()
| None -> return! processFirstArrival ()
| Some res -> return res
}
interface System.IDisposable with
member _.Dispose() =
if isNotNull pulse then (pulse :> IDisposable).Dispose()
if isNotNull pulse then
(pulse :> IDisposable).Dispose()
#if DEBUG
member x.UnsafeContents =
(x.inbox, arrivals, pulse, savedCont) |> box
member x.UnsafeContents = (x.inbox, arrivals, pulse, savedCont) |> box
#endif
[<Sealed>]
[<CompiledName("FSharpAsyncReplyChannel`1")>]
type AsyncReplyChannel<'Reply>(replyf : 'Reply -> unit) =
member x.Reply value = replyf value
type AsyncReplyChannel<'Reply>(replyf: 'Reply -> unit) =
member x.Reply value =
replyf value
[<Sealed>]
[<AutoSerializable(false)>]
@ -340,7 +360,7 @@ type MailboxProcessor<'Msg>(body, ?cancellationToken) =
member _.CurrentQueueLength = mailbox.CurrentQueueLength // nb. unprotected access gives an approximation of the queue length
member _.DefaultTimeout
with get() = defaultTimeout
with get () = defaultTimeout
and set v = defaultTimeout <- v
[<CLIEvent>]
@ -360,81 +380,118 @@ type MailboxProcessor<'Msg>(body, ?cancellationToken) =
// Note that exception stack traces are lost in this design - in an extended design
// the event could propagate an ExceptionDispatchInfo instead of an Exception.
let p =
async { try
do! body x
with exn ->
errorEvent.Trigger exn }
async {
try
do! body x
with exn ->
errorEvent.Trigger exn
}
Async.Start(computation=p, cancellationToken=cancellationToken)
Async.Start(computation = p, cancellationToken = cancellationToken)
member _.Post message = mailbox.Post message
member _.Post message =
mailbox.Post message
member _.TryPostAndReply(buildMessage : (_ -> 'Msg), ?timeout) : 'Reply option =
member _.TryPostAndReply(buildMessage: (_ -> 'Msg), ?timeout) : 'Reply option =
let timeout = defaultArg timeout defaultTimeout
use resultCell = new ResultCell<_>()
let msg = buildMessage (new AsyncReplyChannel<_>(fun reply ->
// Note the ResultCell may have been disposed if the operation
// timed out. In this case RegisterResult drops the result on the floor.
resultCell.RegisterResult(reply, reuseThread=false) |> ignore))
let msg =
buildMessage (
new AsyncReplyChannel<_>(fun reply ->
// Note the ResultCell may have been disposed if the operation
// timed out. In this case RegisterResult drops the result on the floor.
resultCell.RegisterResult(reply, reuseThread = false) |> ignore)
)
mailbox.Post msg
resultCell.TryWaitForResultSynchronously(timeout=timeout)
resultCell.TryWaitForResultSynchronously(timeout = timeout)
member x.PostAndReply(buildMessage, ?timeout) : 'Reply =
match x.TryPostAndReply(buildMessage, ?timeout=timeout) with
| None -> raise (TimeoutException(SR.GetString(SR.mailboxProcessorPostAndReplyTimedOut)))
match x.TryPostAndReply(buildMessage, ?timeout = timeout) with
| None -> raise (TimeoutException(SR.GetString(SR.mailboxProcessorPostAndReplyTimedOut)))
| Some res -> res
member _.PostAndTryAsyncReply(buildMessage, ?timeout) : Async<'Reply option> =
let timeout = defaultArg timeout defaultTimeout
let resultCell = new ResultCell<_>()
let msg = buildMessage (new AsyncReplyChannel<_>(fun reply ->
// Note the ResultCell may have been disposed if the operation
// timed out. In this case RegisterResult drops the result on the floor.
resultCell.RegisterResult(reply, reuseThread=false) |> ignore))
let msg =
buildMessage (
new AsyncReplyChannel<_>(fun reply ->
// Note the ResultCell may have been disposed if the operation
// timed out. In this case RegisterResult drops the result on the floor.
resultCell.RegisterResult(reply, reuseThread = false) |> ignore)
)
mailbox.Post msg
match timeout with
| Threading.Timeout.Infinite when not cancellationSupported ->
async { let! result = resultCell.AwaitResult_NoDirectCancelOrTimeout
return Some result }
async {
let! result = resultCell.AwaitResult_NoDirectCancelOrTimeout
return Some result
}
| _ ->
async { use _disposeCell = resultCell
let! ok = Async.AwaitWaitHandle(resultCell.GetWaitHandle(), millisecondsTimeout=timeout)
let res = (if ok then Some(resultCell.GrabResult()) else None)
return res }
async {
use _disposeCell = resultCell
let! ok = Async.AwaitWaitHandle(resultCell.GetWaitHandle(), millisecondsTimeout = timeout)
member x.PostAndAsyncReply(buildMessage, ?timeout:int) =
let res =
(if ok then
Some(resultCell.GrabResult())
else
None)
return res
}
member x.PostAndAsyncReply(buildMessage, ?timeout: int) =
let timeout = defaultArg timeout defaultTimeout
match timeout with
| Threading.Timeout.Infinite when not cancellationSupported ->
// Nothing to dispose, no wait handles used
let resultCell = new ResultCell<_>()
let msg = buildMessage (new AsyncReplyChannel<_>(fun reply -> resultCell.RegisterResult(reply, reuseThread=false) |> ignore))
let channel =
AsyncReplyChannel<_>(fun reply -> resultCell.RegisterResult(reply, reuseThread = false) |> ignore)
let msg = buildMessage channel
mailbox.Post msg
resultCell.AwaitResult_NoDirectCancelOrTimeout
| _ ->
let asyncReply = x.PostAndTryAsyncReply(buildMessage, timeout=timeout)
async { let! res = asyncReply
match res with
| None -> return! raise (TimeoutException(SR.GetString(SR.mailboxProcessorPostAndAsyncReplyTimedOut)))
| Some res -> return res }
let asyncReply = x.PostAndTryAsyncReply(buildMessage, timeout = timeout)
async {
let! res = asyncReply
match res with
| None -> return! raise (TimeoutException(SR.GetString(SR.mailboxProcessorPostAndAsyncReplyTimedOut)))
| Some res -> return res
}
member _.Receive(?timeout) =
mailbox.Receive(timeout=defaultArg timeout defaultTimeout)
mailbox.Receive(timeout = defaultArg timeout defaultTimeout)
member _.TryReceive(?timeout) =
mailbox.TryReceive(timeout=defaultArg timeout defaultTimeout)
mailbox.TryReceive(timeout = defaultArg timeout defaultTimeout)
member _.Scan(scanner: 'Msg -> (Async<'T>) option, ?timeout) =
mailbox.Scan(scanner, timeout=defaultArg timeout defaultTimeout)
mailbox.Scan(scanner, timeout = defaultArg timeout defaultTimeout)
member _.TryScan(scanner: 'Msg -> (Async<'T>) option, ?timeout) =
mailbox.TryScan(scanner, timeout=defaultArg timeout defaultTimeout)
mailbox.TryScan(scanner, timeout = defaultArg timeout defaultTimeout)
interface System.IDisposable with
member _.Dispose() = (mailbox :> IDisposable).Dispose()
member _.Dispose() =
(mailbox :> IDisposable).Dispose()
static member Start(body, ?cancellationToken) =
let mailboxProcessor = new MailboxProcessor<'Msg>(body, ?cancellationToken=cancellationToken)
let mailboxProcessor =
new MailboxProcessor<'Msg>(body, ?cancellationToken = cancellationToken)
mailboxProcessor.Start()
mailboxProcessor

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -484,8 +484,9 @@ module Map =
/// Evaluates to <c>"1 a 2 b initial"</c>
/// </example>
[<CompiledName("FoldBack")>]
val foldBack<'Key, 'T, 'State> : folder: ('Key -> 'T -> 'State -> 'State) -> table: Map<'Key, 'T> -> state: 'State -> 'State
when 'Key: comparison
val foldBack<'Key, 'T, 'State> :
folder: ('Key -> 'T -> 'State -> 'State) -> table: Map<'Key, 'T> -> state: 'State -> 'State
when 'Key: comparison
/// <summary>Folds over the bindings in the map </summary>
///
@ -504,8 +505,9 @@ module Map =
/// Evaluates to <c>"initial 1 a 2 b"</c>.
/// </example>
[<CompiledName("Fold")>]
val fold<'Key, 'T, 'State> : folder: ('State -> 'Key -> 'T -> 'State) -> state: 'State -> table: Map<'Key, 'T> -> 'State
when 'Key: comparison
val fold<'Key, 'T, 'State> :
folder: ('State -> 'Key -> 'T -> 'State) -> state: 'State -> table: Map<'Key, 'T> -> 'State
when 'Key: comparison
/// <summary>Applies the given function to each binding in the dictionary</summary>
///

Просмотреть файл

@ -26,60 +26,64 @@ open System.Numerics
[<AutoOpen>]
module NumericLiterals =
module NumericLiteralI =
module NumericLiteralI =
let tab64 = new System.Collections.Generic.Dictionary<int64,obj>()
let tabParse = new System.Collections.Generic.Dictionary<string,obj>()
let FromInt64Dynamic (value:int64) : obj =
lock tab64 (fun () ->
let mutable res = Unchecked.defaultof<_>
let ok = tab64.TryGetValue(value,&res)
if ok then res else
res <- BigInteger(value)
tab64.[value] <- res
res)
let tab64 = new System.Collections.Generic.Dictionary<int64, obj>()
let tabParse = new System.Collections.Generic.Dictionary<string, obj>()
let inline get32 (x32:int32) = FromInt64Dynamic (int64 x32)
let FromInt64Dynamic (value: int64) : obj =
lock tab64 (fun () ->
let mutable res = Unchecked.defaultof<_>
let ok = tab64.TryGetValue(value, &res)
let inline isOX s = not (System.String.IsNullOrEmpty(s)) && s.Length > 2 && s.[0] = '0' && s.[1] = 'x'
let FromZero () : 'T =
(get32 0 :?> 'T)
when 'T : BigInteger = BigInteger.Zero
if ok then
res
else
res <- BigInteger(value)
tab64.[value] <- res
res)
let FromOne () : 'T =
(get32 1 :?> 'T)
when 'T : BigInteger = BigInteger.One
let inline get32 (x32: int32) =
FromInt64Dynamic(int64 x32)
let FromInt32 (value:int32): 'T =
(get32 value :?> 'T)
when 'T : BigInteger = new BigInteger(value)
let FromInt64 (value:int64): 'T =
(FromInt64Dynamic value :?> 'T)
when 'T : BigInteger = new BigInteger(value)
let getParse s =
lock tabParse (fun () ->
let mutable res = Unchecked.defaultof<_>
let ok = tabParse.TryGetValue(s,&res)
if ok then
res
else
let v =
if isOX s then
BigInteger.Parse (s.[2..],NumberStyles.AllowHexSpecifier,CultureInfo.InvariantCulture)
else
BigInteger.Parse (s,NumberStyles.AllowLeadingSign,CultureInfo.InvariantCulture)
res <- v
tabParse.[s] <- res
res)
let inline isOX s =
not (System.String.IsNullOrEmpty(s))
&& s.Length > 2
&& s.[0] = '0'
&& s.[1] = 'x'
let FromStringDynamic (text:string) : obj =
let FromZero () : 'T =
(get32 0 :?> 'T) when 'T: BigInteger = BigInteger.Zero
let FromOne () : 'T =
(get32 1 :?> 'T) when 'T: BigInteger = BigInteger.One
let FromInt32 (value: int32) : 'T =
(get32 value :?> 'T) when 'T: BigInteger = new BigInteger(value)
let FromInt64 (value: int64) : 'T =
(FromInt64Dynamic value :?> 'T) when 'T: BigInteger = new BigInteger(value)
let getParse s =
lock tabParse (fun () ->
let mutable res = Unchecked.defaultof<_>
let ok = tabParse.TryGetValue(s, &res)
if ok then
res
else
let v =
if isOX s then
BigInteger.Parse(s.[2..], NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture)
else
BigInteger.Parse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture)
res <- v
tabParse.[s] <- res
res)
let FromStringDynamic (text: string) : obj =
getParse text
let FromString (text:string) : 'T =
(FromStringDynamic text :?> 'T)
when 'T : BigInteger = getParse text
let FromString (text: string) : 'T =
(FromStringDynamic text :?> 'T) when 'T: BigInteger = getParse text

Просмотреть файл

@ -12,7 +12,11 @@ open Microsoft.FSharp.Control
module Observable =
let inline protect f succeed fail =
match (try Choice1Of2 (f ()) with e -> Choice2Of2 e) with
match (try
Choice1Of2(f ())
with e ->
Choice2Of2 e)
with
| Choice1Of2 x -> (succeed x)
| Choice2Of2 e -> (fail e)
@ -21,55 +25,67 @@ module Observable =
let mutable stopped = false
abstract Next : value : 'T -> unit
abstract Next: value: 'T -> unit
abstract Error : error : exn -> unit
abstract Error: error: exn -> unit
abstract Completed : unit -> unit
abstract Completed: unit -> unit
interface IObserver<'T> with
member x.OnNext value =
if not stopped then
x.Next value
member x.OnNext value =
if not stopped then x.Next value
member x.OnError e =
if not stopped then
member x.OnError e =
if not stopped then
stopped <- true
x.Error e
member x.OnCompleted () =
if not stopped then
stopped <- true
x.Completed ()
member x.OnCompleted() =
if not stopped then
stopped <- true
x.Completed()
[<CompiledName("Map")>]
let map mapping (source: IObservable<'T>) =
{ new IObservable<'U> with
member x.Subscribe(observer) =
source.Subscribe
{ new BasicObserver<'T>() with
member x.Next(v) =
protect (fun () -> mapping v) observer.OnNext observer.OnError
member x.Error(e) = observer.OnError(e)
member x.Completed() = observer.OnCompleted() } }
{ new IObservable<'U> with
member x.Subscribe(observer) =
source.Subscribe
{ new BasicObserver<'T>() with
member x.Next(v) =
protect (fun () -> mapping v) observer.OnNext observer.OnError
member x.Error(e) =
observer.OnError(e)
member x.Completed() =
observer.OnCompleted()
}
}
[<CompiledName("Choose")>]
let choose chooser (source: IObservable<'T>) =
{ new IObservable<'U> with
member x.Subscribe(observer) =
source.Subscribe
{ new BasicObserver<'T>() with
{ new IObservable<'U> with
member x.Subscribe(observer) =
source.Subscribe
{ new BasicObserver<'T>() with
member x.Next(v) =
protect (fun () -> chooser v) (function None -> () | Some v2 -> observer.OnNext v2) observer.OnError
member x.Next(v) =
protect
(fun () -> chooser v)
(function
| None -> ()
| Some v2 -> observer.OnNext v2)
observer.OnError
member x.Error(e) = observer.OnError(e)
member x.Error(e) =
observer.OnError(e)
member x.Completed() = observer.OnCompleted() } }
member x.Completed() =
observer.OnCompleted()
}
}
[<CompiledName("Filter")>]
let filter predicate (source: IObservable<'T>) =
@ -81,97 +97,129 @@ module Observable =
[<CompiledName("Scan")>]
let scan collector state (source: IObservable<'T>) =
{ new IObservable<'U> with
member x.Subscribe(observer) =
let mutable state = state
source.Subscribe
{ new BasicObserver<'T>() with
{ new IObservable<'U> with
member x.Subscribe(observer) =
let mutable state = state
member x.Next(v) =
let z = state
protect (fun () -> collector z v) (fun z ->
state <- z
observer.OnNext z) observer.OnError
member x.Error(e) = observer.OnError(e)
source.Subscribe
{ new BasicObserver<'T>() with
member x.Completed() = observer.OnCompleted() } }
member x.Next(v) =
let z = state
protect
(fun () -> collector z v)
(fun z ->
state <- z
observer.OnNext z)
observer.OnError
member x.Error(e) =
observer.OnError(e)
member x.Completed() =
observer.OnCompleted()
}
}
[<CompiledName("Add")>]
let add callback (source: IObservable<'T>) = source.Add(callback)
let add callback (source: IObservable<'T>) =
source.Add(callback)
[<CompiledName("Subscribe")>]
let subscribe (callback: 'T -> unit) (source: IObservable<'T>) = source.Subscribe(callback)
let subscribe (callback: 'T -> unit) (source: IObservable<'T>) =
source.Subscribe(callback)
[<CompiledName("Pairwise")>]
let pairwise (source : IObservable<'T>) : IObservable<'T * 'T> =
{ new IObservable<_> with
member x.Subscribe(observer) =
let mutable lastArgs = None
source.Subscribe
{ new BasicObserver<'T>() with
let pairwise (source: IObservable<'T>) : IObservable<'T * 'T> =
{ new IObservable<_> with
member x.Subscribe(observer) =
let mutable lastArgs = None
member x.Next(args2) =
match lastArgs with
| None -> ()
| Some args1 -> observer.OnNext (args1,args2)
lastArgs <- Some args2
source.Subscribe
{ new BasicObserver<'T>() with
member x.Error(e) = observer.OnError(e)
member x.Next(args2) =
match lastArgs with
| None -> ()
| Some args1 -> observer.OnNext(args1, args2)
member x.Completed() = observer.OnCompleted() } }
lastArgs <- Some args2
member x.Error(e) =
observer.OnError(e)
member x.Completed() =
observer.OnCompleted()
}
}
[<CompiledName("Merge")>]
let merge (source1: IObservable<'T>) (source2: IObservable<'T>) =
{ new IObservable<_> with
member x.Subscribe(observer) =
let mutable stopped = false
let mutable completed1 = false
let mutable completed2 = false
let h1 =
source1.Subscribe
{ new IObserver<'T> with
member x.OnNext(v) =
if not stopped then
observer.OnNext v
{ new IObservable<_> with
member x.Subscribe(observer) =
let mutable stopped = false
let mutable completed1 = false
let mutable completed2 = false
member x.OnError(e) =
if not stopped then
stopped <- true
observer.OnError(e)
let h1 =
source1.Subscribe
{ new IObserver<'T> with
member x.OnNext(v) =
if not stopped then observer.OnNext v
member x.OnCompleted() =
if not stopped then
completed1 <- true
if completed1 && completed2 then
stopped <- true
observer.OnCompleted() }
let h2 =
source2.Subscribe
{ new IObserver<'T> with
member x.OnNext(v) =
if not stopped then
observer.OnNext v
member x.OnError(e) =
if not stopped then
stopped <- true
observer.OnError(e)
member x.OnError(e) =
if not stopped then
stopped <- true
observer.OnError(e)
member x.OnCompleted() =
if not stopped then
completed1 <- true
member x.OnCompleted() =
if not stopped then
completed2 <- true
if completed1 && completed2 then
stopped <- true
observer.OnCompleted() }
if completed1 && completed2 then
stopped <- true
observer.OnCompleted()
}
{ new IDisposable with
member x.Dispose() =
h1.Dispose()
h2.Dispose() } }
let h2 =
source2.Subscribe
{ new IObserver<'T> with
member x.OnNext(v) =
if not stopped then observer.OnNext v
member x.OnError(e) =
if not stopped then
stopped <- true
observer.OnError(e)
member x.OnCompleted() =
if not stopped then
completed2 <- true
if completed1 && completed2 then
stopped <- true
observer.OnCompleted()
}
{ new IDisposable with
member x.Dispose() =
h1.Dispose()
h2.Dispose()
}
}
[<CompiledName("Split")>]
let split (splitter : 'T -> Choice<'U1,'U2>) (source: IObservable<'T>) =
choose (fun v -> match splitter v with Choice1Of2 x -> Some x | _ -> None) source,
choose (fun v -> match splitter v with Choice2Of2 x -> Some x | _ -> None) source
let split (splitter: 'T -> Choice<'U1, 'U2>) (source: IObservable<'T>) =
choose
(fun v ->
match splitter v with
| Choice1Of2 x -> Some x
| _ -> None)
source,
choose
(fun v ->
match splitter v with
| Choice2Of2 x -> Some x
| _ -> None)
source

Просмотреть файл

@ -5,7 +5,7 @@ namespace Microsoft.FSharp.Core
open Microsoft.FSharp.Core.Operators
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Option =
module Option =
[<CompiledName("GetValue")>]
let get option =
@ -56,13 +56,13 @@ module Option =
| Some _ -> 1
[<CompiledName("Fold")>]
let fold<'T,'State> folder (state:'State) (option: 'T option) =
let fold<'T, 'State> folder (state: 'State) (option: 'T option) =
match option with
| None -> state
| Some x -> folder state x
[<CompiledName("FoldBack")>]
let foldBack<'T,'State> folder (option: option<'T>) (state:'State) =
let foldBack<'T, 'State> folder (option: option<'T>) (state: 'State) =
match option with
| None -> state
| Some x -> folder x state
@ -95,18 +95,18 @@ module Option =
let map mapping option =
match option with
| None -> None
| Some x -> Some (mapping x)
| Some x -> Some(mapping x)
[<CompiledName("Map2")>]
let map2 mapping option1 option2 =
let map2 mapping option1 option2 =
match option1, option2 with
| Some x, Some y -> Some (mapping x y)
| Some x, Some y -> Some(mapping x y)
| _ -> None
[<CompiledName("Map3")>]
let map3 mapping option1 option2 option3 =
let map3 mapping option1 option2 option3 =
match option1, option2, option3 with
| Some x, Some y, Some z -> Some (mapping x y z)
| Some x, Some y, Some z -> Some(mapping x y z)
| _ -> None
[<CompiledName("Bind")>]
@ -130,13 +130,13 @@ module Option =
[<CompiledName("ToArray")>]
let toArray option =
match option with
| None -> [| |]
| None -> [||]
| Some x -> [| x |]
[<CompiledName("ToList")>]
let toList option =
match option with
| None -> [ ]
| None -> []
| Some x -> [ x ]
[<CompiledName("ToNullable")>]
@ -146,7 +146,7 @@ module Option =
| Some v -> System.Nullable(v)
[<CompiledName("OfNullable")>]
let ofNullable (value:System.Nullable<'T>) =
let ofNullable (value: System.Nullable<'T>) =
if value.HasValue then
Some value.Value
else
@ -215,13 +215,13 @@ module ValueOption =
| ValueSome _ -> 1
[<CompiledName("Fold")>]
let fold<'T,'State> folder (state:'State) (voption: voption<'T>) =
let fold<'T, 'State> folder (state: 'State) (voption: voption<'T>) =
match voption with
| ValueNone -> state
| ValueSome x -> folder state x
[<CompiledName("FoldBack")>]
let foldBack<'T,'State> folder (voption: voption<'T>) (state:'State) =
let foldBack<'T, 'State> folder (voption: voption<'T>) (state: 'State) =
match voption with
| ValueNone -> state
| ValueSome x -> folder x state
@ -254,18 +254,18 @@ module ValueOption =
let map mapping voption =
match voption with
| ValueNone -> ValueNone
| ValueSome x -> ValueSome (mapping x)
| ValueSome x -> ValueSome(mapping x)
[<CompiledName("Map2")>]
let map2 mapping voption1 voption2 =
let map2 mapping voption1 voption2 =
match voption1, voption2 with
| ValueSome x, ValueSome y -> ValueSome (mapping x y)
| ValueSome x, ValueSome y -> ValueSome(mapping x y)
| _ -> ValueNone
[<CompiledName("Map3")>]
let map3 mapping voption1 voption2 voption3 =
let map3 mapping voption1 voption2 voption3 =
match voption1, voption2, voption3 with
| ValueSome x, ValueSome y, ValueSome z -> ValueSome (mapping x y z)
| ValueSome x, ValueSome y, ValueSome z -> ValueSome(mapping x y z)
| _ -> ValueNone
[<CompiledName("Bind")>]
@ -284,18 +284,22 @@ module ValueOption =
let filter predicate voption =
match voption with
| ValueNone -> ValueNone
| ValueSome x -> if predicate x then ValueSome x else ValueNone
| ValueSome x ->
if predicate x then
ValueSome x
else
ValueNone
[<CompiledName("ToArray")>]
let toArray voption =
match voption with
| ValueNone -> [| |]
| ValueNone -> [||]
| ValueSome x -> [| x |]
[<CompiledName("ToList")>]
let toList voption =
match voption with
| ValueNone -> [ ]
| ValueNone -> []
| ValueSome x -> [ x ]
[<CompiledName("ToNullable")>]
@ -305,7 +309,7 @@ module ValueOption =
| ValueSome v -> System.Nullable(v)
[<CompiledName("OfNullable")>]
let ofNullable (value:System.Nullable<'T>) =
let ofNullable (value: System.Nullable<'T>) =
if value.HasValue then
ValueSome value.Value
else

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,10 +6,19 @@ namespace Microsoft.FSharp.Core
module Result =
[<CompiledName("Map")>]
let map mapping result = match result with Error e -> Error e | Ok x -> Ok (mapping x)
let map mapping result =
match result with
| Error e -> Error e
| Ok x -> Ok(mapping x)
[<CompiledName("MapError")>]
let mapError mapping result = match result with Error e -> Error (mapping e) | Ok x -> Ok x
let mapError mapping result =
match result with
| Error e -> Error(mapping e)
| Ok x -> Ok x
[<CompiledName("Bind")>]
let bind binder result = match result with Error e -> Error e | Ok x -> binder x
let bind binder result =
match result with
| Error e -> Error e
| Ok x -> binder x

Просмотреть файл

@ -20,9 +20,9 @@ open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Control
open Microsoft.FSharp.Collections
[<AttributeUsage (AttributeTargets.Method, AllowMultiple=false)>]
[<AttributeUsage(AttributeTargets.Method, AllowMultiple = false)>]
[<Sealed>]
type NoEagerConstraintApplicationAttribute() =
type NoEagerConstraintApplicationAttribute() =
inherit System.Attribute()
type IResumableStateMachine<'Data> =
@ -43,26 +43,28 @@ type ResumableStateMachine<'Data> =
[<DefaultValue(false)>]
val mutable ResumptionDynamicInfo: ResumptionDynamicInfo<'Data>
interface IResumableStateMachine<'Data> with
interface IResumableStateMachine<'Data> with
member sm.ResumptionPoint = sm.ResumptionPoint
member sm.Data with get() = sm.Data and set v = sm.Data <- v
interface IAsyncStateMachine with
member sm.Data
with get () = sm.Data
and set v = sm.Data <- v
interface IAsyncStateMachine with
// Used for dynamic execution. For "__stateMachine" it is replaced.
member sm.MoveNext() =
member sm.MoveNext() =
sm.ResumptionDynamicInfo.MoveNext(&sm)
// Used when dynamic execution. For "__stateMachine" it is replaced.
member sm.SetStateMachine(state) =
member sm.SetStateMachine(state) =
sm.ResumptionDynamicInfo.SetStateMachine(&sm, state)
and ResumptionFunc<'Data> = delegate of byref<ResumableStateMachine<'Data>> -> bool
and [<AbstractClass>]
ResumptionDynamicInfo<'Data>(initial: ResumptionFunc<'Data>) =
member val ResumptionFunc: ResumptionFunc<'Data> = initial with get, set
member val ResumptionData: obj = null with get, set
and [<AbstractClass>] ResumptionDynamicInfo<'Data>(initial: ResumptionFunc<'Data>) =
member val ResumptionFunc: ResumptionFunc<'Data> = initial with get, set
member val ResumptionData: obj = null with get, set
abstract MoveNext: machine: byref<ResumableStateMachine<'Data>> -> unit
abstract SetStateMachine: machine: byref<ResumableStateMachine<'Data>> * machineState: IAsyncStateMachine -> unit
@ -78,33 +80,40 @@ type SetStateMachineMethodImpl<'Data> = delegate of byref<ResumableStateMachine<
type AfterCode<'Data, 'Result> = delegate of byref<ResumableStateMachine<'Data>> -> 'Result
[<AutoOpen>]
module StateMachineHelpers =
module StateMachineHelpers =
/// Statically determines whether resumable code is being used
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __useResumableCode<'T> : bool = false
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __debugPoint (_name: string) : unit = ()
let __debugPoint (_name: string) : unit =
()
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __resumableEntry () : int option =
failwith "__resumableEntry should always be guarded by __useResumableCode and only used in valid state machine implementations"
let __resumableEntry () : int option =
failwith
"__resumableEntry should always be guarded by __useResumableCode and only used in valid state machine implementations"
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __resumeAt<'T> (programLabel: int) : 'T =
let __resumeAt<'T> (programLabel: int) : 'T =
ignore programLabel
failwith "__resumeAt should always be guarded by __useResumableCode and only used in valid state machine implementations"
failwith
"__resumeAt should always be guarded by __useResumableCode and only used in valid state machine implementations"
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __stateMachine<'Data, 'Result>
(moveNextMethod: MoveNextMethodImpl<'Data>)
(setStateMachineMethod: SetStateMachineMethodImpl<'Data>)
(afterCode: AfterCode<'Data, 'Result>): 'Result =
let __stateMachine<'Data, 'Result>
(moveNextMethod: MoveNextMethodImpl<'Data>)
(setStateMachineMethod: SetStateMachineMethodImpl<'Data>)
(afterCode: AfterCode<'Data, 'Result>)
: 'Result =
ignore moveNextMethod
ignore setStateMachineMethod
ignore afterCode
failwith "__stateMachine should always be guarded by __useResumableCode and only used in valid state machine implementations"
failwith
"__stateMachine should always be guarded by __useResumableCode and only used in valid state machine implementations"
module ResumableCode =
@ -114,23 +123,28 @@ module ResumableCode =
let inline GetResumptionFunc (sm: byref<ResumableStateMachine<'Data>>) =
sm.ResumptionDynamicInfo.ResumptionFunc
let inline Delay(f : unit -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> =
ResumableCode<'Data, 'T>(fun sm -> (f()).Invoke(&sm))
let inline Delay (f: unit -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> =
ResumableCode<'Data, 'T>(fun sm -> (f ()).Invoke(&sm))
/// Used to represent no-ops like the implicit empty "else" branch of an "if" expression.
let inline Zero() : ResumableCode<'Data, unit> =
let inline Zero () : ResumableCode<'Data, unit> =
ResumableCode<'Data, unit>(fun sm -> true)
/// Chains together a step with its following step.
/// Note that this requires that the first step has no result.
/// This prevents constructs like `task { return 1; return 2; }`.
let CombineDynamic(sm: byref<ResumableStateMachine<'Data>>, code1: ResumableCode<'Data, unit>, code2: ResumableCode<'Data, 'T>) : bool =
if code1.Invoke(&sm) then
let CombineDynamic
(
sm: byref<ResumableStateMachine<'Data>>,
code1: ResumableCode<'Data, unit>,
code2: ResumableCode<'Data, 'T>
) : bool =
if code1.Invoke(&sm) then
code2.Invoke(&sm)
else
let rec resume (mf: ResumptionFunc<'Data>) =
ResumptionFunc<'Data>(fun sm ->
if mf.Invoke(&sm) then
ResumptionFunc<'Data>(fun sm ->
if mf.Invoke(&sm) then
code2.Invoke(&sm)
else
sm.ResumptionDynamicInfo.ResumptionFunc <- (resume (GetResumptionFunc &sm))
@ -142,131 +156,191 @@ module ResumableCode =
/// Chains together a step with its following step.
/// Note that this requires that the first step has no result.
/// This prevents constructs like `task { return 1; return 2; }`.
let inline Combine(code1: ResumableCode<'Data, unit>, code2: ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> =
let inline Combine (code1: ResumableCode<'Data, unit>, code2: ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> =
ResumableCode<'Data, 'T>(fun sm ->
if __useResumableCode then
//-- RESUMABLE CODE START
// NOTE: The code for code1 may contain await points! Resuming may branch directly
// into this code!
let __stack_fin = code1.Invoke(&sm)
if __stack_fin then
if __stack_fin then
code2.Invoke(&sm)
else
false
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
CombineDynamic(&sm, code1, code2))
let rec WhileDynamic (sm: byref<ResumableStateMachine<'Data>>, condition: unit -> bool, body: ResumableCode<'Data,unit>) : bool =
if condition() then
if body.Invoke (&sm) then
WhileDynamic (&sm, condition, body)
let rec WhileDynamic
(
sm: byref<ResumableStateMachine<'Data>>,
condition: unit -> bool,
body: ResumableCode<'Data, unit>
) : bool =
if condition () then
if body.Invoke(&sm) then
WhileDynamic(&sm, condition, body)
else
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf)))
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf)))
false
else
true
and WhileBodyDynamicAux (sm: byref<ResumableStateMachine<'Data>>, condition: unit -> bool, body: ResumableCode<'Data,unit>, rf: ResumptionFunc<_>) : bool =
if rf.Invoke (&sm) then
WhileDynamic (&sm, condition, body)
and WhileBodyDynamicAux
(
sm: byref<ResumableStateMachine<'Data>>,
condition: unit -> bool,
body: ResumableCode<'Data, unit>,
rf: ResumptionFunc<_>
) : bool =
if rf.Invoke(&sm) then
WhileDynamic(&sm, condition, body)
else
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf)))
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf)))
false
/// Builds a step that executes the body while the condition predicate is true.
let inline While ([<InlineIfLambda>] condition : unit -> bool, body : ResumableCode<'Data, unit>) : ResumableCode<'Data, unit> =
let inline While
(
[<InlineIfLambda>] condition: unit -> bool,
body: ResumableCode<'Data, unit>
) : ResumableCode<'Data, unit> =
ResumableCode<'Data, unit>(fun sm ->
if __useResumableCode then
if __useResumableCode then
//-- RESUMABLE CODE START
let mutable __stack_go = true
while __stack_go && condition() do
let mutable __stack_go = true
while __stack_go && condition () do
// NOTE: The body of the state machine code for 'while' may contain await points, so resuming
// the code will branch directly into the expanded 'body', branching directly into the while loop
let __stack_body_fin = body.Invoke(&sm)
// If the body completed, we go back around the loop (__stack_go = true)
// If the body yielded, we yield (__stack_go = false)
__stack_go <- __stack_body_fin
__stack_go
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
WhileDynamic(&sm, condition, body))
let rec TryWithDynamic (sm: byref<ResumableStateMachine<'Data>>, body: ResumableCode<'Data, 'T>, handler: exn -> ResumableCode<'Data, 'T>) : bool =
let rec TryWithDynamic
(
sm: byref<ResumableStateMachine<'Data>>,
body: ResumableCode<'Data, 'T>,
handler: exn -> ResumableCode<'Data, 'T>
) : bool =
try
if body.Invoke(&sm) then
if body.Invoke(&sm) then
true
else
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryWithDynamic(&sm, ResumableCode<'Data,'T>(fun sm -> rf.Invoke(&sm)), handler)))
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm ->
TryWithDynamic(&sm, ResumableCode<'Data, 'T>(fun sm -> rf.Invoke(&sm)), handler)))
false
with exn ->
with exn ->
(handler exn).Invoke(&sm)
/// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function
/// to retrieve the step, and in the continuation of the step (if any).
let inline TryWith (body: ResumableCode<'Data, 'T>, catch: exn -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> =
let inline TryWith
(
body: ResumableCode<'Data, 'T>,
catch: exn -> ResumableCode<'Data, 'T>
) : ResumableCode<'Data, 'T> =
ResumableCode<'Data, 'T>(fun sm ->
if __useResumableCode then
if __useResumableCode then
//-- RESUMABLE CODE START
let mutable __stack_fin = false
let mutable __stack_caught = false
let mutable __stack_savedExn = Unchecked.defaultof<_>
try
// The try block may contain await points.
let __stack_body_fin = body.Invoke(&sm)
// If we make it to the assignment we prove we've made a step
__stack_fin <- __stack_body_fin
with exn ->
with exn ->
__stack_caught <- true
__stack_savedExn <- exn
if __stack_caught then
// Place the catch code outside the catch block
if __stack_caught then
// Place the catch code outside the catch block
(catch __stack_savedExn).Invoke(&sm)
else
__stack_fin
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
TryWithDynamic(&sm, body, catch))
let rec TryFinallyCompensateDynamic (sm: byref<ResumableStateMachine<'Data>>, mf: ResumptionFunc<'Data>, savedExn: exn option) : bool =
let rec TryFinallyCompensateDynamic
(
sm: byref<ResumableStateMachine<'Data>>,
mf: ResumptionFunc<'Data>,
savedExn: exn option
) : bool =
let mutable fin = false
fin <- mf.Invoke(&sm)
if fin then
// reraise at the end of the finally block
match savedExn with
match savedExn with
| None -> true
| Some exn -> raise exn
else
else
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryFinallyCompensateDynamic(&sm, rf, savedExn)))
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm -> TryFinallyCompensateDynamic(&sm, rf, savedExn)))
false
let rec TryFinallyAsyncDynamic (sm: byref<ResumableStateMachine<'Data>>, body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) : bool =
let rec TryFinallyAsyncDynamic
(
sm: byref<ResumableStateMachine<'Data>>,
body: ResumableCode<'Data, 'T>,
compensation: ResumableCode<'Data, unit>
) : bool =
let mutable fin = false
let mutable savedExn = None
try
fin <- body.Invoke(&sm)
with exn ->
savedExn <- Some exn
savedExn <- Some exn
fin <- true
if fin then
if fin then
TryFinallyCompensateDynamic(&sm, ResumptionFunc<'Data>(fun sm -> compensation.Invoke(&sm)), savedExn)
else
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryFinallyAsyncDynamic(&sm, ResumableCode<'Data,'T>(fun sm -> rf.Invoke(&sm)), compensation)))
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm ->
TryFinallyAsyncDynamic(&sm, ResumableCode<'Data, 'T>(fun sm -> rf.Invoke(&sm)), compensation)))
false
/// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function
/// to retrieve the step, and in the continuation of the step (if any).
let inline TryFinally (body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) =
let inline TryFinally (body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data, unit>) =
ResumableCode<'Data, 'T>(fun sm ->
if __useResumableCode then
if __useResumableCode then
//-- RESUMABLE CODE START
let mutable __stack_fin = false
try
let __stack_body_fin = body.Invoke(&sm)
// If we make it to the assignment we prove we've made a step, an early 'ret' exit out of the try/with
@ -274,24 +348,30 @@ module ResumableCode =
__stack_fin <- __stack_body_fin
with _exn ->
let __stack_ignore = compensation.Invoke(&sm)
reraise()
reraise ()
if __stack_fin then
if __stack_fin then
let __stack_ignore = compensation.Invoke(&sm)
()
__stack_fin
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
TryFinallyAsyncDynamic(&sm, body, ResumableCode<_,_>(fun sm -> compensation.Invoke(&sm))))
TryFinallyAsyncDynamic(&sm, body, ResumableCode<_, _>(fun sm -> compensation.Invoke(&sm))))
/// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function
/// to retrieve the step, and in the continuation of the step (if any).
let inline TryFinallyAsync (body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) : ResumableCode<'Data, 'T> =
let inline TryFinallyAsync
(
body: ResumableCode<'Data, 'T>,
compensation: ResumableCode<'Data, unit>
) : ResumableCode<'Data, 'T> =
ResumableCode<'Data, 'T>(fun sm ->
if __useResumableCode then
if __useResumableCode then
//-- RESUMABLE CODE START
let mutable __stack_fin = false
let mutable savedExn = None
try
let __stack_body_fin = body.Invoke(&sm)
// If we make it to the assignment we prove we've made a step, an early 'ret' exit out of the try/with
@ -301,59 +381,67 @@ module ResumableCode =
savedExn <- Some exn
__stack_fin <- true
if __stack_fin then
if __stack_fin then
let __stack_compensation_fin = compensation.Invoke(&sm)
__stack_fin <- __stack_compensation_fin
if __stack_fin then
match savedExn with
if __stack_fin then
match savedExn with
| None -> ()
| Some exn -> raise exn
__stack_fin
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
TryFinallyAsyncDynamic(&sm, body, compensation))
let inline Using (resource : 'Resource, body : 'Resource -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> when 'Resource :> IDisposable =
let inline Using
(
resource: 'Resource,
body: 'Resource -> ResumableCode<'Data, 'T>
) : ResumableCode<'Data, 'T> when 'Resource :> IDisposable =
// A using statement is just a try/finally with the finally block disposing if non-null.
TryFinally(
ResumableCode<'Data, 'T>(fun sm -> (body resource).Invoke(&sm)),
ResumableCode<'Data,unit>(fun sm ->
if not (isNull (box resource)) then
ResumableCode<'Data, unit>(fun sm ->
if not (isNull (box resource)) then
resource.Dispose()
true))
let inline For (sequence : seq<'T>, body : 'T -> ResumableCode<'Data, unit>) : ResumableCode<'Data, unit> =
true)
)
let inline For (sequence: seq<'T>, body: 'T -> ResumableCode<'Data, unit>) : ResumableCode<'Data, unit> =
// A for loop is just a using statement on the sequence's enumerator...
Using (sequence.GetEnumerator(),
Using(
sequence.GetEnumerator(),
// ... and its body is a while loop that advances the enumerator and runs the body on each element.
(fun e ->
While(
(fun () ->
(fun () ->
__debugPoint "ForLoop.InOrToKeyword"
e.MoveNext()),
ResumableCode<'Data, unit>(fun sm ->
(body e.Current).Invoke(&sm)))))
e.MoveNext()),
ResumableCode<'Data, unit>(fun sm -> (body e.Current).Invoke(&sm))
))
)
let YieldDynamic (sm: byref<ResumableStateMachine<'Data>>) : bool =
let YieldDynamic (sm: byref<ResumableStateMachine<'Data>>) : bool =
let cont = ResumptionFunc<'Data>(fun _sm -> true)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false
let inline Yield () : ResumableCode<'Data, unit> =
ResumableCode<'Data, unit>(fun sm ->
if __useResumableCode then
let inline Yield () : ResumableCode<'Data, unit> =
ResumableCode<'Data, unit>(fun sm ->
if __useResumableCode then
//-- RESUMABLE CODE START
match __resumableEntry() with
match __resumableEntry () with
| Some contID ->
sm.ResumptionPoint <- contID
//if verbose then printfn $"[{sm.Id}] Yield: returning false to indicate yield, contID = {contID}"
//if verbose then printfn $"[{sm.Id}] Yield: returning false to indicate yield, contID = {contID}"
false
| None ->
//if verbose then printfn $"[{sm.Id}] Yield: returning true to indicate post-yield"
//if verbose then printfn $"[{sm.Id}] Yield: returning true to indicate post-yield"
true
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
else
YieldDynamic(&sm))

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -100,8 +100,8 @@ module RuntimeHelpers =
/// <param name="source">The input sequence.</param>
///
/// <returns>The result sequence.</returns>
val EnumerateUsing: resource: 'T -> source: ('T -> 'Collection) -> seq<'U>
when 'T :> IDisposable and 'Collection :> seq<'U>
val EnumerateUsing:
resource: 'T -> source: ('T -> 'Collection) -> seq<'U> when 'T :> IDisposable and 'Collection :> seq<'U>
/// <summary>Creates an anonymous event with the given handlers.</summary>
///

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -471,8 +471,8 @@ module Set =
/// The reverse of the set is [3; 2; 1]</c>
/// </example>
[<CompiledName("Fold")>]
val fold<'T, 'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> set: Set<'T> -> 'State
when 'T: comparison
val fold<'T, 'State> :
folder: ('State -> 'T -> 'State) -> state: 'State -> set: Set<'T> -> 'State when 'T: comparison
/// <summary>Applies the given accumulating function to all the elements of the set.</summary>
///
@ -492,8 +492,8 @@ module Set =
/// The set is [1; 2; 3]</c>
/// </example>
[<CompiledName("FoldBack")>]
val foldBack<'T, 'State> : folder: ('T -> 'State -> 'State) -> set: Set<'T> -> state: 'State -> 'State
when 'T: comparison
val foldBack<'T, 'State> :
folder: ('T -> 'State -> 'State) -> set: Set<'T> -> state: 'State -> 'State when 'T: comparison
/// <summary>Tests if all elements of the collection satisfy the given predicate.
/// If the input function is <c>f</c> and the elements are <c>i0...iN</c> and "j0...jN"

Просмотреть файл

@ -20,13 +20,13 @@ module String =
let LOH_CHAR_THRESHOLD = 40_000
[<CompiledName("Length")>]
let length (str:string) =
let length (str: string) =
if isNull str then 0 else str.Length
[<CompiledName("Concat")>]
let concat sep (strings : seq<string>) =
let concat sep (strings: seq<string>) =
let concatArray sep (strings: string []) =
let concatArray sep (strings: string[]) =
match length sep with
| 0 -> String.Concat strings
// following line should be used when this overload becomes part of .NET Standard (it's only in .NET Core)
@ -34,37 +34,34 @@ module String =
| _ -> String.Join(sep, strings, 0, strings.Length)
match strings with
| :? (string[]) as arr ->
concatArray sep arr
| :? (string[]) as arr -> concatArray sep arr
| :? (string list) as lst ->
lst
|> List.toArray
|> concatArray sep
| :? (string list) as lst -> lst |> List.toArray |> concatArray sep
| _ ->
String.Join(sep, strings)
| _ -> String.Join(sep, strings)
[<CompiledName("Iterate")>]
let iter (action : (char -> unit)) (str:string) =
let iter (action: (char -> unit)) (str: string) =
if not (String.IsNullOrEmpty str) then
for i = 0 to str.Length - 1 do
action str.[i]
action str.[i]
[<CompiledName("IterateIndexed")>]
let iteri action (str:string) =
let iteri action (str: string) =
if not (String.IsNullOrEmpty str) then
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action)
let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt (action)
for i = 0 to str.Length - 1 do
f.Invoke(i, str.[i])
f.Invoke(i, str.[i])
[<CompiledName("Map")>]
let map (mapping: char -> char) (str:string) =
let map (mapping: char -> char) (str: string) =
if String.IsNullOrEmpty str then
String.Empty
else
let result = str.ToCharArray()
let mutable i = 0
for c in result do
result.[i] <- mapping c
i <- i + 1
@ -72,15 +69,17 @@ module String =
new String(result)
[<CompiledName("MapIndexed")>]
let mapi (mapping: int -> char -> char) (str:string) =
let mapi (mapping: int -> char -> char) (str: string) =
let len = length str
if len = 0 then
if len = 0 then
String.Empty
else
let result = str.ToCharArray()
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping)
let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt (mapping)
let mutable i = 0
while i < len do
result.[i] <- f.Invoke(i, result.[i])
i <- i + 1
@ -88,33 +87,39 @@ module String =
new String(result)
[<CompiledName("Filter")>]
let filter (predicate: char -> bool) (str:string) =
let filter (predicate: char -> bool) (str: string) =
let len = length str
if len = 0 then
if len = 0 then
String.Empty
elif len > LOH_CHAR_THRESHOLD then
// By using SB here, which is twice slower than the optimized path, we prevent LOH allocations
// By using SB here, which is twice slower than the optimized path, we prevent LOH allocations
// and 'stop the world' collections if the filtering results in smaller strings.
// We also don't pre-allocate SB here, to allow for less mem pressure when filter result is small.
let res = StringBuilder()
str |> iter (fun c -> if predicate c then res.Append c |> ignore)
str
|> iter (fun c ->
if predicate c then
res.Append c |> ignore)
res.ToString()
else
// Must do it this way, since array.fs is not yet in scope, but this is safe
let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len
let mutable i = 0
for c in str do
if predicate c then
if predicate c then
target.[i] <- c
i <- i + 1
String(target, 0, i)
[<CompiledName("Collect")>]
let collect (mapping: char -> string) (str:string) =
let collect (mapping: char -> string) (str: string) =
if String.IsNullOrEmpty str then
String.Empty
else
@ -123,19 +128,25 @@ module String =
res.ToString()
[<CompiledName("Initialize")>]
let init (count:int) (initializer: int-> string) =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
let init (count: int) (initializer: int -> string) =
if count < 0 then
invalidArgInputMustBeNonNegative "count" count
let res = StringBuilder count
for i = 0 to count - 1 do
res.Append(initializer i) |> ignore
for i = 0 to count - 1 do
res.Append(initializer i) |> ignore
res.ToString()
[<CompiledName("Replicate")>]
let replicate (count:int) (str:string) =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
let replicate (count: int) (str: string) =
if count < 0 then
invalidArgInputMustBeNonNegative "count" count
let len = length str
if len = 0 || count = 0 then
if len = 0 || count = 0 then
String.Empty
elif len = 1 then
@ -150,14 +161,17 @@ module String =
else
// Using the primitive, because array.fs is not yet in scope. It's safe: both len and count are positive.
let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len * count)
let target =
Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len * count)
let source = str.ToCharArray()
// O(log(n)) performance loop:
// Copy first string, then keep copying what we already copied
// Copy first string, then keep copying what we already copied
// (i.e., doubling it) until we reach or pass the halfway point
Array.Copy(source, 0, target, 0, len)
let mutable i = len
while i * 2 < target.Length do
Array.Copy(target, 0, target, i, i)
i <- i * 2
@ -167,17 +181,21 @@ module String =
new String(target)
[<CompiledName("ForAll")>]
let forall predicate (str:string) =
let forall predicate (str: string) =
if String.IsNullOrEmpty str then
true
else
let rec check i = (i >= str.Length) || (predicate str.[i] && check (i+1))
let rec check i =
(i >= str.Length) || (predicate str.[i] && check (i + 1))
check 0
[<CompiledName("Exists")>]
let exists predicate (str:string) =
let exists predicate (str: string) =
if String.IsNullOrEmpty str then
false
else
let rec check i = (i < str.Length) && (predicate str.[i] || check (i+1))
check 0
let rec check i =
(i < str.Length) && (predicate str.[i] || check (i + 1))
check 0

Просмотреть файл

@ -30,10 +30,10 @@ open Microsoft.FSharp.Collections
type TaskStateMachineData<'T> =
[<DefaultValue(false)>]
val mutable Result : 'T
val mutable Result: 'T
[<DefaultValue(false)>]
val mutable MethodBuilder : AsyncTaskMethodBuilder<'T>
val mutable MethodBuilder: AsyncTaskMethodBuilder<'T>
and TaskStateMachine<'TOverall> = ResumableStateMachine<TaskStateMachineData<'TOverall>>
and TaskResumptionFunc<'TOverall> = ResumptionFunc<TaskStateMachineData<'TOverall>>
@ -42,136 +42,177 @@ and TaskCode<'TOverall, 'T> = ResumableCode<TaskStateMachineData<'TOverall>, 'T>
type TaskBuilderBase() =
member inline _.Delay(generator : unit -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> =
TaskCode<'TOverall, 'T>(fun sm -> (generator()).Invoke(&sm))
member inline _.Delay(generator: unit -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> =
TaskCode<'TOverall, 'T>(fun sm -> (generator ()).Invoke(&sm))
/// Used to represent no-ops like the implicit empty "else" branch of an "if" expression.
[<DefaultValue>]
member inline _.Zero() : TaskCode<'TOverall, unit> = ResumableCode.Zero()
member inline _.Zero() : TaskCode<'TOverall, unit> =
ResumableCode.Zero()
member inline _.Return (value: 'T) : TaskCode<'T, 'T> =
TaskCode<'T, _>(fun sm ->
member inline _.Return(value: 'T) : TaskCode<'T, 'T> =
TaskCode<'T, _>(fun sm ->
sm.Data.Result <- value
true)
/// Chains together a step with its following step.
/// Note that this requires that the first step has no result.
/// This prevents constructs like `task { return 1; return 2; }`.
member inline _.Combine(task1: TaskCode<'TOverall, unit>, task2: TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> =
member inline _.Combine
(
task1: TaskCode<'TOverall, unit>,
task2: TaskCode<'TOverall, 'T>
) : TaskCode<'TOverall, 'T> =
ResumableCode.Combine(task1, task2)
/// Builds a step that executes the body while the condition predicate is true.
member inline _.While ([<InlineIfLambda>] condition : unit -> bool, body : TaskCode<'TOverall, unit>) : TaskCode<'TOverall, unit> =
member inline _.While
(
[<InlineIfLambda>] condition: unit -> bool,
body: TaskCode<'TOverall, unit>
) : TaskCode<'TOverall, unit> =
ResumableCode.While(condition, body)
/// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function
/// to retrieve the step, and in the continuation of the step (if any).
member inline _.TryWith (body: TaskCode<'TOverall, 'T>, catch: exn -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> =
member inline _.TryWith
(
body: TaskCode<'TOverall, 'T>,
catch: exn -> TaskCode<'TOverall, 'T>
) : TaskCode<'TOverall, 'T> =
ResumableCode.TryWith(body, catch)
/// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function
/// to retrieve the step, and in the continuation of the step (if any).
member inline _.TryFinally (body: TaskCode<'TOverall, 'T>, [<InlineIfLambda>] compensation : unit -> unit) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinally(body, ResumableCode<_,_>(fun _sm -> compensation(); true))
member inline _.TryFinally
(
body: TaskCode<'TOverall, 'T>,
[<InlineIfLambda>] compensation: unit -> unit
) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinally(
body,
ResumableCode<_, _>(fun _sm ->
compensation ()
true)
)
member inline _.For (sequence : seq<'T>, body : 'T -> TaskCode<'TOverall, unit>) : TaskCode<'TOverall, unit> =
member inline _.For(sequence: seq<'T>, body: 'T -> TaskCode<'TOverall, unit>) : TaskCode<'TOverall, unit> =
ResumableCode.For(sequence, body)
#if NETSTANDARD2_1
member inline internal this.TryFinallyAsync(body: TaskCode<'TOverall, 'T>, compensation : unit -> ValueTask) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinallyAsync(body, ResumableCode<_,_>(fun sm ->
if __useResumableCode then
let mutable __stack_condition_fin = true
let __stack_vtask = compensation()
if not __stack_vtask.IsCompleted then
let mutable awaiter = __stack_vtask.GetAwaiter()
let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm)
__stack_condition_fin <- __stack_yield_fin
member inline internal this.TryFinallyAsync
(
body: TaskCode<'TOverall, 'T>,
compensation: unit -> ValueTask
) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinallyAsync(
body,
ResumableCode<_, _>(fun sm ->
if __useResumableCode then
let mutable __stack_condition_fin = true
let __stack_vtask = compensation ()
if not __stack_condition_fin then
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
if not __stack_vtask.IsCompleted then
let mutable awaiter = __stack_vtask.GetAwaiter()
let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm)
__stack_condition_fin <- __stack_yield_fin
__stack_condition_fin
else
let vtask = compensation()
let mutable awaiter = vtask.GetAwaiter()
if not __stack_condition_fin then
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
let cont =
TaskResumptionFunc<'TOverall>( fun sm ->
awaiter.GetResult() |> ignore
true)
// shortcut to continue immediately
if awaiter.IsCompleted then
true
__stack_condition_fin
else
sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false
))
let vtask = compensation ()
let mutable awaiter = vtask.GetAwaiter()
member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> =
let cont =
TaskResumptionFunc<'TOverall>(fun sm ->
awaiter.GetResult() |> ignore
true)
// shortcut to continue immediately
if awaiter.IsCompleted then
true
else
sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false)
)
member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable>
(
resource: 'Resource,
body: 'Resource -> TaskCode<'TOverall, 'T>
) : TaskCode<'TOverall, 'T> =
this.TryFinallyAsync(
(fun sm -> (body resource).Invoke(&sm)),
(fun () ->
if not (isNull (box resource)) then
(fun () ->
if not (isNull (box resource)) then
resource.DisposeAsync()
else
ValueTask()))
ValueTask())
)
#endif
type TaskBuilder() =
inherit TaskBuilderBase()
// This is the dynamic implementation - this is not used
// for statically compiled tasks. An executor (resumptionFuncExecutor) is
// for statically compiled tasks. An executor (resumptionFuncExecutor) is
// registered with the state machine, plus the initial resumption.
// The executor stays constant throughout the execution, it wraps each step
// of the execution in a try/with. The resumption is changed at each step
// to represent the continuation of the computation.
static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> =
static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> =
let mutable sm = TaskStateMachine<'T>()
let initialResumptionFunc = TaskResumptionFunc<'T>(fun sm -> code.Invoke(&sm))
let resumptionInfo =
{ new TaskResumptionDynamicInfo<'T>(initialResumptionFunc) with
member info.MoveNext(sm) =
let resumptionInfo =
{ new TaskResumptionDynamicInfo<'T>(initialResumptionFunc) with
member info.MoveNext(sm) =
let mutable savedExn = null
try
sm.ResumptionDynamicInfo.ResumptionData <- null
let step = info.ResumptionFunc.Invoke(&sm)
if step then
let step = info.ResumptionFunc.Invoke(&sm)
if step then
sm.Data.MethodBuilder.SetResult(sm.Data.Result)
else
let mutable awaiter = sm.ResumptionDynamicInfo.ResumptionData :?> ICriticalNotifyCompletion
let mutable awaiter =
sm.ResumptionDynamicInfo.ResumptionData :?> ICriticalNotifyCompletion
assert not (isNull awaiter)
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
with exn ->
savedExn <- exn
// Run SetException outside the stack unwind, see https://github.com/dotnet/roslyn/issues/26567
match savedExn with
match savedExn with
| null -> ()
| exn -> sm.Data.MethodBuilder.SetException exn
member _.SetStateMachine(sm, state) =
sm.Data.MethodBuilder.SetStateMachine(state)
}
}
sm.ResumptionDynamicInfo <- resumptionInfo
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create()
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create ()
sm.Data.MethodBuilder.Start(&sm)
sm.Data.MethodBuilder.Task
member inline _.Run(code : TaskCode<'T, 'T>) : Task<'T> =
if __useResumableCode then
member inline _.Run(code: TaskCode<'T, 'T>) : Task<'T> =
if __useResumableCode then
__stateMachine<TaskStateMachineData<'T>, Task<'T>>
(MoveNextMethodImpl<_>(fun sm ->
(MoveNextMethodImpl<_>(fun sm ->
//-- RESUMABLE CODE START
__resumeAt sm.ResumptionPoint
let mutable __stack_exn : Exception = null
__resumeAt sm.ResumptionPoint
let mutable __stack_exn: Exception = null
try
let __stack_code_fin = code.Invoke(&sm)
if __stack_code_fin then
sm.Data.MethodBuilder.SetResult(sm.Data.Result)
with exn ->
@ -180,11 +221,11 @@ type TaskBuilder() =
match __stack_exn with
| null -> ()
| exn -> sm.Data.MethodBuilder.SetException exn
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
))
(SetStateMachineMethodImpl<_>(fun sm state -> sm.Data.MethodBuilder.SetStateMachine(state)))
(AfterCode<_,_>(fun sm ->
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create()
(AfterCode<_, _>(fun sm ->
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create ()
sm.Data.MethodBuilder.Start(&sm)
sm.Data.MethodBuilder.Task))
else
@ -194,53 +235,62 @@ type BackgroundTaskBuilder() =
inherit TaskBuilderBase()
static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> =
static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> =
// backgroundTask { .. } escapes to a background thread where necessary
// See spec of ConfigureAwait(false) at https://devblogs.microsoft.com/dotnet/configureawait-faq/
if isNull SynchronizationContext.Current && obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default) then
if
isNull SynchronizationContext.Current
&& obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default)
then
TaskBuilder.RunDynamic(code)
else
Task.Run<'T>(fun () -> TaskBuilder.RunDynamic(code))
//// Same as TaskBuilder.Run except the start is inside Task.Run if necessary
member inline _.Run(code : TaskCode<'T, 'T>) : Task<'T> =
if __useResumableCode then
member inline _.Run(code: TaskCode<'T, 'T>) : Task<'T> =
if __useResumableCode then
__stateMachine<TaskStateMachineData<'T>, Task<'T>>
(MoveNextMethodImpl<_>(fun sm ->
(MoveNextMethodImpl<_>(fun sm ->
//-- RESUMABLE CODE START
__resumeAt sm.ResumptionPoint
__resumeAt sm.ResumptionPoint
try
let __stack_code_fin = code.Invoke(&sm)
if __stack_code_fin then
sm.Data.MethodBuilder.SetResult(sm.Data.Result)
with exn ->
sm.Data.MethodBuilder.SetException exn
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
))
(SetStateMachineMethodImpl<_>(fun sm state -> sm.Data.MethodBuilder.SetStateMachine(state)))
(AfterCode<_,Task<'T>>(fun sm ->
(AfterCode<_, Task<'T>>(fun sm ->
// backgroundTask { .. } escapes to a background thread where necessary
// See spec of ConfigureAwait(false) at https://devblogs.microsoft.com/dotnet/configureawait-faq/
if isNull SynchronizationContext.Current && obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default) then
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create()
if
isNull SynchronizationContext.Current
&& obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default)
then
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create ()
sm.Data.MethodBuilder.Start(&sm)
sm.Data.MethodBuilder.Task
else
let sm = sm // copy contents of state machine so we can capture it
Task.Run<'T>(fun () ->
Task.Run<'T>(fun () ->
let mutable sm = sm // host local mutable copy of contents of state machine on this thread pool thread
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create()
sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create ()
sm.Data.MethodBuilder.Start(&sm)
sm.Data.MethodBuilder.Task)))
else
else
BackgroundTaskBuilder.RunDynamic(code)
module TaskBuilder =
module TaskBuilder =
let task = TaskBuilder()
let backgroundTask = BackgroundTaskBuilder()
namespace Microsoft.FSharp.Control.TaskBuilderExtensions
namespace Microsoft.FSharp.Control.TaskBuilderExtensions
open Microsoft.FSharp.Control
open System
@ -251,112 +301,141 @@ open Microsoft.FSharp.Core.CompilerServices
open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
module LowPriority =
module LowPriority =
// Low priority extensions
type TaskBuilderBase with
[<NoEagerConstraintApplication>]
static member inline BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'TResult1)>
(sm: byref<_>, task: ^TaskLike, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : bool =
static member inline BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'TResult1)>
(
sm: byref<_>,
task: ^TaskLike,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : bool =
let mutable awaiter = (^TaskLike: (member GetAwaiter : unit -> ^Awaiter)(task))
let mutable awaiter = (^TaskLike: (member GetAwaiter: unit -> ^Awaiter) (task))
let cont =
(TaskResumptionFunc<'TOverall>( fun sm ->
let result = (^Awaiter : (member GetResult : unit -> 'TResult1)(awaiter))
(continuation result).Invoke(&sm)))
// shortcut to continue immediately
if (^Awaiter : (member get_IsCompleted : unit -> bool)(awaiter)) then
cont.Invoke(&sm)
else
sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false
[<NoEagerConstraintApplication>]
member inline _.Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'TResult1)>
(task: ^TaskLike, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> =
TaskCode<'TOverall, _>(fun sm ->
if __useResumableCode then
//-- RESUMABLE CODE START
// Get an awaiter from the awaitable
let mutable awaiter = (^TaskLike: (member GetAwaiter : unit -> ^Awaiter)(task))
let mutable __stack_fin = true
if not (^Awaiter : (member get_IsCompleted : unit -> bool)(awaiter)) then
// This will yield with __stack_yield_fin = false
// This will resume with __stack_yield_fin = true
let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm)
__stack_fin <- __stack_yield_fin
if __stack_fin then
let result = (^Awaiter : (member GetResult : unit -> 'TResult1)(awaiter))
(continuation result).Invoke(&sm)
else
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
false
else
TaskBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall>(&sm, task, continuation)
//-- RESUMABLE CODE END
)
[<NoEagerConstraintApplication>]
member inline this.ReturnFrom< ^TaskLike, ^Awaiter, 'T
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'T)>
(task: ^TaskLike) : TaskCode< 'T, 'T> =
this.Bind(task, (fun v -> this.Return v))
member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) =
ResumableCode.Using(resource, body)
module HighPriority =
// High priority extensions
type TaskBuilderBase with
static member BindDynamic (sm: byref<_>, task: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : bool =
let mutable awaiter = task.GetAwaiter()
let cont =
(TaskResumptionFunc<'TOverall>(fun sm ->
let result = awaiter.GetResult()
let cont =
(TaskResumptionFunc<'TOverall>(fun sm ->
let result = (^Awaiter: (member GetResult: unit -> 'TResult1) (awaiter))
(continuation result).Invoke(&sm)))
// shortcut to continue immediately
if awaiter.IsCompleted then
if (^Awaiter: (member get_IsCompleted: unit -> bool) (awaiter)) then
cont.Invoke(&sm)
else
sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false
member inline _.Bind (task: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> =
[<NoEagerConstraintApplication>]
member inline _.Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'TResult1)>
(
task: ^TaskLike,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : TaskCode<'TOverall, 'TResult2> =
TaskCode<'TOverall, _>(fun sm ->
if __useResumableCode then
TaskCode<'TOverall, _>(fun sm ->
if __useResumableCode then
//-- RESUMABLE CODE START
// Get an awaiter from the awaitable
let mutable awaiter = (^TaskLike: (member GetAwaiter: unit -> ^Awaiter) (task))
let mutable __stack_fin = true
if not (^Awaiter: (member get_IsCompleted: unit -> bool) (awaiter)) then
// This will yield with __stack_yield_fin = false
// This will resume with __stack_yield_fin = true
let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm)
__stack_fin <- __stack_yield_fin
if __stack_fin then
let result = (^Awaiter: (member GetResult: unit -> 'TResult1) (awaiter))
(continuation result).Invoke(&sm)
else
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
false
else
TaskBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall>(
&sm,
task,
continuation
)
//-- RESUMABLE CODE END
)
[<NoEagerConstraintApplication>]
member inline this.ReturnFrom< ^TaskLike, ^Awaiter, 'T
when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter)
and ^Awaiter :> ICriticalNotifyCompletion
and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'T)>
(task: ^TaskLike)
: TaskCode<'T, 'T> =
this.Bind(task, (fun v -> this.Return v))
member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable>
(
resource: 'Resource,
body: 'Resource -> TaskCode<'TOverall, 'T>
) =
ResumableCode.Using(resource, body)
module HighPriority =
// High priority extensions
type TaskBuilderBase with
static member BindDynamic
(
sm: byref<_>,
task: Task<'TResult1>,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : bool =
let mutable awaiter = task.GetAwaiter()
let cont =
(TaskResumptionFunc<'TOverall>(fun sm ->
let result = awaiter.GetResult()
(continuation result).Invoke(&sm)))
// shortcut to continue immediately
if awaiter.IsCompleted then
cont.Invoke(&sm)
else
sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion)
sm.ResumptionDynamicInfo.ResumptionFunc <- cont
false
member inline _.Bind
(
task: Task<'TResult1>,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : TaskCode<'TOverall, 'TResult2> =
TaskCode<'TOverall, _>(fun sm ->
if __useResumableCode then
//-- RESUMABLE CODE START
// Get an awaiter from the task
let mutable awaiter = task.GetAwaiter()
let mutable __stack_fin = true
if not awaiter.IsCompleted then
// This will yield with __stack_yield_fin = false
// This will resume with __stack_yield_fin = true
let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm)
__stack_fin <- __stack_yield_fin
if __stack_fin then
if __stack_fin then
let result = awaiter.GetResult()
(continuation result).Invoke(&sm)
else
@ -364,21 +443,26 @@ module HighPriority =
false
else
TaskBuilderBase.BindDynamic(&sm, task, continuation)
//-- RESUMABLE CODE END
//-- RESUMABLE CODE END
)
member inline this.ReturnFrom (task: Task<'T>) : TaskCode<'T, 'T> =
member inline this.ReturnFrom(task: Task<'T>) : TaskCode<'T, 'T> =
this.Bind(task, (fun v -> this.Return v))
module MediumPriority =
module MediumPriority =
open HighPriority
// Medium priority extensions
type TaskBuilderBase with
member inline this.Bind (computation: Async<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> =
this.Bind (Async.StartAsTask computation, continuation)
member inline this.ReturnFrom (computation: Async<'T>) : TaskCode<'T, 'T> =
this.ReturnFrom (Async.StartAsTask computation)
member inline this.Bind
(
computation: Async<'TResult1>,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : TaskCode<'TOverall, 'TResult2> =
this.Bind(Async.StartAsTask computation, continuation)
member inline this.ReturnFrom(computation: Async<'T>) : TaskCode<'T, 'T> =
this.ReturnFrom(Async.StartAsTask computation)
#endif

Просмотреть файл

@ -88,8 +88,8 @@ module internal ProjectFile =
.ReadAllText(resolutionsFile)
.Split([| '\r'; '\n' |], StringSplitOptions.None)
|> Array.filter (fun line -> not (String.IsNullOrEmpty(line)))
with
| _ -> [||]
with _ ->
[||]
[|
for line in lines do

Просмотреть файл

@ -35,10 +35,7 @@ module internal Utilities =
let pos = option.IndexOf('=')
let stringAsOpt text =
if String.IsNullOrEmpty(text) then
None
else
Some text
if String.IsNullOrEmpty(text) then None else Some text
let nameOpt =
if pos <= 0 then
@ -48,12 +45,9 @@ module internal Utilities =
let valueOpt =
let valueText =
if pos < 0 then
option
else if pos < option.Length then
option.Substring(pos + 1)
else
""
if pos < 0 then option
else if pos < option.Length then option.Substring(pos + 1)
else ""
stringAsOpt (valueText.Trim(trimChars))
@ -210,6 +204,5 @@ module internal Utilities =
// So strip off the flags
let pos = source.IndexOf(" ")
if pos >= 0 then
yield ("i", source.Substring(pos).Trim())
if pos >= 0 then yield ("i", source.Substring(pos).Trim())
}

Просмотреть файл

@ -267,8 +267,8 @@ type FSharpDependencyManager(outputDirectory: string option) =
Directory.CreateDirectory(directory) |> ignore
directory
with
| _ -> directory
with _ ->
directory
let deleteScripts () =
try
@ -279,16 +279,16 @@ type FSharpDependencyManager(outputDirectory: string option) =
#else
()
#endif
with
| _ -> ()
with _ ->
()
let emitFile fileName (body: string) =
try
// Create a file to write to
use sw = File.CreateText(fileName)
sw.WriteLine(body)
with
| _ -> ()
with _ ->
()
let prepareDependencyResolutionFiles
(

Просмотреть файл

@ -81,8 +81,8 @@ let main (argv) =
member _.Exit(n) =
try
exit n
with
| _ -> ()
with _ ->
()
failwithf "%s" (FSComp.SR.elSysEnvExitDidntExit ())
}
@ -116,8 +116,7 @@ let main (argv) =
0
with
| e ->
with e ->
// Last-chance error recovery (note, with a poor error range)
errorRecovery e Range.range0
1

Просмотреть файл

@ -76,8 +76,7 @@ module internal Utils =
let guard (f) =
try
f ()
with
| e ->
with e ->
warning (
Failure(
sprintf
@ -197,8 +196,8 @@ type internal ReadLineConsole() =
|> Seq.iter (fun option -> optionsCache.Add(option))
optionsCache.Root <- root
with
| _ -> optionsCache.Clear()
with _ ->
optionsCache.Clear()
optionsCache, true
else
@ -210,10 +209,7 @@ type internal ReadLineConsole() =
| _ -> "^?"
member x.GetCharacterSize(c) =
if Char.IsControl(c) then
x.MapCharacter(c).Length
else
1
if Char.IsControl(c) then x.MapCharacter(c).Length else 1
static member TabSize = 4
@ -224,12 +220,7 @@ type internal ReadLineConsole() =
if currLeft < x.Inset then
if currLeft = 0 then
Console.Write(
if prompt then
x.Prompt2
else
String(' ', x.Inset)
)
Console.Write(if prompt then x.Prompt2 else String(' ', x.Inset))
Utils.guard (fun () ->
Console.CursorTop <- min Console.CursorTop (Console.BufferHeight - 1)
@ -287,8 +278,7 @@ type internal ReadLineConsole() =
let mutable position = -1
for i = 0 to input.Length - 1 do
if (i = curr) then
position <- output.Length
if (i = curr) then position <- output.Length
let c = input.Chars(i)
@ -297,8 +287,7 @@ type internal ReadLineConsole() =
else
output.Append(c) |> ignore
if (curr = input.Length) then
position <- output.Length
if (curr = input.Length) then position <- output.Length
// render the current text, computing a new value for "rendered"
let old_rendered = rendered
@ -377,11 +366,7 @@ type internal ReadLineConsole() =
optionsCache <- opts
if (opts.Count > 0) then
let part =
if shift then
opts.Previous()
else
opts.Next()
let part = if shift then opts.Previous() else opts.Next()
setInput (opts.Root + part)
else if (prefix) then
@ -417,11 +402,7 @@ type internal ReadLineConsole() =
// REVIEW: is this F6 rewrite required? 0x1A looks like Ctrl-Z.
// REVIEW: the Ctrl-Z code is not recognised as EOF by the lexer.
// REVIEW: looks like a relic of the port of readline, which is currently removable.
let c =
if (key.Key = ConsoleKey.F6) then
'\x1A'
else
key.KeyChar
let c = if (key.Key = ConsoleKey.F6) then '\x1A' else key.KeyChar
insertChar (c)
@ -438,8 +419,7 @@ type internal ReadLineConsole() =
if (line = "\x1A") then
null
else
if (line.Length > 0) then
history.AddLast(line)
if (line.Length > 0) then history.AddLast(line)
line

Просмотреть файл

@ -139,8 +139,7 @@ let internal TrySetUnhandledExceptionMode () =
try
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
with
| _ ->
with _ ->
decr i
()
@ -155,8 +154,7 @@ let StartServer (fsiSession: FsiEvaluationSession) (fsiServerName) =
//printf "FSI-SERVER: received CTRL-C request...\n"
try
fsiSession.Interrupt()
with
| _ ->
with _ ->
// Final sanity check! - catch all exns - but not expected
assert false
()
@ -200,8 +198,7 @@ let evaluateSession (argv: string[]) =
let _ = Console.ForegroundColor
let _ = Console.CursorLeft <- Console.CursorLeft
true
with
| _ ->
with _ ->
//if progress then fprintfn outWriter "probe failed, we have no console..."
false
else
@ -248,8 +245,7 @@ let evaluateSession (argv: string[]) =
lazy
try
Some(WinFormsEventLoop())
with
| e ->
with e ->
printfn "Your system doesn't seem to support WinForms correctly. You will"
printfn "need to set fsi.EventLoop use GUI windows from F# Interactive."
printfn "You can set different event loops for MonoMac, Gtk#, WinForms and other"
@ -282,11 +278,7 @@ let evaluateSession (argv: string[]) =
member _.EventLoopRun() =
#if !FX_NO_WINFORMS
match (if fsiSession.IsGui then
fsiWinFormsLoop.Value
else
None)
with
match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with
| Some l -> (l :> IEventLoop).Run()
| _ ->
#endif
@ -294,11 +286,7 @@ let evaluateSession (argv: string[]) =
member _.EventLoopInvoke(f) =
#if !FX_NO_WINFORMS
match (if fsiSession.IsGui then
fsiWinFormsLoop.Value
else
None)
with
match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with
| Some l -> (l :> IEventLoop).Invoke(f)
| _ ->
#endif
@ -306,11 +294,7 @@ let evaluateSession (argv: string[]) =
member _.EventLoopScheduleRestart() =
#if !FX_NO_WINFORMS
match (if fsiSession.IsGui then
fsiWinFormsLoop.Value
else
None)
with
match (if fsiSession.IsGui then fsiWinFormsLoop.Value else None) with
| Some l -> (l :> IEventLoop).ScheduleRestart()
| _ ->
#endif
@ -341,8 +325,8 @@ let evaluateSession (argv: string[]) =
if fsiSession.IsGui then
try
Application.EnableVisualStyles()
with
| _ -> ()
with _ ->
()
// Route GUI application exceptions to the exception handlers
Application.add_ThreadException (
@ -352,14 +336,14 @@ let evaluateSession (argv: string[]) =
let runningOnMono =
try
System.Type.GetType("Mono.Runtime") <> null
with
| e -> false
with e ->
false
if not runningOnMono then
try
TrySetUnhandledExceptionMode()
with
| _ -> ()
with _ ->
()
fsiWinFormsLoop.Value |> Option.iter (fun l -> l.LCID <- fsiSession.LCID)
#endif
@ -400,8 +384,8 @@ let MainMain argv =
member _.Dispose() =
try
Console.SetOut(savedOut)
with
| _ -> ()
with _ ->
()
}
#if !FX_NO_APP_DOMAINS