未验证 提交 5b1a3ae5 编写于 作者: D Don Syme 提交者: GitHub

apply formatting (fix build) (#13209)

* preformat

* apply formatting
上级 36af364b
# 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
\ No newline at end of file
......@@ -11,31 +11,33 @@ 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
/// on a result of a query.
type Grouping<'K, 'T>(key: 'K, values: seq<'T>) =
interface System.Linq.IGrouping<'K, 'T> with
interface IGrouping<'K, 'T> with
member _.Key = key
interface System.Collections.IEnumerable with
interface IEnumerable with
member _.GetEnumerator() =
values.GetEnumerator() :> System.Collections.IEnumerator
values.GetEnumerator() :> IEnumerator
interface System.Collections.Generic.IEnumerable<'T> with
interface Generic.IEnumerable<'T> with
member _.GetEnumerator() =
values.GetEnumerator()
module internal Adapters =
let memoize f =
let d =
new System.Collections.Concurrent.ConcurrentDictionary<Type, 'b>(HashIdentity.Structural)
let d = new ConcurrentDictionary<Type, 'b>(HashIdentity.Structural)
fun x -> d.GetOrAdd(x, (fun r -> f r))
......@@ -46,13 +48,13 @@ module internal Adapters =
let MemberInitializationHelperMeth =
methodhandleof (fun x -> LeafExpressionConverter.MemberInitializationHelper x)
|> System.Reflection.MethodInfo.GetMethodFromHandle
:?> System.Reflection.MethodInfo
|> MethodInfo.GetMethodFromHandle
:?> MethodInfo
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
// using the 'new O(Prop1 = <e>, Prop2 = <e>)' syntax
......@@ -73,7 +75,8 @@ module internal Adapters =
let rec propSetList acc x =
match x with
// detect " v.X <- y"
| ((Patterns.PropertySet (Some (Patterns.Var var), _, _, _)) as p) :: xs when var = varArg -> propSetList (p :: acc) xs
| ((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"
......@@ -190,8 +193,7 @@ module internal Adapters =
let fields =
Microsoft.FSharp.Reflection.FSharpType.GetRecordFields(
typ,
System.Reflection.BindingFlags.Public
||| System.Reflection.BindingFlags.NonPublic
BindingFlags.Public ||| BindingFlags.NonPublic
)
match fields |> Array.tryFindIndex (fun p -> p = propInfo) with
......@@ -223,7 +225,8 @@ module internal Adapters =
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) ])
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)
......@@ -231,10 +234,10 @@ module internal Adapters =
ConvImmutableTypeToMutableType (TupleConv convs) (FSharpType.MakeTupleType types)
| GroupingConv (_keyTy, _elemTy, conv) ->
assert ty.IsGenericType
assert (ty.GetGenericTypeDefinition() = typedefof<System.Linq.IGrouping<_, _>>)
assert (ty.GetGenericTypeDefinition() = typedefof<IGrouping<_, _>>)
let keyt1 = ty.GetGenericArguments().[0]
let valt1 = ty.GetGenericArguments().[1]
typedefof<System.Linq.IGrouping<_, _>>.MakeGenericType [| keyt1; ConvImmutableTypeToMutableType conv valt1 |]
typedefof<IGrouping<_, _>>.MakeGenericType [| keyt1; ConvImmutableTypeToMutableType conv valt1 |]
| SeqConv conv ->
assert ty.IsGenericType
let isIQ = ty.GetGenericTypeDefinition() = typedefof<IQueryable<_>>
......@@ -256,14 +259,14 @@ module internal Adapters =
let mhandle =
(methodhandleof (fun x -> LeafExpressionConverter.NewAnonymousObjectHelper x))
let minfo =
(System.Reflection.MethodInfo.GetMethodFromHandle mhandle) :?> System.Reflection.MethodInfo
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.
......@@ -305,7 +308,8 @@ module internal Adapters =
// rewrite bottom-up
let e =
match e with
| ExprShape.ShapeCombination (comb, args) -> ExprShape.RebuildShapeCombination(comb, List.map SimplifyConsumingExpr args)
| ExprShape.ShapeCombination (comb, args) ->
ExprShape.RebuildShapeCombination(comb, List.map SimplifyConsumingExpr args)
| ExprShape.ShapeLambda (v, body) -> Expr.Lambda(v, SimplifyConsumingExpr body)
| ExprShape.ShapeVar _ -> e
......
......@@ -244,7 +244,11 @@ module Array =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let countByRefType (projection: 'T -> 'Key) (array: 'T[]) =
countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(projection t)) (fun sb -> sb.Value) array
countByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(projection t))
(fun sb -> sb.Value)
array
[<CompiledName("CountBy")>]
let countBy (projection: 'T -> 'Key) (array: 'T[]) =
......@@ -570,7 +574,11 @@ module Array =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let groupByRefType (keyf: 'T -> 'Key) (array: 'T[]) =
groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(keyf t)) (fun sb -> sb.Value) array
groupByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(keyf t))
(fun sb -> sb.Value)
array
[<CompiledName("GroupBy")>]
let groupBy (projection: 'T -> 'Key) (array: 'T[]) =
......@@ -822,7 +830,12 @@ module Array =
count
let private createMask<'a> (f: 'a -> bool) (src: array<'a>) (maskArrayOut: byref<array<uint32>>) (leftoverMaskOut: byref<uint32>) =
let private createMask<'a>
(f: 'a -> bool)
(src: array<'a>)
(maskArrayOut: byref<array<uint32>>)
(leftoverMaskOut: byref<uint32>)
=
let maskArrayLength = src.Length / 0x20
// null when there are less than 32 items in src array.
......@@ -1208,7 +1221,10 @@ module Array =
if len % chunkSize <> 0 then
res.[chunkCount - 1] <-
Microsoft.FSharp.Primitives.Basics.Array.subUnchecked ((chunkCount - 1) * chunkSize) (len % chunkSize) array
Microsoft.FSharp.Primitives.Basics.Array.subUnchecked
((chunkCount - 1) * chunkSize)
(len % chunkSize)
array
res
......@@ -1776,7 +1792,11 @@ module Array =
for j in 1 .. len - 1 do
if lenInner <> array.[j].Length then
invalidArgDifferentArrayLength "array.[0]" lenInner (String.Format("array.[{0}]", j)) array.[j].Length
invalidArgDifferentArrayLength
"array.[0]"
lenInner
(String.Format("array.[{0}]", j))
array.[j].Length
let result: 'T[][] =
Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked lenInner
......
......@@ -870,13 +870,15 @@ module AsyncPrimitives =
/// - Create Thread and call Start() with exception protection. We don't expect this
/// to fail but protect nevertheless.
let CreateSwitchToNewThreadAsync () =
MakeAsyncWithCancelCheck(fun ctxt -> ctxt.ProtectCode(fun () -> ctxt.trampolineHolder.StartThreadWithTrampoline ctxt.cont))
MakeAsyncWithCancelCheck(fun ctxt ->
ctxt.ProtectCode(fun () -> ctxt.trampolineHolder.StartThreadWithTrampoline ctxt.cont))
/// - Initial cancellation check
/// - Call ThreadPool.QueueUserWorkItem with exception protection. We don't expect this
/// to fail but protect nevertheless.
let CreateSwitchToThreadPoolAsync () =
MakeAsyncWithCancelCheck(fun ctxt -> ctxt.ProtectCode(fun () -> ctxt.trampolineHolder.QueueWorkItemWithTrampoline ctxt.cont))
MakeAsyncWithCancelCheck(fun ctxt ->
ctxt.ProtectCode(fun () -> ctxt.trampolineHolder.QueueWorkItemWithTrampoline ctxt.cont))
/// Post back to the sync context regardless of which continuation is taken
/// - Call syncCtxt.Post with exception protection
......@@ -917,7 +919,8 @@ module AsyncPrimitives =
// This logic was added in F# 2.0 though is incorrect from the perspective of
// how SynchronizationContext is meant to work. However the logic works for
// mainline scenarios (WinForms/WPF) and for compatibility reasons we won't change it.
| _ when Object.Equals(syncCtxt, currentSyncCtxt) && thread.Equals Thread.CurrentThread -> executeImmediately ()
| _ when Object.Equals(syncCtxt, currentSyncCtxt) && thread.Equals Thread.CurrentThread ->
executeImmediately ()
| _ -> trampolineHolder.PostOrQueueWithTrampoline syncCtxt action
member _.PostOrQueueWithTrampoline res =
......@@ -1074,7 +1077,7 @@ module AsyncPrimitives =
(typeof<FuncDelegate<'T>>)
.GetMethod("Invoke", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance)
System.Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeMeth) :?> 'Delegate
Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeMeth) :?> 'Delegate
[<DebuggerHidden>]
let QueueAsync cancellationToken cont econt ccont computation =
......@@ -1429,7 +1432,9 @@ type Async =
static member CancelCheck() =
unitAsync
static member FromContinuations(callback: ('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) : Async<'T> =
static member FromContinuations
(callback: ('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit)
: Async<'T> =
MakeAsyncWithCancelCheck(fun ctxt ->
let mutable underCurrentThreadStack = true
let mutable contToTailCall = None
......@@ -1451,7 +1456,11 @@ type Async =
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> cont x) |> unfake
try
callback (once ctxt.cont, (fun exn -> once ctxt.econt (ExceptionDispatchInfo.RestoreOrCapture exn)), once ctxt.ccont)
callback (
once ctxt.cont,
(fun exn -> once ctxt.econt (ExceptionDispatchInfo.RestoreOrCapture exn)),
once ctxt.ccont
)
with exn ->
if not (latch.Enter()) then
invalidOp (SR.GetString(SR.controlContinuationInvokedMultipleTimes))
......@@ -1518,7 +1527,12 @@ type Async =
static member Parallel(computations: seq<Async<'T>>, ?maxDegreeOfParallelism: int) =
match maxDegreeOfParallelism with
| Some x when x < 1 ->
raise (System.ArgumentException(String.Format(SR.GetString(SR.maxDegreeOfParallelismNotPositive), x), "maxDegreeOfParallelism"))
raise (
System.ArgumentException(
String.Format(SR.GetString(SR.maxDegreeOfParallelismNotPositive), x),
"maxDegreeOfParallelism"
)
)
| _ -> ()
MakeAsyncWithCancelCheck(fun ctxt ->
......@@ -1547,8 +1561,10 @@ type Async =
match firstExn with
| None -> ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.cont results)
| Some (Choice1Of2 exn) -> ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.econt exn)
| Some (Choice2Of2 cexn) -> ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.ccont cexn)
| Some (Choice1Of2 exn) ->
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.econt exn)
| Some (Choice2Of2 cexn) ->
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.ccont cexn)
else
fake ()
......@@ -1724,7 +1740,12 @@ type Async =
let cancellationToken =
defaultArg cancellationToken defaultCancellationTokenSource.Token
AsyncPrimitives.StartWithContinuations cancellationToken computation continuation exceptionContinuation cancellationContinuation
AsyncPrimitives.StartWithContinuations
cancellationToken
computation
continuation
exceptionContinuation
cancellationContinuation
static member StartWithContinuations
(
......@@ -1781,7 +1802,8 @@ type Async =
DisposeCancellationRegistration &registration
DisposeTimer &timer
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.ccont (OperationCanceledException(ctxt.token)))
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () ->
ctxt.ccont (OperationCanceledException(ctxt.token)))
|> unfake)
)
|> Some
......@@ -1847,7 +1869,8 @@ type Async =
UnregisterWaitHandle &rwh
// Call the cancellation continuation
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () -> ctxt.ccont (OperationCanceledException(ctxt.token)))
ctxt.trampolineHolder.ExecuteWithTrampoline(fun () ->
ctxt.ccont (OperationCanceledException(ctxt.token)))
|> unfake)
)
|> Some
......@@ -1929,7 +1952,11 @@ type Async =
let res = resultCell.GrabResult()
return res.Commit()
else
let! ok = Async.AwaitWaitHandle(resultCell.GetWaitHandle(), ?millisecondsTimeout = millisecondsTimeout)
let! ok =
Async.AwaitWaitHandle(
resultCell.GetWaitHandle(),
?millisecondsTimeout = millisecondsTimeout
)
if ok then
let res = resultCell.GrabResult()
......@@ -2009,10 +2036,18 @@ type Async =
Async.FromBeginEnd((fun (iar, state) -> beginAction (arg, iar, state)), endAction, ?cancelAction = cancelAction)
static member FromBeginEnd(arg1, arg2, beginAction, endAction, ?cancelAction) : Async<'T> =
Async.FromBeginEnd((fun (iar, state) -> beginAction (arg1, arg2, iar, state)), endAction, ?cancelAction = cancelAction)
Async.FromBeginEnd(
(fun (iar, state) -> beginAction (arg1, arg2, iar, state)),
endAction,
?cancelAction = cancelAction
)
static member FromBeginEnd(arg1, arg2, arg3, beginAction, endAction, ?cancelAction) : Async<'T> =
Async.FromBeginEnd((fun (iar, state) -> beginAction (arg1, arg2, arg3, iar, state)), endAction, ?cancelAction = cancelAction)
Async.FromBeginEnd(
(fun (iar, state) -> beginAction (arg1, arg2, arg3, iar, state)),
endAction,
?cancelAction = cancelAction
)
static member AsBeginEnd<'Arg, 'T>
(computation: ('Arg -> Async<'T>))
......@@ -2267,7 +2302,9 @@ module WebExtensions =
)
|> CreateTryWithFilterAsync(fun exn ->
match exn with
| :? System.Net.WebException as webExn when webExn.Status = System.Net.WebExceptionStatus.RequestCanceled && canceled ->
| :? System.Net.WebException as webExn when
webExn.Status = System.Net.WebExceptionStatus.RequestCanceled && canceled
->
Some(CreateAsyncResultAsync(AsyncResult.Canceled(OperationCanceledException webExn.Message)))
| _ -> None)
......
......@@ -50,7 +50,8 @@ 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
......
......@@ -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
......@@ -79,7 +80,8 @@ type EventDelegee<'Args>(observer: System.IObserver<'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<_>
......@@ -98,7 +100,7 @@ type Event<'Delegate, 'Args when 'Delegate: delegate<'Args, unit> and 'Delegate
// 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>)
(Delegate.CreateDelegate(typeof<EventWrapper<'Delegate, 'Args>>, mi) :?> EventWrapper<'Delegate, 'Args>)
else
null
......@@ -152,8 +154,7 @@ type Event<'Delegate, 'Args when 'Delegate: delegate<'Args, unit> and 'Delegate
member e.Subscribe(observer) =
let obj = new EventDelegee<'Args>(observer)
let h =
System.Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> 'Delegate
let h = Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> 'Delegate
(e :?> IDelegateEvent<'Delegate>).AddHandler(h)
......
......@@ -37,12 +37,20 @@ module ExtraTopLevelOperators =
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) =
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()
......@@ -512,7 +520,8 @@ type ITypeProvider =
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
......
......@@ -75,7 +75,11 @@ module List =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let countByRefType (projection: 'T -> 'Key) (list: 'T list) =
countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(projection t)) (fun sb -> sb.Value) list
countByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(projection t))
(fun sb -> sb.Value)
list
[<CompiledName("CountBy")>]
let countBy (projection: 'T -> 'Key) (list: 'T list) =
......@@ -358,7 +362,13 @@ module List =
let arrn = arr.Length
foldArraySubRight f arr 0 (arrn - 2) arr.[arrn - 1]
let scanArraySubRight<'T, 'State> (f: OptimizedClosures.FSharpFunc<'T, 'State, 'State>) (arr: _[]) start fin initState =
let scanArraySubRight<'T, 'State>
(f: OptimizedClosures.FSharpFunc<'T, 'State, 'State>)
(arr: _[])
start
fin
initState
=
let mutable state = initState
let mutable res = [ state ]
......@@ -411,7 +421,8 @@ module List =
| [], [] -> f.Invoke(h1, k1, state)
| [ h2 ], [ k2 ] -> f.Invoke(h1, k1, f.Invoke(h2, k2, state))
| [ h2; h3 ], [ k2; k3 ] -> f.Invoke(h1, k1, f.Invoke(h2, k2, f.Invoke(h3, k3, state)))
| [ h2; h3; h4 ], [ k2; k3; k4 ] -> f.Invoke(h1, k1, f.Invoke(h2, k2, f.Invoke(h3, k3, f.Invoke(h4, k4, state))))
| [ h2; h3; h4 ], [ k2; k3; k4 ] ->
f.Invoke(h1, k1, f.Invoke(h2, k2, f.Invoke(h3, k3, f.Invoke(h4, k4, state))))
| _ -> foldBack2UsingArrays f list1 list2 state
| [], xs2 -> invalidArgDifferentListLength "list1" "list2" xs2.Length
| xs1, [] -> invalidArgDifferentListLength "list2" "list1" xs1.Length
......@@ -528,7 +539,12 @@ module List =
let where predicate list =
Microsoft.FSharp.Primitives.Basics.List.filter predicate list
let inline groupByImpl (comparer: IEqualityComparer<'SafeKey>) (keyf: 'T -> 'SafeKey) (getKey: 'SafeKey -> 'Key) (list: 'T list) =
let inline groupByImpl
(comparer: IEqualityComparer<'SafeKey>)
(keyf: 'T -> 'SafeKey)
(getKey: 'SafeKey -> 'Key)
(list: 'T list)
=
Microsoft.FSharp.Primitives.Basics.List.groupBy comparer keyf getKey list
// We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance
......@@ -537,7 +553,11 @@ module List =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let groupByRefType (keyf: 'T -> 'Key) (list: 'T list) =
groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(keyf t)) (fun sb -> sb.Value) list
groupByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(keyf t))
(fun sb -> sb.Value)
list
[<CompiledName("GroupBy")>]
let groupBy (projection: 'T -> 'Key) (list: 'T list) =
......
......@@ -203,7 +203,8 @@ type Mailbox<'Msg>(cancellationSupported: bool) =
match ok with
| Choice1Of2 true -> return! scan timeoutAsync timeoutCts
| Choice1Of2 false -> return failwith "should not happen - waitOneNoTimeoutOrCancellation always returns true"
| Choice1Of2 false ->
return failwith "should not happen - waitOneNoTimeoutOrCancellation always returns true"
| Choice2Of2 () ->
lock syncRoot (fun () ->
// Cancel the outstanding wait for messages installed by waitOneWithCancellation
......@@ -454,8 +455,10 @@ type MailboxProcessor<'Msg>(body, ?cancellationToken) =
// 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
......
......@@ -22,7 +22,14 @@ type internal MapTree<'Key, 'Value>(k: 'Key, v: 'Value, h: int) =
[<NoEquality; NoComparison>]
[<Sealed>]
[<AllowNullLiteral>]
type internal MapTreeNode<'Key, 'Value>(k: 'Key, v: 'Value, left: MapTree<'Key, 'Value>, right: MapTree<'Key, 'Value>, h: int) =
type internal MapTreeNode<'Key, 'Value>
(
k: 'Key,
v: 'Value,
left: MapTree<'Key, 'Value>,
right: MapTree<'Key, 'Value>,
h: int
) =
inherit MapTree<'Key, 'Value>(k, v, h)
member _.Left = left
member _.Right = right
......@@ -68,7 +75,7 @@ module MapTree =
traceCount <- traceCount + 1
if traceCount % 1000000 = 0 then
System.Console.WriteLine(
Console.WriteLine(
"#MapOne = {0}, #MapNode = {1}, #Add = {2}, #Remove = {3}, #Unions = {4}, #Lookups = {5}, avMapTreeSizeOnNodeCreation = {6}, avMapSizeOnCreation = {7}, avMapSizeOnLookup = {8}",
numOnes,
numNodes,
......@@ -81,7 +88,7 @@ module MapTree =
(totalSizeOnMapLookup / float numLookups)
)
System.Console.WriteLine("#largestMapSize = {0}, largestMapStackTrace = {1}", largestMapSize, largestMapStackTrace)
Console.WriteLine("#largestMapSize = {0}, largestMapStackTrace = {1}", largestMapSize, largestMapStackTrace)
let MapTree (k, v) =
report ()
......@@ -202,7 +209,12 @@ module MapTree =
else
(acc1, add comparer k v acc2)
let rec partitionAux (comparer: IComparer<'Key>) (f: OptimizedClosures.FSharpFunc<_, _, _>) (m: MapTree<'Key, 'Value>) acc =
let rec partitionAux
(comparer: IComparer<'Key>)
(f: OptimizedClosures.FSharpFunc<_, _, _>)
(m: MapTree<'Key, 'Value>)
acc
=
if isEmpty m then
acc
else if m.Height = 1 then
......@@ -222,7 +234,12 @@ module MapTree =
else
acc
let rec filterAux (comparer: IComparer<'Key>) (f: OptimizedClosures.FSharpFunc<_, _, _>) (m: MapTree<'Key, 'Value>) acc =
let rec filterAux
(comparer: IComparer<'Key>)
(f: OptimizedClosures.FSharpFunc<_, _, _>)
(m: MapTree<'Key, 'Value>)
acc
=
if isEmpty m then
acc
else if m.Height = 1 then
......@@ -273,7 +290,12 @@ module MapTree =
else
rebalance mn.Left mn.Key mn.Value (remove comparer k mn.Right)
let rec change (comparer: IComparer<'Key>) k (u: 'Value option -> 'Value option) (m: MapTree<'Key, 'Value>) : MapTree<'Key, 'Value> =
let rec change
(comparer: IComparer<'Key>)
k
(u: 'Value option -> 'Value option)
(m: MapTree<'Key, 'Value>)
: MapTree<'Key, 'Value> =
if isEmpty m then
match u None with
| None -> m
......@@ -440,7 +462,14 @@ module MapTree =
let fold f x m =
foldOpt (OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt f) x m
let foldSectionOpt (comparer: IComparer<'Key>) lo hi (f: OptimizedClosures.FSharpFunc<_, _, _, _>) (m: MapTree<'Key, 'Value>) x =
let foldSectionOpt
(comparer: IComparer<'Key>)
lo
hi
(f: OptimizedClosures.FSharpFunc<_, _, _, _>)
(m: MapTree<'Key, 'Value>)
x
=
let rec foldFromTo (f: OptimizedClosures.FSharpFunc<_, _, _, _>) (m: MapTree<'Key, 'Value>) x =
if isEmpty m then
x
......
......@@ -256,12 +256,16 @@ and [<CompiledName("FSharpExpr"); StructuredFormatDisplay("{DebugText}")>] Expr(
eq t1 (CombTerm(InstanceMethodCallOp(minfo2), obj2 :: args2WithoutWitnesses))
// We strip off StaticMethodCallWOp to ensure that CallWithWitness = Call
| CombTerm (StaticMethodCallWOp (minfo1, _minfoW1, nWitnesses1), args1), _ when nWitnesses1 <= args1.Length ->
| CombTerm (StaticMethodCallWOp (minfo1, _minfoW1, nWitnesses1), args1), _ when
nWitnesses1 <= args1.Length
->
let argsWithoutWitnesses1 = List.skip nWitnesses1 args1
eq (CombTerm(StaticMethodCallOp(minfo1), argsWithoutWitnesses1)) t2
// We strip off StaticMethodCallWOp to ensure that CallWithWitness = Call
| _, CombTerm (StaticMethodCallWOp (minfo2, _minfoW2, nWitnesses2), args2) when nWitnesses2 <= args2.Length ->
| _, CombTerm (StaticMethodCallWOp (minfo2, _minfoW2, nWitnesses2), args2) when
nWitnesses2 <= args2.Length
->
let argsWithoutWitnesses2 = List.skip nWitnesses2 args2
eq t1 (CombTerm(StaticMethodCallOp(minfo2), argsWithoutWitnesses2))
......@@ -383,11 +387,14 @@ and [<CompiledName("FSharpExpr"); StructuredFormatDisplay("{DebugText}")>] Expr(
| CombTerm (ValueOp (v, _, None), []) -> combL "Value" [ objL v ]
| CombTerm (WithValueOp (v, _), [ defn ]) -> combL "WithValue" [ objL v; expr defn ]
| CombTerm (InstanceMethodCallOp (minfo), obj :: args) -> combL "Call" [ someL obj; minfoL minfo; listL (exprs args) ]
| CombTerm (InstanceMethodCallOp (minfo), obj :: args) ->
combL "Call" [ someL obj; minfoL minfo; listL (exprs args) ]
| CombTerm (StaticMethodCallOp (minfo), args) -> combL "Call" [ noneL; minfoL minfo; listL (exprs args) ]
| CombTerm (InstanceMethodCallWOp (minfo, _minfoW, nWitnesses), obj :: argsWithoutObj) when nWitnesses <= argsWithoutObj.Length ->
| CombTerm (InstanceMethodCallWOp (minfo, _minfoW, nWitnesses), obj :: argsWithoutObj) when
nWitnesses <= argsWithoutObj.Length
->
let argsWithoutWitnesses = List.skip nWitnesses argsWithoutObj
combL "Call" [ someL obj; minfoL minfo; listL (exprs argsWithoutWitnesses) ]
......@@ -395,9 +402,11 @@ and [<CompiledName("FSharpExpr"); StructuredFormatDisplay("{DebugText}")>] Expr(
let argsWithoutWitnesses = List.skip nWitnesses args
combL "Call" [ noneL; minfoL minfo; listL (exprs argsWithoutWitnesses) ]
| CombTerm (InstancePropGetOp (pinfo), (obj :: args)) -> combL "PropertyGet" [ someL obj; pinfoL pinfo; listL (exprs args) ]
| CombTerm (InstancePropGetOp (pinfo), (obj :: args)) ->
combL "PropertyGet" [ someL obj; pinfoL pinfo; listL (exprs args) ]
| CombTerm (StaticPropGetOp (pinfo), args) -> combL "PropertyGet" [ noneL; pinfoL pinfo; listL (exprs args) ]
| CombTerm (InstancePropSetOp (pinfo), (obj :: args)) -> combL "PropertySet" [ someL obj; pinfoL pinfo; listL (exprs args) ]
| CombTerm (InstancePropSetOp (pinfo), (obj :: args)) ->
combL "PropertySet" [ someL obj; pinfoL pinfo; listL (exprs args) ]
| CombTerm (StaticPropSetOp (pinfo), args) -> combL "PropertySet" [ noneL; pinfoL pinfo; listL (exprs args) ]
| CombTerm (InstanceFieldGetOp (finfo), [ obj ]) -> combL "FieldGet" [ someL obj; finfoL finfo ]
| CombTerm (StaticFieldGetOp (finfo), []) -> combL "FieldGet" [ noneL; finfoL finfo ]
......@@ -415,7 +424,8 @@ and [<CompiledName("FSharpExpr"); StructuredFormatDisplay("{DebugText}")>] Expr(
combL "ForIntegerRangeLoop" [ varL v; expr e1; expr e2; expr e3 ]
| CombTerm (WhileLoopOp, args) -> combL "WhileLoop" (exprs args)
| CombTerm (TryFinallyOp, args) -> combL "TryFinally" (exprs args)
| CombTerm (TryWithOp, [ e1; Lambda (v1, e2); Lambda (v2, e3) ]) -> combL "TryWith" [ expr e1; varL v1; expr e2; varL v2; expr e3 ]
| CombTerm (TryWithOp, [ e1; Lambda (v1, e2); Lambda (v2, e3) ]) ->
combL "TryWith" [ expr e1; varL v1; expr e2; varL v2; expr e3 ]
| CombTerm (SequentialOp, args) -> combL "Sequential" (exprs args)
| CombTerm (NewDelegateOp ty, [ e ]) ->
......@@ -764,7 +774,9 @@ module Patterns =
Some(None, minfo, List.skip nWitnesses args)
// A InstanceMethodCallWOp matches as if it were a InstanceMethodCallOp
| E (CombTerm (InstanceMethodCallWOp (minfo, _minfoW, nWitnesses), obj :: argsWithoutObj)) when nWitnesses <= argsWithoutObj.Length ->
| E (CombTerm (InstanceMethodCallWOp (minfo, _minfoW, nWitnesses), obj :: argsWithoutObj)) when
nWitnesses <= argsWithoutObj.Length
->
let argsWithoutWitnesses = List.skip nWitnesses argsWithoutObj
Some(Some obj, minfo, argsWithoutWitnesses)
......@@ -854,7 +866,8 @@ module Patterns =
match cases |> Array.tryFind (fun ucase -> ucase.Name = unionCaseName) with
| Some case -> case
| _ -> invalidArg "unionCaseName" (String.Format(SR.GetString(SR.QmissingUnionCase), ty.FullName, unionCaseName))
| _ ->
invalidArg "unionCaseName" (String.Format(SR.GetString(SR.QmissingUnionCase), ty.FullName, unionCaseName))
let getUnionCaseInfoField (unionCase: UnionCaseInfo, index) =
let fields = unionCase.GetFields()
......@@ -981,7 +994,8 @@ module Patterns =
invalidArg "args" (SR.GetString(SR.QincorrectNumArgs))
List.iter2
(fun (p: ParameterInfo) a -> checkTypesWeakSR p.ParameterType (typeOf a) "args" (SR.GetString(SR.QtmmInvalidParam)))
(fun (p: ParameterInfo) a ->
checkTypesWeakSR p.ParameterType (typeOf a) "args" (SR.GetString(SR.QtmmInvalidParam)))
(paramInfos |> Array.toList)
args
// todo: shouldn't this be "strong" type check? sometimes?
......@@ -1140,7 +1154,8 @@ module Patterns =
invalidArg "args" (SR.GetString(SR.QincompatibleRecordLength))
List.iter2
(fun (minfo: PropertyInfo) a -> checkTypesSR minfo.PropertyType (typeOf a) "recd" (SR.GetString(SR.QtmmIncorrectArgForRecord)))
(fun (minfo: PropertyInfo) a ->
checkTypesSR minfo.PropertyType (typeOf a) "recd" (SR.GetString(SR.QtmmIncorrectArgForRecord)))
(Array.toList mems)
args
......@@ -1157,7 +1172,8 @@ module Patterns =
invalidArg "args" (SR.GetString(SR.QunionNeedsDiffNumArgs))
List.iter2
(fun (minfo: PropertyInfo) a -> checkTypesSR minfo.PropertyType (typeOf a) "sum" (SR.GetString(SR.QtmmIncorrectArgForUnion)))
(fun (minfo: PropertyInfo) a ->
checkTypesSR minfo.PropertyType (typeOf a) "sum" (SR.GetString(SR.QtmmIncorrectArgForUnion)))
(Array.toList sargs)
args
......@@ -1894,7 +1910,10 @@ module Patterns =
// For some reason we can get 'null' returned here even when a type with the right name exists... Hence search the slow way...
match (assembly.GetTypes() |> Array.tryFind (fun a -> a.FullName = tcName)) with
| Some ty -> ty
| None -> invalidArg "tcName" (String.Format(SR.GetString(SR.QfailedToBindTypeInAssembly), tcName, assembly.FullName))
| None ->
invalidArg
"tcName"
(String.Format(SR.GetString(SR.QfailedToBindTypeInAssembly), tcName, assembly.FullName))
| ty -> ty
let decodeNamedTy genericType tsR =
......@@ -2151,7 +2170,8 @@ module Patterns =
and instModuleDefnOp r tyargs _ =
match r with
| StaticMethodCallOp (minfo) -> StaticMethodCallOp(instMeth (minfo, tyargs))
| StaticMethodCallWOp (minfo, minfoW, n) -> StaticMethodCallWOp(instMeth (minfo, tyargs), instMeth (minfoW, tyargs), n)
| StaticMethodCallWOp (minfo, minfoW, n) ->
StaticMethodCallWOp(instMeth (minfo, tyargs), instMeth (minfoW, tyargs), n)
// OK to throw away the tyargs here since this only non-generic values in modules get represented by static properties
| x -> x
......@@ -2313,7 +2333,8 @@ module Patterns =
let h = l.[idx]
match typeOf h with
| expected when expected <> ty -> invalidArg "receivedType" (String.Format(SR.GetString(SR.QtmmRaw), expected, ty))
| expected when expected <> ty ->
invalidArg "receivedType" (String.Format(SR.GetString(SR.QtmmRaw), expected, ty))
| _ -> h
let rec freeInExprAcc bvs acc (E t) =
......@@ -2373,7 +2394,8 @@ module Patterns =
if v = bv then
let v2 = new Var(v.Name, v.Type)
let v2exp = E(VarTerm v2)
EA(LambdaTerm(v2, substituteInExpr bvs (fun v -> if v = bv then Some v2exp else tmsubst v) b), e.CustomAttributes)
let b2 = substituteInExpr bvs (fun v -> if v = bv then Some v2exp else tmsubst v) b
EA(LambdaTerm(v2, b2), e.CustomAttributes)
else
reraise ()
| HoleTerm _ -> e
......@@ -2417,6 +2439,9 @@ module Patterns =
decodedTopResources.Add((assem, resourceName), 0)
let isReflectedDefinitionResourceName (resourceName: string) =
resourceName.StartsWith(ReflectedDefinitionsResourceNameBase, StringComparison.Ordinal)
/// Get the reflected definition at the given (always generic) instantiation
let tryGetReflectedDefinition (methodBase: MethodBase, tyargs: Type[]) =
checkNonNull "methodBase" methodBase
......@@ -2448,7 +2473,7 @@ module Patterns =
[
for resourceName in resources do
if
resourceName.StartsWith(ReflectedDefinitionsResourceNameBase, StringComparison.Ordinal)
isReflectedDefinitionResourceName resourceName
&& not (decodedTopResources.ContainsKey((assem, resourceName)))
then
......@@ -2459,7 +2484,8 @@ module Patterns =
| x -> x)
|> Array.tryPick (fun ca ->
match ca with
| :? CompilationMappingAttribute as cma when cma.ResourceName = resourceName -> Some cma
| :? CompilationMappingAttribute as cma when cma.ResourceName = resourceName ->
Some cma
| _ -> None)
let resourceBytes = readToEnd (assem.GetManifestResourceStream resourceName)
......@@ -2481,7 +2507,8 @@ module Patterns =
|> List.iter (fun (resourceName, defns) ->
defns
|> List.iter (fun (methodBase, exprBuilder) ->
reflectedDefinitionTable.[ReflectedDefinitionTableKey.GetKey methodBase] <- Entry exprBuilder)
reflectedDefinitionTable.[ReflectedDefinitionTableKey.GetKey methodBase] <-
Entry exprBuilder)
decodedTopResources.[(assem, resourceName)] <- 0)
// we know it's in the table now, if it's ever going to be there
......@@ -2581,7 +2608,14 @@ type Expr with
checkNonNull "methodInfoWithWitnesses" methodInfoWithWitnesses
mkStaticMethodCallW (methodInfo, methodInfoWithWitnesses, List.length witnesses, witnesses @ arguments)
static member CallWithWitnesses(obj: Expr, methodInfo: MethodInfo, methodInfoWithWitnesses: MethodInfo, witnesses, arguments) =
static member CallWithWitnesses
(
obj: Expr,
methodInfo: MethodInfo,
methodInfoWithWitnesses: MethodInfo,
witnesses,
arguments
) =
checkNonNull "methodInfo" methodInfo
checkNonNull "methodInfoWithWitnesses" methodInfoWithWitnesses
mkInstanceMethodCallW (obj, methodInfo, methodInfoWithWitnesses, List.length witnesses, witnesses @ arguments)
......@@ -2988,7 +3022,8 @@ module ExprShape =
| StaticMethodCallOp minfo, _ -> mkStaticMethodCall (minfo, arguments)
| InstanceMethodCallOp minfo, obj :: args -> mkInstanceMethodCall (obj, minfo, args)
| StaticMethodCallWOp (minfo, minfoW, n), _ -> mkStaticMethodCallW (minfo, minfoW, n, arguments)
| InstanceMethodCallWOp (minfo, minfoW, n), obj :: args -> mkInstanceMethodCallW (obj, minfo, minfoW, n, args)
| InstanceMethodCallWOp (minfo, minfoW, n), obj :: args ->
mkInstanceMethodCallW (obj, minfo, minfoW, n, args)
| CoerceOp ty, [ arg ] -> mkCoerce (ty, arg)
| NewArrayOp ty, _ -> mkNewArray (ty, arguments)
| NewDelegateOp ty, [ arg ] -> mkNewDelegate (ty, arg)
......
......@@ -83,11 +83,11 @@ module internal Impl =
let compilePropGetterFunc (prop: PropertyInfo) =
let param = Expression.Parameter(typeof<obj>, "param")
let propExpr =
Expression.Property(Expression.Convert(param, prop.DeclaringType), prop)
let expr =
Expression.Lambda<Func<obj, obj>>(
Expression.Convert(Expression.Property(Expression.Convert(param, prop.DeclaringType), prop), typeof<obj>),
param
)
Expression.Lambda<Func<obj, obj>>(Expression.Convert(propExpr, typeof<obj>), param)
expr.Compile()
......@@ -103,7 +103,8 @@ module internal Impl =
Expression.NewArrayInit(
typeof<obj>,
[
for prop in props -> Expression.Convert(Expression.Property(typedParam, prop), typeof<obj>) :> Expression
for prop in props ->
Expression.Convert(Expression.Property(typedParam, prop), typeof<obj>) :> Expression
]
)
),
......@@ -125,8 +126,8 @@ module internal Impl =
for paramIndex in 0 .. ctorParams.Length - 1 do
let p = ctorParams.[paramIndex]
Expression.Convert(Expression.ArrayAccess(paramArray, Expression.Constant paramIndex), p.ParameterType)
:> Expression
let accessExpr = Expression.ArrayAccess(paramArray, Expression.Constant paramIndex)
Expression.Convert(accessExpr, p.ParameterType) :> Expression
]
),
typeof<obj>
......@@ -149,8 +150,8 @@ module internal Impl =
for paramIndex in 0 .. methodParams.Length - 1 do
let p = methodParams.[paramIndex]
Expression.Convert(Expression.ArrayAccess(paramArray, Expression.Constant paramIndex), p.ParameterType)
:> Expression
let accessExpr = Expression.ArrayAccess(paramArray, Expression.Constant paramIndex)
Expression.Convert(accessExpr, p.ParameterType) :> Expression
]
),
typeof<obj>
......@@ -184,14 +185,20 @@ module internal Impl =
if paramIndex = tupleEncField then
constituentTuple genericArg elements (startIndex + paramIndex) :> Expression
else
Expression.Convert(Expression.ArrayAccess(elements, Expression.Constant(startIndex + paramIndex)), genericArg)
Expression.Convert(
Expression.ArrayAccess(elements, Expression.Constant(startIndex + paramIndex)),
genericArg
)
]
)
let elements = Expression.Parameter(typeof<obj[]>, "elements")
let expr =
Expression.Lambda<Func<obj[], obj>>(Expression.Convert(constituentTuple typ elements 0, typeof<obj>), elements)
Expression.Lambda<Func<obj[], obj>>(
Expression.Convert(constituentTuple typ elements 0, typeof<obj>),
elements
)
expr.Compile()
......@@ -201,9 +208,11 @@ module internal Impl =
let elements =
match getTupleElementAccessors typ with
// typ is a struct tuple and its elements are accessed via fields
| Choice1Of2 (fi: FieldInfo[]) -> fi |> Array.map (fun fi -> Expression.Field(tuple, fi), fi.FieldType)
| Choice1Of2 (fi: FieldInfo[]) ->
fi |> Array.map (fun fi -> Expression.Field(tuple, fi), fi.FieldType)
// typ is a class tuple and its elements are accessed via properties
| Choice2Of2 (pi: PropertyInfo[]) -> pi |> Array.map (fun pi -> Expression.Property(tuple, pi), pi.PropertyType)
| Choice2Of2 (pi: PropertyInfo[]) ->
pi |> Array.map (fun pi -> Expression.Property(tuple, pi), pi.PropertyType)
for index, (element, elementType) in elements |> Array.indexed do
if index = tupleEncField then
......@@ -241,14 +250,12 @@ module internal Impl =
Expression.Block(
[ outputArray ],
[
yield
Expression.Assign(
outputArray,
Expression.NewArrayBounds(typeof<obj>, Expression.Constant(outputLength tupleEncField typ))
)
:> Expression
let arrayBounds =
Expression.NewArrayBounds(typeof<obj>, Expression.Constant(outputLength tupleEncField typ))
Expression.Assign(outputArray, arrayBounds) :> Expression
yield! writeTupleIntoArray typ (Expression.Convert(param, typ)) outputArray 0
yield outputArray :> Expression
outputArray :> Expression
]
),
param
......@@ -263,7 +270,9 @@ module internal Impl =
match attrs with
| null
| [||] -> None
| [| res |] -> let a = (res :?> CompilationMappingAttribute) in Some(a.SourceConstructFlags, a.SequenceNumber, a.VariantNumber)
| [| res |] ->
let a = (res :?> CompilationMappingAttribute)
Some(a.SourceConstructFlags, a.SequenceNumber, a.VariantNumber)
| _ -> invalidOp (SR.GetString(SR.multipleCompilationMappings))
let findCompilationMappingAttribute (attrs: obj[]) =
......@@ -287,12 +296,24 @@ module internal Impl =
let flags =
match args.Count with
| 1 -> ((let x = args.[0] in x.Value :?> SourceConstructFlags), 0, 0)
| 2 -> ((let x = args.[0] in x.Value :?> SourceConstructFlags), (let x = args.[1] in x.Value :?> int), 0)
| 1 ->
let arg0 = args.[0]
let v0 = arg0.Value :?> SourceConstructFlags
(v0, 0, 0)
| 2 ->
let arg0 = args.[0]
let v0 = arg0.Value :?> SourceConstructFlags
let arg1 = args.[1]
let v1 = arg1.Value :?> int
(v0, v1, 0)
| 3 ->
((let x = args.[0] in x.Value :?> SourceConstructFlags),
(let x = args.[1] in x.Value :?> int),
(let x = args.[2] in x.Value :?> int))
let arg0 = args.[0]
let v0 = arg0.Value :?> SourceConstructFlags
let arg1 = args.[1]
let v1 = arg1.Value :?> int
let arg2 = args.[2]
let v2 = arg2.Value :?> int
(v0, v1, v2)
| _ -> (enum 0, 0, 0)
res <- Some flags
......@@ -579,12 +600,16 @@ module internal Impl =
"New" + constrname
match typ.GetMethod(methname, BindingFlags.Static ||| bindingFlags) with
| null -> invalidOp (String.Format(SR.GetString(SR.constructorForUnionCaseNotFound), methname))
| null ->
let msg = String.Format(SR.GetString(SR.constructorForUnionCaseNotFound), methname)
invalidOp msg
| meth -> meth
let getUnionCaseConstructor (typ: Type, tag: int, bindingFlags) =
let meth = getUnionCaseConstructorMethod (typ, tag, bindingFlags)
(fun args -> meth.Invoke(null, BindingFlags.Static ||| BindingFlags.InvokeMethod ||| bindingFlags, null, args, null))
(fun args ->
meth.Invoke(null, BindingFlags.Static ||| BindingFlags.InvokeMethod ||| bindingFlags, null, args, null))
let getUnionCaseConstructorCompiled (typ: Type, tag: int, bindingFlags) =
let meth = getUnionCaseConstructorMethod (typ, tag, bindingFlags)
......@@ -595,9 +620,11 @@ module internal Impl =
if not (isUnionType (unionType, bindingFlags)) then
if isUnionType (unionType, bindingFlags ||| BindingFlags.NonPublic) then
invalidArg "unionType" (String.Format(SR.GetString(SR.privateUnionType), unionType.FullName))
let msg = String.Format(SR.GetString(SR.privateUnionType), unionType.FullName)
invalidArg "unionType" msg
else
invalidArg "unionType" (String.Format(SR.GetString(SR.notAUnionType), unionType.FullName))
let msg = String.Format(SR.GetString(SR.notAUnionType), unionType.FullName)
invalidArg "unionType" msg
//-----------------------------------------------------------------
// TUPLE DECOMPILATION
......@@ -718,7 +745,8 @@ module internal Impl =
let rec getTupleTypeInfo (typ: Type) =
if not (isTupleType typ) then
invalidArg "typ" (String.Format(SR.GetString(SR.notATupleType), typ.FullName))
let msg = String.Format(SR.GetString(SR.notATupleType), typ.FullName)
invalidArg "typ" msg
let tyargs = typ.GetGenericArguments()
......@@ -801,20 +829,35 @@ module internal Impl =
let fields =
typ.GetFields(instanceFieldFlags ||| BindingFlags.Public) |> orderTupleFields
typ.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, fields |> Array.map (fun fi -> fi.FieldType), null)
typ.GetConstructor(
BindingFlags.Public ||| BindingFlags.Instance,
null,
fields |> Array.map (fun fi -> fi.FieldType),
null
)
else
let props = typ.GetProperties() |> orderTupleProperties
typ.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, props |> Array.map (fun p -> p.PropertyType), null)
typ.GetConstructor(
BindingFlags.Public ||| BindingFlags.Instance,
null,
props |> Array.map (fun p -> p.PropertyType),
null
)
match ctor with
| null -> raise (ArgumentException(String.Format(SR.GetString(SR.invalidTupleTypeConstructorNotDefined), typ.FullName)))
| null ->
let msg = String.Format(SR.GetString(SR.invalidTupleTypeConstructorNotDefined))
raise (ArgumentException(msg, typ.FullName))
| _ -> ()
ctor
let getTupleCtor (typ: Type) =
let ctor = getTupleConstructorMethod typ
(fun (args: obj[]) -> ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| BindingFlags.Public, null, args, null))
(fun (args: obj[]) ->
ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| BindingFlags.Public, null, args, null))
let getTupleElementAccessors (typ: Type) =
if typ.IsValueType then
......@@ -869,7 +912,10 @@ module internal Impl =
let getTupleReaderInfo (typ: Type, index: int) =
if index < 0 then
invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString()))
let msg =
String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())
invalidArg "index" msg
let get index =
if typ.IsValueType then
......@@ -878,7 +924,10 @@ module internal Impl =
|> orderTupleProperties
if index >= props.Length then
invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString()))
let msg =
String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())
invalidArg "index" msg
props.[index]
else
......@@ -887,7 +936,10 @@ module internal Impl =
|> orderTupleProperties
if index >= props.Length then
invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString()))
let msg =
String.Format(SR.GetString(SR.tupleIndexOutOfRange), typ.FullName, index.ToString())
invalidArg "index" msg
props.[index]
......@@ -944,19 +996,28 @@ module internal Impl =
let props = fieldPropsOfRecordType (typ, bindingFlags)
let ctor =
typ.GetConstructor(BindingFlags.Instance ||| bindingFlags, null, props |> Array.map (fun p -> p.PropertyType), null)
typ.GetConstructor(
BindingFlags.Instance ||| bindingFlags,
null,
props |> Array.map (fun p -> p.PropertyType),
null
)
match ctor with
| null ->
raise
<| ArgumentException(String.Format(SR.GetString(SR.invalidRecordTypeConstructorNotDefined), typ.FullName))
let msg =
String.Format(SR.GetString(SR.invalidRecordTypeConstructorNotDefined), typ.FullName)
raise (ArgumentException(msg))
| _ -> ()
ctor
let getRecordConstructor (typ: Type, bindingFlags) =
let ctor = getRecordConstructorMethod (typ, bindingFlags)
(fun (args: obj[]) -> ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| bindingFlags, null, args, null))
(fun (args: obj[]) ->
ctor.Invoke(BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| bindingFlags, null, args, null))
let getRecordConstructorCompiled (typ: Type, bindingFlags) =
let ctor = getRecordConstructorMethod (typ, bindingFlags)
......@@ -1001,24 +1062,31 @@ module internal Impl =
let checkExnType (exceptionType, bindingFlags) =
if not (isExceptionRepr (exceptionType, bindingFlags)) then
if isExceptionRepr (exceptionType, bindingFlags ||| BindingFlags.NonPublic) then
invalidArg "exceptionType" (String.Format(SR.GetString(SR.privateExceptionType), exceptionType.FullName))
let msg =
String.Format(SR.GetString(SR.privateExceptionType), exceptionType.FullName)
invalidArg "exceptionType" msg
else
invalidArg "exceptionType" (String.Format(SR.GetString(SR.notAnExceptionType), exceptionType.FullName))
let msg = String.Format(SR.GetString(SR.notAnExceptionType), exceptionType.FullName)
invalidArg "exceptionType" msg
let checkRecordType (argName, recordType, bindingFlags) =
checkNonNull argName recordType
if not (isRecordType (recordType, bindingFlags)) then
if isRecordType (recordType, bindingFlags ||| BindingFlags.NonPublic) then
invalidArg argName (String.Format(SR.GetString(SR.privateRecordType), recordType.FullName))
let msg = String.Format(SR.GetString(SR.privateRecordType), recordType.FullName)
invalidArg argName msg
else
invalidArg argName (String.Format(SR.GetString(SR.notARecordType), recordType.FullName))
let msg = String.Format(SR.GetString(SR.notARecordType), recordType.FullName)
invalidArg argName msg
let checkTupleType (argName, (tupleType: Type)) =
checkNonNull argName tupleType
if not (isTupleType tupleType) then
invalidArg argName (String.Format(SR.GetString(SR.notATupleType), tupleType.FullName))
let msg = String.Format(SR.GetString(SR.notATupleType), tupleType.FullName)
invalidArg argName msg
[<Sealed>]
type UnionCaseInfo(typ: System.Type, tag: int) =
......@@ -1228,7 +1296,8 @@ type FSharpValue =
checkNonNull "functionType" functionType
if not (isFunctionType functionType) then
invalidArg "functionType" (String.Format(SR.GetString(SR.notAFunctionType), functionType.FullName))
let msg = String.Format(SR.GetString(SR.notAFunctionType), functionType.FullName)
invalidArg "functionType" msg
checkNonNull "implementation" implementation
let domain, range = getFunctionTypeInfo functionType
......@@ -1248,7 +1317,8 @@ type FSharpValue =
let typ = tuple.GetType()
if not (isTupleType typ) then
invalidArg "tuple" (String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName))
let msg = String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName)
invalidArg "tuple" msg
getTupleReader typ tuple
......@@ -1257,12 +1327,16 @@ type FSharpValue =
let typ = tuple.GetType()
if not (isTupleType typ) then
invalidArg "tuple" (String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName))
let msg = String.Format(SR.GetString(SR.notATupleType), tuple.GetType().FullName)
invalidArg "tuple" msg
let fields = getTupleReader typ tuple
if index < 0 || index >= fields.Length then
invalidArg "index" (String.Format(SR.GetString(SR.tupleIndexOutOfRange), tuple.GetType().FullName, index.ToString()))
let msg =
String.Format(SR.GetString(SR.tupleIndexOutOfRange), tuple.GetType().FullName, index.ToString())
invalidArg "index" msg
fields.[index]
......@@ -1421,7 +1495,11 @@ module FSharpReflectionExtensions =
let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation
FSharpValue.PreComputeUnionTagReader(unionType, bindingFlags)
static member PreComputeUnionReader(unionCase: UnionCaseInfo, ?allowAccessToPrivateRepresentation) : (obj -> obj[]) =
static member PreComputeUnionReader
(
unionCase: UnionCaseInfo,
?allowAccessToPrivateRepresentation
) : (obj -> obj[]) =
let bindingFlags = getBindingFlags allowAccessToPrivateRepresentation
FSharpValue.PreComputeUnionReader(unionCase, bindingFlags)
......
......@@ -92,12 +92,15 @@ module StateMachineHelpers =
[<MethodImpl(MethodImplOptions.NoInlining)>]
let __resumableEntry () : int option =
failwith "__resumableEntry should always be guarded by __useResumableCode and only used in valid state machine implementations"
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 =
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>
......@@ -108,7 +111,9 @@ module StateMachineHelpers =
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 =
......@@ -167,13 +172,21 @@ module ResumableCode =
else
CombineDynamic(&sm, code1, code2))
let rec WhileDynamic (sm: byref<ResumableStateMachine<'Data>>, condition: unit -> bool, body: ResumableCode<'Data, unit>) : bool =
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
......@@ -189,11 +202,18 @@ module ResumableCode =
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
//-- RESUMABLE CODE START
......@@ -225,7 +245,8 @@ module ResumableCode =
let rf = GetResumptionFunc &sm
sm.ResumptionDynamicInfo.ResumptionFunc <-
(ResumptionFunc<'Data>(fun sm -> TryWithDynamic(&sm, ResumableCode<'Data, 'T>(fun sm -> rf.Invoke(&sm)), handler)))
(ResumptionFunc<'Data>(fun sm ->
TryWithDynamic(&sm, ResumableCode<'Data, 'T>(fun sm -> rf.Invoke(&sm)), handler)))
false
with exn ->
......@@ -233,7 +254,11 @@ module ResumableCode =
/// 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
//-- RESUMABLE CODE START
......@@ -260,7 +285,12 @@ module ResumableCode =
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)
......@@ -271,7 +301,10 @@ module ResumableCode =
| Some exn -> raise exn
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
......@@ -328,7 +361,11 @@ module ResumableCode =
/// 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
//-- RESUMABLE CODE START
......
......@@ -443,7 +443,8 @@ module Internal =
static member Bind(g: Generator<'T>, cont) =
match g with
| :? GenerateThen<'T> as g -> GenerateThen<_>.Bind (g.Generator, (fun () -> GenerateThen<_>.Bind (g.Cont(), cont)))
| :? GenerateThen<'T> as g ->
GenerateThen<_>.Bind (g.Generator, (fun () -> GenerateThen<_>.Bind (g.Cont(), cont)))
| g -> (new GenerateThen<'T>(g, cont) :> Generator<'T>)
let bindG g cont =
......@@ -1290,7 +1291,10 @@ module Seq =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let groupByRefType (keyf: 'T -> 'Key) (seq: seq<'T>) =
seq
|> groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(keyf t)) (fun sb -> sb.Value)
|> groupByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(keyf t))
(fun sb -> sb.Value)
[<CompiledName("GroupBy")>]
let groupBy (projection: 'T -> 'Key) (source: seq<'T>) =
......@@ -1402,7 +1406,10 @@ module Seq =
// Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
let countByRefType (keyf: 'T -> 'Key) (seq: seq<'T>) =
seq
|> countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox(keyf t)) (fun sb -> sb.Value)
|> countByImpl
RuntimeHelpers.StructBox<'Key>.Comparer
(fun t -> RuntimeHelpers.StructBox(keyf t))
(fun sb -> sb.Value)
[<CompiledName("CountBy")>]
let countBy (projection: 'T -> 'Key) (source: seq<'T>) =
......
......@@ -571,13 +571,21 @@ module internal SetTree =
compareStacks comparer (empty :: SetTree x1.Key :: t1) l2
else
let x1n = asNode x1
compareStacks comparer (x1n.Left :: (SetTreeNode(x1n.Key, empty, x1n.Right, 0) :> SetTree<'T>) :: t1) l2
compareStacks
comparer
(x1n.Left :: (SetTreeNode(x1n.Key, empty, x1n.Right, 0) :> SetTree<'T>) :: t1)
l2
| _, (x2 :: t2) when not (isEmpty x2) ->
if x2.Height = 1 then
compareStacks comparer l1 (empty :: SetTree x2.Key :: t2)
else
let x2n = asNode x2
compareStacks comparer l1 (x2n.Left :: (SetTreeNode(x2n.Key, empty, x2n.Right, 0) :> SetTree<'T>) :: t2)
compareStacks
comparer
l1
(x2n.Left :: (SetTreeNode(x2n.Key, empty, x2n.Right, 0) :> SetTree<'T>) :: t2)
| _ -> unexpectedstateInSetTreeCompareStacks ()
match l1, l2 with
......
......@@ -58,21 +58,37 @@ type TaskBuilderBase() =
/// 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> =
member inline _.TryFinally
(
body: TaskCode<'TOverall, 'T>,
[<InlineIfLambda>] compensation: unit -> unit
) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinally(
body,
ResumableCode<_, _>(fun _sm ->
......@@ -84,7 +100,11 @@ type TaskBuilderBase() =
ResumableCode.For(sequence, body)
#if NETSTANDARD2_1
member inline internal this.TryFinallyAsync(body: TaskCode<'TOverall, 'T>, compensation: unit -> ValueTask) : TaskCode<'TOverall, 'T> =
member inline internal this.TryFinallyAsync
(
body: TaskCode<'TOverall, 'T>,
compensation: unit -> ValueTask
) : TaskCode<'TOverall, 'T> =
ResumableCode.TryFinallyAsync(
body,
ResumableCode<_, _>(fun sm ->
......@@ -344,7 +364,11 @@ module LowPriority =
sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm)
false
else
TaskBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall>(&sm, task, continuation)
TaskBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall>(
&sm,
task,
continuation
)
//-- RESUMABLE CODE END
)
......@@ -370,7 +394,12 @@ module HighPriority =
// High priority extensions
type TaskBuilderBase with
static member BindDynamic(sm: byref<_>, task: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : bool =
static member BindDynamic
(
sm: byref<_>,
task: Task<'TResult1>,
continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)
) : bool =
let mutable awaiter = task.GetAwaiter()
let cont =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册