From 456ee9cb06e3e086c289fa6d1e4bbc923cf44a52 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Sun, 18 Dec 2022 04:09:48 +0100 Subject: [PATCH] Unifying generic type names, removing redundant annotations and more consistency in code --- src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs | 89 ++++++++----------- src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi | 21 +++-- 2 files changed, 50 insertions(+), 60 deletions(-) diff --git a/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs b/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs index e8f1f729..463323dd 100644 --- a/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs +++ b/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs @@ -307,7 +307,7 @@ and TaskSeqResumptionDynamicInfo<'T> = ResumptionDynamicInfo ResumableTSC<'T>) : ResumableTSC<'T> = ResumableTSC<'T>(fun sm -> f().Invoke(&sm)) + member inline _.Delay(f: unit -> ResumableTSC<'T>) = ResumableTSC<'T>(fun sm -> f().Invoke(&sm)) member inline _.Run(code: ResumableTSC<'T>) : IAsyncEnumerable<'T> = if __useResumableCode then @@ -348,11 +348,9 @@ type TaskSeqBuilder() = // but only a reference to itself. let boxed = sm.Data.boxedSelf - sm.Data.awaiter.UnsafeOnCompleted( - Action(fun () -> - let mutable boxed = boxed - moveNextRef &boxed) - ) + sm.Data.awaiter.UnsafeOnCompleted(fun () -> + let mutable boxed = boxed + moveNextRef &boxed) with exn -> Debug.logInfo ("Setting exception of PromiseOfValueOrEnd to: ", exn.Message) @@ -386,7 +384,7 @@ type TaskSeqBuilder() = Debug.logInfo "at Zero()" ResumableCode.Zero() - member inline _.Combine(task1: ResumableTSC<'T>, task2: ResumableTSC<'T>) : ResumableTSC<'T> = + member inline _.Combine(task1: ResumableTSC<'T>, task2: ResumableTSC<'T>) = Debug.logInfo "at Combine(.., ..)" ResumableCode.Combine(task1, task2) @@ -401,7 +399,7 @@ type TaskSeqBuilder() = ResumableCode.While( (fun () -> condition_res), - ResumableCode<_, _>(fun sm -> + ResumableTSC<'T>(fun sm -> let mutable __stack_condition_fin = true let __stack_vtask = condition () @@ -432,25 +430,24 @@ type TaskSeqBuilder() = false) ) - member inline b.While([] condition: unit -> bool, body: ResumableTSC<'T>) : ResumableTSC<'T> = + member inline _.While([] condition: unit -> bool, body: ResumableTSC<'T>) = Debug.logInfo "at While(...)" ResumableCode.While(condition, body) - member inline _.TryWith(body: ResumableTSC<'T>, catch: exn -> ResumableTSC<'T>) : ResumableTSC<'T> = - ResumableCode.TryWith(body, catch) + member inline _.TryWith(body: ResumableTSC<'T>, catch: exn -> ResumableTSC<'T>) = ResumableCode.TryWith(body, catch) - member inline _.TryFinallyAsync(body: ResumableTSC<'T>, compensation: unit -> Task) : ResumableTSC<'T> = + member inline _.TryFinallyAsync(body: ResumableTSC<'T>, compensationAction: unit -> Task) = ResumableCode.TryFinallyAsync( ResumableTSC<'T>(fun sm -> - sm.Data.PushDispose(fun () -> compensation ()) + sm.Data.PushDispose compensationAction body.Invoke(&sm)), - ResumableCode<_, _>(fun sm -> + ResumableTSC<'T>(fun sm -> sm.Data.PopDispose() let mutable __stack_condition_fin = true - let __stack_vtask = compensation () + let __stack_vtask = compensationAction () if not __stack_vtask.IsCompleted then let mutable awaiter = __stack_vtask.GetAwaiter() @@ -463,22 +460,19 @@ type TaskSeqBuilder() = __stack_condition_fin) ) - member inline _.TryFinally(body: ResumableTSC<'T>, compensation: unit -> unit) : ResumableTSC<'T> = + member inline _.TryFinally(body: ResumableTSC<'T>, compensationAction: unit -> unit) = ResumableCode.TryFinally( ResumableTSC<'T>(fun sm -> - sm.Data.PushDispose(fun () -> - compensation () - Task.CompletedTask) - + sm.Data.PushDispose(compensationAction >> Task.get_CompletedTask) body.Invoke(&sm)), - ResumableCode<_, _>(fun sm -> + ResumableTSC<'T>(fun sm -> sm.Data.PopDispose() - compensation () + compensationAction () true) ) - member inline this.Using(disp: #IAsyncDisposable, body: #IAsyncDisposable -> ResumableTSC<'T>) : ResumableTSC<'T> = + member inline this.Using(disp: #IAsyncDisposable, body: #IAsyncDisposable -> ResumableTSC<'T>) = // A using statement is just a try/finally with the finally block disposing if non-null. this.TryFinallyAsync( @@ -490,14 +484,14 @@ type TaskSeqBuilder() = Task.CompletedTask) ) - member inline _.Yield(v: 'T) : ResumableTSC<'T> = + member inline _.Yield(value: 'T) : ResumableTSC<'T> = ResumableTSC<'T>(fun sm -> // This will yield with __stack_fin = false // This will resume with __stack_fin = true Debug.logInfo "at Yield" let __stack_fin = ResumableCode.Yield().Invoke(&sm) - sm.Data.current <- ValueSome v + sm.Data.current <- ValueSome value sm.Data.awaiter <- null __stack_fin) @@ -535,34 +529,33 @@ module LowPriority = // - Task<'T> (because it only implements GetResult() -> unit, not GetResult() -> 'TResult) [] - member inline _.Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall + member inline _.Bind< ^TaskLike, 'T, 'U, ^Awaiter, 'TOverall when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) and ^Awaiter :> ICriticalNotifyCompletion and ^Awaiter: (member get_IsCompleted: unit -> bool) - and ^Awaiter: (member GetResult: unit -> 'TResult1)> + and ^Awaiter: (member GetResult: unit -> 'T)> ( task: ^TaskLike, - continuation: ('TResult1 -> ResumableTSC<'TResult2>) - ) : ResumableTSC<'TResult2> = + continuation: ('T -> ResumableTSC<'U>) + ) = - ResumableTSC<'TResult2>(fun sm -> + ResumableTSC<'U>(fun sm -> let mutable awaiter = (^TaskLike: (member GetAwaiter: unit -> ^Awaiter) (task)) let mutable __stack_fin = true Debug.logInfo "at TaskLike bind" - if not (^Awaiter: (member get_IsCompleted: unit -> bool) (awaiter)) then + if not (^Awaiter: (member get_IsCompleted: unit -> bool) awaiter) then // This will yield with __stack_fin2 = false // This will resume with __stack_fin2 = true let __stack_fin2 = ResumableCode.Yield().Invoke(&sm) __stack_fin <- __stack_fin2 - Debug.logInfo ("at TaskLike bind: with __stack_fin = ", __stack_fin) Debug.logInfo ("at TaskLike bind: this.completed = ", sm.Data.completed) if __stack_fin then Debug.logInfo "at TaskLike bind!: finished awaiting, calling continuation" - let result = (^Awaiter: (member GetResult: unit -> 'TResult1) (awaiter)) + let result = (^Awaiter: (member GetResult: unit -> 'T) awaiter) (continuation result).Invoke(&sm) else @@ -577,43 +570,37 @@ module LowPriority = module MediumPriority = type TaskSeqBuilder with - member inline this.Using(disp: #IDisposable, body: #IDisposable -> ResumableTSC<'T>) : ResumableTSC<'T> = + member inline this.Using(dispensation: #IDisposable, body: #IDisposable -> ResumableTSC<'T>) = // A using statement is just a try/finally with the finally block disposing if non-null. this.TryFinally( - (fun sm -> (body disp).Invoke(&sm)), + (fun sm -> (body dispensation).Invoke(&sm)), (fun () -> // yes, this can be null from time to time - if not (isNull (box disp)) then - disp.Dispose()) + if not (isNull (box dispensation)) then + dispensation.Dispose()) ) - member inline this.For(sequence: seq<'TElement>, body: 'TElement -> ResumableTSC<'T>) : ResumableTSC<'T> = + member inline this.For(sequence: seq<'TElement>, body: 'TElement -> ResumableTSC<'T>) = // A for loop is just a using statement on the sequence's enumerator... this.Using( sequence.GetEnumerator(), // ... and its body is a while loop that advances the enumerator and runs the body on each element. - (fun e -> this.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke(&sm)))) + fun e -> this.While(e.MoveNext, (fun sm -> (body e.Current).Invoke(&sm))) ) - member inline this.YieldFrom(source: seq<'T>) : ResumableTSC<'T> = this.For(source, (fun v -> this.Yield(v))) + member inline this.YieldFrom(source: seq<'T>) : ResumableTSC<'T> = this.For(source, this.Yield) - member inline this.For - ( - source: #IAsyncEnumerable<'TElement>, - body: 'TElement -> ResumableTSC<'T> - ) : ResumableTSC<'T> = + member inline this.For(source: #IAsyncEnumerable<'TElement>, body: 'TElement -> ResumableTSC<'T>) = ResumableTSC<'T>(fun sm -> this .Using( source.GetAsyncEnumerator(sm.Data.cancellationToken), - (fun e -> - this.WhileAsync((fun () -> e.MoveNextAsync()), (fun sm -> (body e.Current).Invoke(&sm)))) + fun e -> this.WhileAsync(e.MoveNextAsync, (fun sm -> (body e.Current).Invoke(&sm))) ) .Invoke(&sm)) - member inline this.YieldFrom(source: IAsyncEnumerable<'T>) : ResumableTSC<'T> = - this.For(source, (fun v -> this.Yield(v))) + member inline this.YieldFrom(source: IAsyncEnumerable<'T>) = this.For(source, (fun v -> this.Yield(v))) [] module HighPriority = @@ -629,8 +616,8 @@ module HighPriority = // - In contrast, ValueTask<_> *does have* GetResult() -> 'TResult // - Conclusion: we do not need an extra overload anymore for ValueTask // - member inline _.Bind(task: Task<'TResult1>, continuation: ('TResult1 -> ResumableTSC<'T>)) : ResumableTSC<'T> = - ResumableTSC<'T>(fun sm -> + member inline _.Bind(task: Task<'T>, continuation: ('T -> ResumableTSC<'U>)) = + ResumableTSC<'U>(fun sm -> let mutable awaiter = task.GetAwaiter() let mutable __stack_fin = true diff --git a/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi b/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi index 4f115910..c6e9d6ea 100644 --- a/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi +++ b/src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi @@ -131,14 +131,15 @@ type TaskSeqBuilder = member inline Combine: task1: ResumableTSC<'T> * task2: ResumableTSC<'T> -> ResumableTSC<'T> member inline Delay: f: (unit -> ResumableTSC<'T>) -> ResumableTSC<'T> member inline Run: code: ResumableTSC<'T> -> taskSeq<'T> - member inline TryFinally: body: ResumableTSC<'T> * compensation: (unit -> unit) -> ResumableTSC<'T> - member inline TryFinallyAsync: body: ResumableTSC<'T> * compensation: (unit -> Task) -> ResumableTSC<'T> + member inline TryFinally: body: ResumableTSC<'T> * compensationAction: (unit -> unit) -> ResumableTSC<'T> + member inline TryFinallyAsync: body: ResumableTSC<'T> * compensationAction: (unit -> Task) -> ResumableTSC<'T> member inline TryWith: body: ResumableTSC<'T> * catch: (exn -> ResumableTSC<'T>) -> ResumableTSC<'T> - member inline Using: disp: 'a * body: ('a -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'a :> IAsyncDisposable + member inline Using: + disp: 'Disp * body: ('Disp -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'Disp :> IAsyncDisposable member inline While: condition: (unit -> bool) * body: ResumableTSC<'T> -> ResumableTSC<'T> /// Used by `For`. F# currently doesn't support `while!`, so this cannot be called directly from the CE member inline WhileAsync: condition: (unit -> ValueTask) * body: ResumableTSC<'T> -> ResumableTSC<'T> - member inline Yield: v: 'T -> ResumableTSC<'T> + member inline Yield: value: 'T -> ResumableTSC<'T> member inline Zero: unit -> ResumableTSC<'T> [] @@ -159,12 +160,12 @@ module LowPriority = type TaskSeqBuilder with [] - member inline Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall> : - task: ^TaskLike * continuation: ('TResult1 -> ResumableTSC<'TResult2>) -> ResumableTSC<'TResult2> + member inline Bind< ^TaskLike, 'T, 'U, ^Awaiter, 'TOverall> : + task: ^TaskLike * continuation: ('T -> ResumableTSC<'U>) -> ResumableTSC<'U> when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) and ^Awaiter :> ICriticalNotifyCompletion and ^Awaiter: (member get_IsCompleted: unit -> bool) - and ^Awaiter: (member GetResult: unit -> 'TResult1) + and ^Awaiter: (member GetResult: unit -> 'T) /// /// Contains low priority extension methods for the main builder class for the computation expression. @@ -175,7 +176,9 @@ module LowPriority = module MediumPriority = type TaskSeqBuilder with - member inline Using: disp: 'a * body: ('a -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'a :> IDisposable + // NOTE: syntax with '#Disposable' won't work properly in FSI + member inline Using: + dispensation: 'Disp * body: ('Disp -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'Disp :> IDisposable member inline For: sequence: seq<'TElement> * body: ('TElement -> ResumableTSC<'T>) -> ResumableTSC<'T> member inline YieldFrom: source: seq<'T> -> ResumableTSC<'T> member inline For: source: #taskSeq<'TElement> * body: ('TElement -> ResumableTSC<'T>) -> ResumableTSC<'T> @@ -190,4 +193,4 @@ module MediumPriority = module HighPriority = type TaskSeqBuilder with - member inline Bind: task: Task<'TResult1> * continuation: ('TResult1 -> ResumableTSC<'T>) -> ResumableTSC<'T> + member inline Bind: task: Task<'T> * continuation: ('T -> ResumableTSC<'U>) -> ResumableTSC<'U>