Skip to content

Commit a3802e0

Browse files
committed
Removed circular dependencies
1 parent c60ccdc commit a3802e0

File tree

15 files changed

+297
-504
lines changed

15 files changed

+297
-504
lines changed

src/Fable.Transforms/Fable2Babel.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ module Reflection =
283283
| Fable.Array _ | Fable.Tuple _ ->
284284
libCall com ctx None "Util" "isArrayLike" [|com.TransformAsExpr(ctx, expr)|]
285285
| Fable.List _ ->
286-
jsInstanceof (libValue com ctx "List" "LinkedList$1") expr
286+
jsInstanceof (libValue com ctx "List" "FSharpList") expr
287287
| Fable.AnonymousRecordType _ ->
288288
warnAndEvalToFalse "anonymous records"
289289
| Fable.MetaType ->

src/Fable.Transforms/Replacements.fs

Lines changed: 11 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,50 +1661,12 @@ let stringModule (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr opti
16611661
Helper.LibCall(com, "String", Naming.lowerFirst meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
16621662

16631663
let seqModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
1664-
let sort r returnType descending projection args genArg =
1665-
let compareFn =
1666-
let identExpr ident =
1667-
match projection with
1668-
| Some projection ->
1669-
let info = makeCallInfo None [IdentExpr ident] []
1670-
Call(projection, info, genArg, None)
1671-
| None -> IdentExpr ident
1672-
let x = makeUniqueIdent ctx genArg "x"
1673-
let y = makeUniqueIdent ctx genArg "y"
1674-
let comparison =
1675-
let comparison = compare com ctx None (identExpr x) (identExpr y)
1676-
if descending
1677-
then makeUnOp None (Number Int32) comparison UnaryMinus
1678-
else comparison
1679-
Delegate([x; y], comparison, None)
1680-
Helper.LibCall(com, "Seq", "sortWith", returnType, compareFn::args, ?loc=r) |> Some
1681-
16821664
match i.CompiledName, args with
16831665
| "Cast", [arg] -> Some arg // Erase
1684-
| ("Cache" | "ToArray"), [arg] -> toArray r t arg |> Some
1685-
| "OfList", [arg] -> toSeq t arg |> Some
1686-
| "ToList", _ -> Helper.LibCall(com, "List", "ofSeq", t, args, i.SignatureArgTypes, ?loc=r) |> Some
1687-
| ("ChunkBySize" | "Permute" | "SplitInto") as meth, [arg1; arg2] ->
1688-
let arg2 = toArray r (Array Any) arg2
1689-
let result = Helper.LibCall(com, "Array", Naming.lowerFirst meth, Any, [arg1; arg2])
1690-
Helper.LibCall(com, "Seq", "ofArray", t, [result]) |> Some
1691-
// For Using we need to cast the argument to IDisposable
1692-
| "EnumerateUsing", [arg; f] ->
1693-
Helper.LibCall(com, "Seq", "enumerateUsing", t, [arg; f], i.SignatureArgTypes, ?loc=r) |> Some
1694-
| ("Sort" | "SortDescending" as meth), args ->
1695-
(genArg com ctx r 0 i.GenericArgs) |> sort r t (meth = "SortDescending") None args
1696-
| ("SortBy" | "SortByDescending" as meth), projection::args ->
1697-
(genArg com ctx r 1 i.GenericArgs) |> sort r t (meth = "SortByDescending") (Some projection) args
1698-
| ("GroupBy" | "CountBy" as meth), args ->
1699-
let meth = Naming.lowerFirst meth
1700-
let args = injectArg com ctx r "Map" meth i.GenericArgs args
1701-
Helper.LibCall(com, "Map", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
1702-
| ("Distinct" | "DistinctBy" as meth), args ->
1666+
| ("Distinct" | "DistinctBy" | "Except" | "GroupBy" | "CountBy" as meth), args ->
17031667
let meth = Naming.lowerFirst meth
1704-
let args = injectArg com ctx r "Set" meth i.GenericArgs args
1705-
Helper.LibCall(com, "Set", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
1706-
| "TryExactlyOne", args ->
1707-
tryCoreOp com r t "Seq" "exactlyOne" args |> Some
1668+
let args = injectArg com ctx r "Seq2" meth i.GenericArgs args
1669+
Helper.LibCall(com, "Seq2", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
17081670
| meth, _ ->
17091671
let meth = Naming.lowerFirst meth
17101672
let args = injectArg com ctx r "Seq" meth i.GenericArgs args
@@ -1860,19 +1822,16 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
18601822
newArray (makeIntConst 0) t |> Some
18611823
| "IsEmpty", [ar] ->
18621824
eq (get r (Number Int32) ar "length") (makeIntConst 0) |> Some
1863-
| "TryExactlyOne", args ->
1864-
tryCoreOp com r t "Array" "exactlyOne" args |> Some
1865-
// | "SortInPlace", args ->
1866-
// let _, thisArg = List.splitLast args
1867-
// let argTypes = List.take (List.length args) i.SignatureArgTypes
1868-
// let compareFn = (genArg com ctx r 0 i.GenericArgs) |> makeComparerFunction com ctx
1869-
// Helper.InstanceCall(thisArg, "sort", t, [compareFn], argTypes, ?loc=r) |> Some
18701825
| "CopyTo", args ->
18711826
copyToArray com r t i args
18721827
| Patterns.DicContains nativeArrayFunctions meth, _ ->
18731828
let args, thisArg = List.splitLast args
18741829
let argTypes = List.take (List.length args) i.SignatureArgTypes
18751830
Helper.InstanceCall(thisArg, meth, t, args, argTypes, ?loc=r) |> Some
1831+
| ("Distinct" | "DistinctBy" | "Except" | "GroupBy" | "CountBy" as meth), args ->
1832+
let meth = Naming.lowerFirst meth
1833+
let args = injectArg com ctx r "Seq2" meth i.GenericArgs args
1834+
Helper.LibCall(com, "Seq2", "Array_" + meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
18761835
| meth, _ ->
18771836
let meth = Naming.lowerFirst meth
18781837
let args = injectArg com ctx r "Array" meth i.GenericArgs args
@@ -1905,8 +1864,10 @@ let listModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Exp
19051864
// Use a cast to give it better chances of optimization (e.g. converting list
19061865
// literals to arrays) after the beta reduction pass
19071866
| "ToSeq", [x] -> toSeq t x |> Some
1908-
| "TryExactlyOne", args ->
1909-
tryCoreOp com r t "List" "exactlyOne" args |> Some
1867+
| ("Distinct" | "DistinctBy" | "Except" | "GroupBy" | "CountBy" as meth), args ->
1868+
let meth = Naming.lowerFirst meth
1869+
let args = injectArg com ctx r "Seq2" meth i.GenericArgs args
1870+
Helper.LibCall(com, "Seq2", "List_" + meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
19101871
| meth, _ ->
19111872
let meth = Naming.lowerFirst meth
19121873
let args = injectArg com ctx r "List" meth i.GenericArgs args

src/Fable.Transforms/ReplacementsInject.fs

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,6 @@ module Fable.Transforms.ReplacementsInject
33

44
let fableReplacementsModules =
55
Map [
6-
"Seq", Map [
7-
"maxBy", (Types.comparer, 1)
8-
"max", (Types.comparer, 0)
9-
"minBy", (Types.comparer, 1)
10-
"min", (Types.comparer, 0)
11-
"sumBy", (Types.adder, 1)
12-
"sum", (Types.adder, 0)
13-
"averageBy", (Types.averager, 1)
14-
"average", (Types.averager, 0)
15-
]
166
"Array", Map [
177
"append", (Types.arrayCons, 0)
188
"mapIndexed", (Types.arrayCons, 1)
@@ -25,12 +15,7 @@ let fableReplacementsModules =
2515
"mapFoldBack", (Types.arrayCons, 2)
2616
"concat", (Types.arrayCons, 0)
2717
"collect", (Types.arrayCons, 1)
28-
"countBy", (Types.equalityComparer, 1)
29-
"distinctBy", (Types.equalityComparer, 1)
30-
"distinct", (Types.equalityComparer, 0)
3118
"contains", (Types.equalityComparer, 0)
32-
"except", (Types.equalityComparer, 0)
33-
"groupBy", (Types.equalityComparer, 1)
3419
"singleton", (Types.arrayCons, 0)
3520
"initialize", (Types.arrayCons, 0)
3621
"replicate", (Types.arrayCons, 0)
@@ -60,7 +45,6 @@ let fableReplacementsModules =
6045
]
6146
"List", Map [
6247
"contains", (Types.equalityComparer, 0)
63-
"except", (Types.equalityComparer, 0)
6448
"sort", (Types.comparer, 0)
6549
"sortBy", (Types.comparer, 1)
6650
"sortDescending", (Types.comparer, 0)
@@ -73,14 +57,9 @@ let fableReplacementsModules =
7357
"min", (Types.comparer, 0)
7458
"average", ("Fable.Core.IGenericAverager`1", 0)
7559
"averageBy", ("Fable.Core.IGenericAverager`1", 1)
76-
"distinctBy", (Types.equalityComparer, 1)
77-
"distinct", (Types.equalityComparer, 0)
78-
"groupBy", (Types.equalityComparer, 1)
79-
"countBy", (Types.equalityComparer, 1)
8060
]
8161
"Seq", Map [
8262
"contains", (Types.equalityComparer, 0)
83-
"except", (Types.equalityComparer, 0)
8463
"sort", (Types.comparer, 0)
8564
"sortBy", (Types.comparer, 1)
8665
"sortDescending", (Types.comparer, 0)
@@ -94,6 +73,13 @@ let fableReplacementsModules =
9473
"average", ("Fable.Core.IGenericAverager`1", 0)
9574
"averageBy", ("Fable.Core.IGenericAverager`1", 1)
9675
]
76+
"Seq2", Map [
77+
"distinct", (Types.equalityComparer, 0)
78+
"distinctBy", (Types.equalityComparer, 1)
79+
"except", (Types.equalityComparer, 0)
80+
"countBy", (Types.equalityComparer, 1)
81+
"groupBy", (Types.equalityComparer, 1)
82+
]
9783
"Set", Map [
9884
"FSharpSet__Map", (Types.comparer, 1)
9985
"singleton", (Types.comparer, 0)
@@ -103,19 +89,11 @@ let fableReplacementsModules =
10389
"ofList", (Types.comparer, 0)
10490
"ofArray", (Types.comparer, 0)
10591
"ofSeq", (Types.comparer, 0)
106-
"createMutable", (Types.equalityComparer, 0)
107-
"distinct", (Types.equalityComparer, 0)
108-
"distinctBy", (Types.equalityComparer, 1)
10992
"intersectWith", (Types.comparer, 0)
11093
"isSubsetOf", (Types.comparer, 0)
11194
"isSupersetOf", (Types.comparer, 0)
11295
"isProperSubsetOf", (Types.comparer, 0)
11396
"isProperSupersetOf", (Types.comparer, 0)
11497
]
115-
"Map", Map [
116-
"createMutable", (Types.equalityComparer, 0)
117-
"groupBy", (Types.equalityComparer, 1)
118-
"countBy", (Types.equalityComparer, 1)
119-
]
12098
]
12199

src/fable-library/Array.fs

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -254,28 +254,6 @@ let collect (mapping: 'T -> 'U[]) (array: 'T[]) ([<Inject>] cons: Cons<'U>): 'U[
254254
concat mapped cons
255255
// collectImpl mapping array // flatMap not widely available yet
256256

257-
let countBy (projection: 'T -> 'Key) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'Key>): ('Key * int)[] =
258-
let dict = Dictionary<'Key, int>(eq)
259-
let keys: 'Key[] = [||]
260-
for value in array do
261-
let key = projection value
262-
match dict.TryGetValue(key) with
263-
| true, prev ->
264-
dict.[key] <- prev + 1
265-
| false, _ ->
266-
dict.[key] <- 1
267-
pushImpl keys key |> ignore
268-
let result =
269-
map (fun key -> key, dict.[key]) keys Unchecked.defaultof<_>
270-
result
271-
272-
let distinctBy (projection: 'T -> 'Key) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'Key>) =
273-
let hashSet = HashSet<'Key>(eq)
274-
array |> filter (projection >> hashSet.Add)
275-
276-
let distinct (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'T>) =
277-
distinctBy id array eq
278-
279257
let where predicate (array: _[]) = filterImpl predicate array
280258

281259
let contains<'T> (value: 'T) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'T>) =
@@ -287,28 +265,6 @@ let contains<'T> (value: 'T) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'T>
287265
else loop (i + 1)
288266
loop 0
289267

290-
let except (itemsToExclude: seq<'T>) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'T>): 'T[] =
291-
if array.Length = 0 then
292-
array
293-
else
294-
let cached = HashSet(itemsToExclude, eq)
295-
array |> filterImpl cached.Add
296-
297-
let groupBy (projection: 'T -> 'Key) (array: 'T[]) ([<Inject>] eq: IEqualityComparer<'Key>): ('Key * 'T[])[] =
298-
let dict = Dictionary<'Key, ResizeArray<'T>>(eq)
299-
let keys: 'Key[] = [||]
300-
for v in array do
301-
let key = projection v
302-
match dict.TryGetValue(key) with
303-
| true, prev ->
304-
prev.Add(v)
305-
| false, _ ->
306-
dict.Add(key, ResizeArray [|v|])
307-
pushImpl keys key |> ignore
308-
let result =
309-
map (fun key -> key, arrayFrom dict.[key]) keys Unchecked.defaultof<_>
310-
result
311-
312268
let empty cons = allocateArrayFromCons cons 0
313269

314270
let singleton value ([<Inject>] cons: Cons<'T>) =
@@ -414,7 +370,8 @@ let addInPlace (x: 'T) (array: 'T[]) =
414370

415371
let addRangeInPlace (range: seq<'T>) (array: 'T[]) =
416372
// if isTypedArrayImpl array then invalidArg "array" "Typed arrays not supported"
417-
Seq.iter (fun x -> pushImpl array x |> ignore) range
373+
for x in range do
374+
addInPlace x array
418375

419376
let removeInPlace (item: 'T) (array: 'T[]) =
420377
// if isTypedArrayImpl array then invalidArg "array" "Typed arrays not supported"
@@ -778,6 +735,11 @@ let exactlyOne (array: 'T[]) =
778735
elif array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
779736
else invalidArg "array" "Input array too long"
780737

738+
let tryExactlyOne (array: 'T[]) =
739+
if array.Length = 1
740+
then Some (array.[0])
741+
else None
742+
781743
let head (array: 'T[]) =
782744
if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
783745
else array.[0]

src/fable-library/BigInt.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ let private flipTwosComplement currByte lowBitFound =
8888
| 0uy, false -> 0uy, false // Haven't found first bit yet and no chance to do so with zero byte
8989
| _, false ->
9090
// Found first byte containing a 1, flip higher bits and all future bytes
91-
let firstBitIndex = [0..7] |> List.find (fun i -> currByte &&& (1uy <<< i) > 0uy)
91+
let firstBitIndex = [|0;1;2;3;4;5;6;7|] |> Array.find (fun i -> currByte &&& (1uy <<< i) > 0uy)
9292
(currByte ^^^ (0b11111110uy <<< firstBitIndex)) &&& 255uy, true
9393

9494
// Spec:
@@ -148,7 +148,7 @@ let fromByteArray (bytes:byte array) =
148148
|> fun value -> if isPositive then value else bigint(-1) * value
149149
else
150150
let bytesToProcess = min bytesRemaining 4
151-
for i in 0 .. bytesToProcess - 1 do buffer.[i] <- bytes.[currIndex + i] // fill buffer with up to 4 bytes
151+
for i = 0 to bytesToProcess - 1 do buffer.[i] <- bytes.[currIndex + i] // fill buffer with up to 4 bytes
152152
if isPositive then
153153
Array.fill buffer bytesToProcess (4 - bytesToProcess) 0uy // clear any unfilled bytes in buffer
154154
let value =

src/fable-library/Fable.Library.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<Compile Include="Array.fs" />
2626
<Compile Include="List.fs" />
2727
<Compile Include="Seq.fs" />
28+
<Compile Include="Seq2.fs" />
2829
<Compile Include="Range.fs" />
2930
<Compile Include="Set.fs" />
3031
<Compile Include="Map.fs" />

src/fable-library/List.fs

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module SR =
1313
let notEnoughElements = "The input sequence has an insufficient number of elements."
1414

1515
[<CustomEquality; CustomComparison>]
16-
// [<CompiledName("FSharpList`1")>]
16+
[<CompiledName("FSharpList")>]
1717
type LinkedList<'T when 'T: comparison> =
1818
{ head: 'T; mutable tail: LinkedList<'T> option }
1919

@@ -471,12 +471,6 @@ let contains (value: 'T) (xs: 'T list) ([<Inject>] eq: System.Collections.Generi
471471
tryFindIndex (fun v -> eq.Equals (value, v)) xs
472472
|> Option.isSome
473473

474-
let except (itemsToExclude: seq<'T>) (xs: 'T list) ([<Inject>] eq: System.Collections.Generic.IEqualityComparer<'T>) =
475-
if xs.IsEmpty then xs
476-
else
477-
let cached = System.Collections.Generic.HashSet(itemsToExclude, eq)
478-
xs |> filter cached.Add
479-
480474
let initialize n (f: int -> 'T) =
481475
let root = List.Empty
482476
let mutable node = root
@@ -525,7 +519,7 @@ let zip3 xs ys zs =
525519

526520
let sortWith (comparer: 'T -> 'T -> int) (xs: 'T list) =
527521
let arr = toArray xs
528-
Array.sortInPlaceWith comparer arr // TODO: use stable sort
522+
Array.sortInPlaceWith comparer arr // Note: In JS this sort is stable
529523
arr |> ofArray
530524

531525
let sort (xs: 'T list) ([<Inject>] comparer: System.Collections.Generic.IComparer<'T>) =
@@ -646,49 +640,17 @@ let splitAt index (xs: 'T list) =
646640
if index > xs.Length then invalidArg "index" SR.notEnoughElements
647641
take index xs, skip index xs
648642

649-
let distinctBy (projection: 'T -> 'Key) (xs: 'T list) ([<Inject>] eq: System.Collections.Generic.IEqualityComparer<'Key>) =
650-
let hashSet = System.Collections.Generic.HashSet<'Key>(eq)
651-
xs |> filter (projection >> hashSet.Add)
652-
653-
let distinct (xs: 'T list) ([<Inject>] eq: System.Collections.Generic.IEqualityComparer<'T>) =
654-
distinctBy id xs eq
655-
656643
let exactlyOne (xs: 'T list) =
657644
if xs.IsEmpty
658645
then invalidArg "list" SR.inputSequenceEmpty
659646
else
660647
if xs.Tail.IsEmpty then xs.Head
661648
else invalidArg "list" SR.inputSequenceTooLong
662649

663-
let groupBy (projection: 'T -> 'Key) (xs: 'T list) ([<Inject>] eq: System.Collections.Generic.IEqualityComparer<'Key>): ('Key * 'T list) list =
664-
let dict = System.Collections.Generic.Dictionary<'Key, 'T list>(eq)
665-
let mutable keys = List.Empty
666-
xs |> iterate (fun v ->
667-
let key = projection v
668-
match dict.TryGetValue(key) with
669-
| true, prev ->
670-
dict.[key] <- List.Cons(v, prev)
671-
| false, _ ->
672-
dict.Add(key, List.Cons(v, List.Empty))
673-
keys <- List.Cons(key, keys) )
674-
let mutable result = List.Empty
675-
keys |> iterate (fun key -> result <- List.Cons((key, reverse dict.[key]), result))
676-
result
677-
678-
let countBy (projection: 'T -> 'Key) (xs: 'T list) ([<Inject>] eq: System.Collections.Generic.IEqualityComparer<'Key>) =
679-
let dict = System.Collections.Generic.Dictionary<'Key, int>(eq)
680-
let mutable keys = List.Empty
681-
xs |> iterate (fun v ->
682-
let key = projection v
683-
match dict.TryGetValue(key) with
684-
| true, prev ->
685-
dict.[key] <- prev + 1
686-
| false, _ ->
687-
dict.[key] <- 1
688-
keys <- List.Cons(key, keys) )
689-
let mutable result = List.Empty
690-
keys |> iterate (fun key -> result <- List.Cons((key, dict.[key]), result))
691-
result
650+
let tryExactlyOne (xs: 'T list) =
651+
if not (xs.IsEmpty) && xs.Tail.IsEmpty
652+
then Some (xs.Head)
653+
else None
692654

693655
let where predicate (xs: 'T list) =
694656
filter predicate xs
@@ -712,7 +674,8 @@ let splitInto (chunks: int) (xs: 'T list): 'T list list =
712674

713675
let transpose (lists: seq<'T list>): 'T list list =
714676
lists
715-
|> Seq.map toArray
677+
|> Array.ofSeq
678+
|> Array.map toArray
716679
|> Array.transpose
717680
|> Array.map ofArray
718681
|> ofArray

0 commit comments

Comments
 (0)