Skip to content

Commit 300c888

Browse files
committed
Array-based List type
1 parent 199e671 commit 300c888

File tree

4 files changed

+426
-390
lines changed

4 files changed

+426
-390
lines changed

src/Fable.Transforms/Fable2Babel.fs

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ module Annotation =
438438
makeNativeTypeAnnotation com ctx [genArg] "Array"
439439

440440
let makeListTypeAnnotation com ctx genArg =
441-
makeImportTypeAnnotation com ctx [genArg] "Types" "List"
441+
makeImportTypeAnnotation com ctx [genArg] "List" "List"
442442

443443
let makeUnionTypeAnnotation com ctx genArgs =
444444
List.map (typeAnnotation com ctx) genArgs
@@ -659,12 +659,6 @@ module Util =
659659
| [] -> expr
660660
| m::ms -> get None expr m |> getParts ms
661661

662-
let makeList com ctx r headAndTail =
663-
match headAndTail with
664-
| None -> [||]
665-
| Some(TransformExpr com ctx head, TransformExpr com ctx tail) -> [|head; tail|]
666-
|> libConsCall com ctx r "Types" "List"
667-
668662
let makeArray (com: IBabelCompiler) ctx exprs =
669663
List.mapToArray (fun e -> com.TransformAsExpr(ctx, e)) exprs
670664
|> ArrayExpression :> Expression
@@ -911,27 +905,21 @@ module Util =
911905
| Fable.NewArray (values, typ) -> makeTypedArray com ctx typ values
912906
| Fable.NewArrayFrom (size, typ) -> makeTypedAllocatedFrom com ctx typ size
913907
| Fable.NewTuple vals -> makeArray com ctx vals
914-
| Fable.NewList (headAndTail, _) when List.contains "FABLE_LIBRARY" com.Options.Define ->
915-
makeList com ctx r headAndTail
908+
// | Fable.NewList (headAndTail, _) when List.contains "FABLE_LIBRARY" com.Options.Define ->
909+
// makeList com ctx r headAndTail
916910
// Optimization for bundle size: compile list literals as List.ofArray
911+
| Replacements.ListLiteral(exprs, t) ->
912+
[|List.rev exprs |> makeArray com ctx|]
913+
|> libCall com ctx r "List" "newList"
914+
// match exprs with
915+
// | [] -> libCall com ctx r "List" "empty" [||]
916+
// | [TransformExpr com ctx expr] -> libCall com ctx r "List" "singleton" [|expr|]
917+
// | exprs -> [|makeArray com ctx exprs|] |> libCall com ctx r "List" "ofArray"
917918
| Fable.NewList (headAndTail, _) ->
918-
let rec getItems acc = function
919-
| None -> List.rev acc, None
920-
| Some(head, Fable.Value(Fable.NewList(tail, _),_)) -> getItems (head::acc) tail
921-
| Some(head, tail) -> List.rev (head::acc), Some tail
922-
match getItems [] headAndTail with
923-
| [], None ->
924-
libCall com ctx r "List" "empty" [||]
925-
| [TransformExpr com ctx expr], None ->
926-
libCall com ctx r "List" "singleton" [|expr|]
927-
| exprs, None ->
928-
[|makeArray com ctx exprs|]
929-
|> libCall com ctx r "List" "ofArray"
930-
| [TransformExpr com ctx head], Some(TransformExpr com ctx tail) ->
919+
match headAndTail with
920+
| None -> libCall com ctx r "List" "empty" [||]
921+
| Some(TransformExpr com ctx head, TransformExpr com ctx tail) ->
931922
libCall com ctx r "List" "cons" [|head; tail|]
932-
| exprs, Some(TransformExpr com ctx tail) ->
933-
[|makeArray com ctx exprs; tail|]
934-
|> libCall com ctx r "List" "ofArrayWithTail"
935923
| Fable.NewOption (value, t) ->
936924
match value with
937925
| Some (TransformExpr com ctx e) ->
@@ -1196,10 +1184,12 @@ module Util =
11961184
| Fable.FieldKey field -> get range expr field.Name
11971185

11981186
| Fable.ListHead ->
1199-
get range (com.TransformAsExpr(ctx, fableExpr)) "head"
1187+
// get range (com.TransformAsExpr(ctx, fableExpr)) "head"
1188+
libCall com ctx range "List" "head" [|com.TransformAsExpr(ctx, fableExpr)|]
12001189

