Skip to content

Commit

Permalink
Merge pull request #1 from liboz/manofstick
Browse files Browse the repository at this point in the history
Adding ListEnumerable, Choose, and some cleanup
  • Loading branch information
manofstick authored Oct 5, 2016
2 parents 42c570c + 9108197 commit 8c5ad63
Showing 1 changed file with 104 additions and 45 deletions.
149 changes: 104 additions & 45 deletions src/fsharp/FSharp.Core/seq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -837,21 +837,21 @@ namespace Microsoft.FSharp.Collections

abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>

abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U>
abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U>
abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U>
abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U>

default __.OnComplete () = ()

default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)

default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)

and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
Expand All @@ -874,16 +874,16 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponent<'T,'U>()

override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
second.ComposeMap first
second.ComposeWithMap first

override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
upcast Map (first.Map >> second.Map)

override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
upcast FilterMap (first.Filter, second.Map)
override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
upcast FilterThenMap (first.Filter, second.Map)

override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
upcast FilterMap (first.Filter, first.Map >> second.Map)
override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> =
upcast FilterThenMap (first.Filter, first.Map >> second.Map)

override __.ProcessNext (input:'T, halted:byref<bool>, output:byref<'U>) : bool =
output <- map input
Expand All @@ -906,17 +906,17 @@ namespace Microsoft.FSharp.Collections
and Filter<'T> (filter:'T->bool) =
inherit SeqComponent<'T,'T>()

override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
next.ComposeFilter this
override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
second.ComposeWithFilter first

override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
upcast MapFilter (first.Map, second.Filter)
override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
upcast MapThenFilter (first.Map, second.Filter)

override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)

override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> =
upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)

override __.ProcessNext (input:'T, halted:byref<bool>, output:byref<'T>) : bool =
if filter input then
Expand All @@ -927,20 +927,20 @@ namespace Microsoft.FSharp.Collections

member __.Filter :'T->bool = filter

and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
inherit SeqComponent<'T,'U>()

override __.ProcessNext (input:'T, halted:byref<bool>, output:byref<'U>) :bool =
output <- map input
Helpers.avoidTailCall (filter output)

override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
second.ComposeMapFilter first
second.ComposeWithMapThenFilter first

member __.Map : 'T->'U = map
member __.Filter : 'U->bool = filter

and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) =
and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) =
inherit SeqComponent<'T,'U>()

override __.ProcessNext (input:'T, halted:byref<bool>, output:byref<'U>) : bool =
Expand All @@ -950,7 +950,7 @@ namespace Microsoft.FSharp.Collections
else
false

override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first

member __.Filter : 'T->bool = filter
member __.Map : 'T->'U = map
Expand All @@ -977,10 +977,10 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0

override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
second.ComposeSkip first
second.ComposeWithSkip first

override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
if System.Int32.MaxValue - second.SkipCount > first.SkipCount then
override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then
upcast Skip (first.SkipCount + second.SkipCount)
else
upcast Composed (first, second)
Expand All @@ -1006,9 +1006,9 @@ namespace Microsoft.FSharp.Collections

let mutable count = 0

override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
if System.Int32.MaxValue - second.TakeCount > first.SkipCount then
upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount)
override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then
upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount)
else
upcast Composed (first, second)

Expand All @@ -1030,7 +1030,7 @@ namespace Microsoft.FSharp.Collections

member __.TakeCount = takeCount

and SkipTake<'T> (startIdx:int, endIdx:int) =
and SkipThenTake<'T> (startIdx:int, endIdx:int) =
inherit SeqComponent<'T,'T>()

let mutable count = 0
Expand All @@ -1057,13 +1057,22 @@ namespace Microsoft.FSharp.Collections
let x = endIdx - count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]

and Choose<'T, 'U> (choose:'T->'U option) =
inherit SeqComponent<'T,'U>()

override __.ProcessNext (input:'T, halted:byref<bool>, output:byref<'U>) : bool =
match choose input with
| Some value -> output <- value
true
| None -> false

type SeqProcessNextStates =
| NotStarted = 1
| Finished = 2
| InProcess = 3

type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
Expand All @@ -1082,7 +1091,7 @@ namespace Microsoft.FSharp.Collections
false

interface IDisposable with
member x.Dispose():unit =
member __.Dispose():unit =
match source with
| null -> ()
| _ -> source.Dispose (); source <- Unchecked.defaultof<_>
Expand All @@ -1095,13 +1104,13 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()

interface IEnumerator<'U> with
member x.Current =
member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> current

type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
Expand All @@ -1121,7 +1130,7 @@ namespace Microsoft.FSharp.Collections
false

interface IDisposable with
member x.Dispose() : unit = ()
member __.Dispose() : unit = ()

interface IEnumerator with
member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
Expand All @@ -1131,7 +1140,43 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()

interface IEnumerator<'U> with
member x.Current =
member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> current

type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false

let mutable list = alist

let rec moveNext () =
match halted, list with
| false, head::tail ->
list <- tail
if t2u.ProcessNext (head, &halted, &current) then
true
else
moveNext ()
| _ -> state <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false

interface IDisposable with
member __.Dispose() : unit = ()

interface IEnumerator with
member this.Current : obj = box (this:>IEnumerator<'U>).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
member __.Reset () : unit = noReset ()

interface IEnumerator<'U> with
member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
Expand All @@ -1145,7 +1190,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()

let getEnumerator () : IEnumerator<'U> =
Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))

interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
Expand Down Expand Up @@ -1176,7 +1221,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()

let getEnumerator () : IEnumerator<'U> =
Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ()))
Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current ()))

interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
Expand Down Expand Up @@ -1204,6 +1249,20 @@ namespace Microsoft.FSharp.Collections
//
// state

type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) =
inherit ComposableEnumerable<'U>()

let getEnumerator () : IEnumerator<'U> =
Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current ()))

interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())

interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()

override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ())))


#if FX_NO_ICLONEABLE
Expand Down Expand Up @@ -1330,6 +1389,7 @@ namespace Microsoft.FSharp.Collections
match source with
| :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
| :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
| :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
| _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))

let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
Expand Down Expand Up @@ -1371,8 +1431,7 @@ namespace Microsoft.FSharp.Collections

[<CompiledName("Choose")>]
let choose f source =
checkNonNull "source" source
revamp (IEnumerator.choose f) source
source |> seqFactoryForImmutable (SeqComposer.Choose f)

[<CompiledName("Indexed")>]
let indexed source =
Expand Down

0 comments on commit 8c5ad63

Please sign in to comment.