Skip to content
Paul Westcott edited this page Dec 9, 2016 · 1 revision
    module Core =
        [<Struct; NoComparison; NoEquality>]
        type NoValue = struct end

        [<Struct; NoComparison; NoEquality>]
        type Values<'a,'b> =
            val mutable _1 : 'a
            val mutable _2 : 'b

            new (a:'a, b: 'b) = { _1 = a;  _2 = b }

        [<Struct; NoComparison; NoEquality>]
        type Values<'a,'b,'c> =
            val mutable _1 : 'a
            val mutable _2 : 'b
            val mutable _3 : 'c

            new (a:'a, b:'b, c:'c) = { _1 = a; _2 = b; _3 = c }

        type PipeIdx = int

        type IOutOfBand =
            abstract StopFurtherProcessing : PipeIdx -> unit

        type ICompletionChain =
            abstract OnComplete : stopTailCall:byref<unit> * PipeIdx -> unit
            abstract OnDispose  : stopTailCall:byref<unit> -> unit

        [<AbstractClass>]
        type Consumer<'T,'U> () =
            abstract ProcessNext : input:'T -> bool

            interface ICompletionChain with
                member this.OnComplete (_,_) = ()
                member this.OnDispose _ = ()

        [<AbstractClass>]
        type ConsumerWithState<'T,'U,'Value> =
            inherit Consumer<'T,'U>

            val mutable Value : 'Value

            new (init) = {
                Value = init
            }

        [<AbstractClass>]
        type ConsumerChainedWithState<'T,'U,'Value> =
            inherit ConsumerWithState<'T,'U,'Value>

            val private Next : ICompletionChain

            new (next:ICompletionChain, init) = {
                inherit ConsumerWithState<'T,'U,'Value> (init)
                Next = next
            }

            interface ICompletionChain with
                member this.OnComplete (stopTailCall, terminatingIdx) =
                    this.Next.OnComplete (&stopTailCall, terminatingIdx)
                member this.OnDispose stopTailCall =
                    this.Next.OnDispose (&stopTailCall)

        [<AbstractClass>]
        type ConsumerChained<'T,'U>(next:ICompletionChain) =
            inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof<NoValue>)

        [<AbstractClass>] 
        type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> (next, init) =
            inherit ConsumerChainedWithState<'T,'U,'Value>(next, init)

            abstract OnComplete : PipeIdx -> unit
            abstract OnDispose  : unit -> unit

            interface ICompletionChain with
                member this.OnComplete (stopTailCall, terminatingIdx) =
                    this.OnComplete terminatingIdx
                    next.OnComplete (&stopTailCall, terminatingIdx)
                member this.OnDispose stopTailCall  =
                    try     this.OnDispose ()
                    finally next.OnDispose (&stopTailCall)

        [<AbstractClass>]
        type ConsumerChainedWithCleanup<'T,'U>(next:ICompletionChain) =
            inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof<NoValue>)

        [<AbstractClass>]
        type Folder<'T,'U>(init) =
            inherit ConsumerWithState<'T,'T,'U>(init)

        [<AbstractClass>]
        type FolderWithOnComplete<'T, 'U>(init) =
            inherit Folder<'T,'U>(init)

            abstract OnComplete : PipeIdx -> unit

            interface ICompletionChain with
                member this.OnComplete (stopTailCall, terminatingIdx) =
                    this.OnComplete terminatingIdx
                member this.OnDispose _ = ()

        [<AbstractClass>]
        type SeqFactory<'T,'U> () =
            abstract PipeIdx : PipeIdx
            abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V>

            default __.PipeIdx = 1

            member this.Build outOfBand next = this.Create outOfBand 1 next

        type ISeq<'T> =
            inherit IEnumerable<'T>
            abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U>
            abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer
Clone this wiki locally