12011190
| Fable.ListTail ->
1202-
get range (com.TransformAsExpr(ctx, fableExpr)) "tail"
1191+
// get range (com.TransformAsExpr(ctx, fableExpr)) "tail"
1192+
libCall com ctx range "List" "tail" [|com.TransformAsExpr(ctx, fableExpr)|]
12031193

12041194
| Fable.TupleIndex index ->
12051195
match fableExpr with
@@ -1267,9 +1257,9 @@ module Util =
12671257
let op = if nonEmpty then BinaryUnequal else BinaryEqual
12681258
upcast BinaryExpression(op, com.TransformAsExpr(ctx, expr), NullLiteral(), ?loc=range)
12691259
| Fable.ListTest nonEmpty ->
1270-
let expr = com.TransformAsExpr(ctx, expr)
1271-
let op = if nonEmpty then BinaryUnequal else BinaryEqual
1272-
upcast BinaryExpression(op, get None expr "tail", NullLiteral(), ?loc=range)
1260+
// let expr = get range (com.TransformAsExpr(ctx, expr)) "IsEmpty"
1261+
let expr = libCall com ctx range "List" "isEmpty" [|com.TransformAsExpr(ctx, expr)|]
1262+
if nonEmpty then upcast UnaryExpression(UnaryNot, expr, ?loc=range) else expr
12731263
| Fable.UnionCaseTest tag ->
12741264
let expected = ofInt tag
12751265
let actual = com.TransformAsExpr(ctx, expr) |> getUnionExprTag None

src/Fable.Transforms/Replacements.fs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,29 +1859,26 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
18591859
Helper.LibCall(com, "Array", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
18601860

18611861
let lists (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
1862+
let meth = Naming.removeGetSetPrefix i.CompiledName |> Naming.lowerFirst
18621863
match i.CompiledName, thisArg, args with
1863-
// Use methods for Head and Tail (instead of Get(ListHead) for example) to check for empty lists
1864-
| ReplaceName
1865-
[ "get_Head", "head"
1866-
"get_Tail", "tail"
1867-
"get_Item", "item"
1868-
"get_Length", "length"
1869-
"GetSlice", "slice" ] methName, Some x, _ ->
1870-
let args = match args with [ExprType Unit] -> [x] | args -> args @ [x]
1871-
Helper.LibCall(com, "List", methName, t, args, i.SignatureArgTypes, ?loc=r) |> Some
1872-
| "get_IsEmpty", Some x, _ -> Test(x, ListTest false, r) |> Some
1873-
| "get_Empty", None, _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1874-
| "Cons", None, [h;t] -> NewList(Some(h,t), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1864+
| ("get_Head" | "get_Tail" | "get_IsEmpty" | "get_Length"), Some x, _ ->
1865+
Helper.LibCall(com, "List", meth, t, [x], i.SignatureArgTypes, ?loc=r) |> Some
1866+
// get r t x meth |> Some
1867+
| ("get_Item" | "GetSlice"), Some x, _ ->
1868+
Helper.LibCall(com, "List", meth, t, args @ [x], i.SignatureArgTypes, ?loc=r) |> Some
1869+
| ("get_Empty" | "Cons"), None, _ ->
1870+
Helper.LibCall(com, "List", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
18751871
| ("GetHashCode" | "Equals" | "CompareTo"), Some callee, _ ->
18761872
Helper.InstanceCall(callee, i.CompiledName, t, args, i.SignatureArgTypes, ?loc=r) |> Some
18771873
| _ -> None
18781874

18791875
let listModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) =
18801876
match i.CompiledName, args with
1881-
| "IsEmpty", [x] -> Test(x, ListTest false, r) |> Some
1882-
| "Empty", _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1883-
| "Singleton", [x] ->
1884-
NewList(Some(x, Value(NewList(None, t), None)), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1877+
// | ("Head" | "Tail" | "IsEmpty") as meth, [x] -> get r t x (Naming.lowerFirst meth) |> Some
1878+
// | "IsEmpty", [x] -> Test(x, ListTest false, r) |> Some
1879+
// | "Empty", _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1880+
// | "Singleton", [x] ->
1881+
// NewList(Some(x, Value(NewList(None, t), None)), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
18851882
// Use a cast to give it better chances of optimization (e.g. converting list
18861883
// literals to arrays) after the beta reduction pass
18871884
| "ToSeq", [x] -> toSeq t x |> Some

0 commit comments

Comments
 (0)