Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding ListEnumerable, Choose, and some cleanup #1

Merged
merged 2 commits into from
Oct 5, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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