Skip to content

Commit c9a6aa2

Browse files
committed
Array-based List type
1 parent ba509a9 commit c9a6aa2

File tree

5 files changed

+426
-418
lines changed

5 files changed

+426
-418
lines changed

src/Fable.Transforms/Fable2Babel.fs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ module Annotation =
426426
makeNativeTypeAnnotation com ctx [genArg] "Array"
427427

428428
let makeListTypeAnnotation com ctx genArg =
429-
makeImportTypeAnnotation com ctx [genArg] "Types" "List"
429+
makeImportTypeAnnotation com ctx [genArg] "List" "List"
430430

431431
let makeUnionTypeAnnotation com ctx genArgs =
432432
List.map (typeAnnotation com ctx) genArgs
@@ -647,12 +647,6 @@ module Util =
647647
| [] -> expr
648648
| m::ms -> get None expr m |> getParts ms
649649

650-
let makeList com ctx r headAndTail =
651-
match headAndTail with
652-
| None -> [||]
653-
| Some(TransformExpr com ctx head, TransformExpr com ctx tail) -> [|head; tail|]
654-
|> libConsCall com ctx r "Types" "List"
655-
656650
let makeArray (com: IBabelCompiler) ctx exprs =
657651
List.mapToArray (fun e -> com.TransformAsExpr(ctx, e)) exprs
658652
|> ArrayExpression :> Expression
@@ -902,12 +896,17 @@ module Util =
902896
| Fable.NewTuple vals -> makeArray com ctx vals
903897
// Optimization for bundle size: compile list literals as List.ofArray
904898
| Replacements.ListLiteral(exprs, t) ->
905-
match exprs with
906-
| [] -> makeList com ctx r None
907-
| [expr] -> Some(expr, Fable.Value(Fable.NewList (None,t), None)) |> makeList com ctx r
908-
| exprs -> [|makeArray com ctx exprs|] |> libCall com ctx r "List" "ofArray"
899+
[|List.rev exprs |> makeArray com ctx|]
900+
|> libCall com ctx r "List" "newList"
901+
// match exprs with
902+
// | [] -> libCall com ctx r "List" "empty" [||]
903+
// | [TransformExpr com ctx expr] -> libCall com ctx r "List" "singleton" [|expr|]
904+
// | exprs -> [|makeArray com ctx exprs|] |> libCall com ctx r "List" "ofArray"
909905
| Fable.NewList (headAndTail, _) ->
910-
makeList com ctx r headAndTail
906+
match headAndTail with
907+
| None -> libCall com ctx r "List" "empty" [||]
908+
| Some(TransformExpr com ctx head, TransformExpr com ctx tail) ->
909+
libCall com ctx r "List" "cons" [|head; tail|]
911910
| Fable.NewOption (value, t) ->
912911
match value with
913912
| Some (TransformExpr com ctx e) ->
@@ -1162,10 +1161,12 @@ module Util =
11621161
| Fable.FieldKey field -> get range expr field.Name
11631162

11641163
| Fable.ListHead ->
1165-
get range (com.TransformAsExpr(ctx, fableExpr)) "head"
1164+
// get range (com.TransformAsExpr(ctx, fableExpr)) "head"
1165+
libCall com ctx range "List" "head" [|com.TransformAsExpr(ctx, fableExpr)|]
11661166

11671167
| Fable.ListTail ->
1168-
get range (com.TransformAsExpr(ctx, fableExpr)) "tail"
1168+
// get range (com.TransformAsExpr(ctx, fableExpr)) "tail"
1169+
libCall com ctx range "List" "tail" [|com.TransformAsExpr(ctx, fableExpr)|]
11691170

11701171
| Fable.TupleIndex index ->
11711172
match fableExpr with
@@ -1233,9 +1234,9 @@ module Util =
12331234
let op = if nonEmpty then BinaryUnequal else BinaryEqual
12341235
upcast BinaryExpression(op, com.TransformAsExpr(ctx, expr), NullLiteral(), ?loc=range)
12351236
| Fable.ListTest nonEmpty ->
1236-
let expr = com.TransformAsExpr(ctx, expr)
1237-
let op = if nonEmpty then BinaryUnequal else BinaryEqual
1238-
upcast BinaryExpression(op, get None expr "tail", NullLiteral(), ?loc=range)
1237+
// let expr = get range (com.TransformAsExpr(ctx, expr)) "IsEmpty"
1238+
let expr = libCall com ctx range "List" "isEmpty" [|com.TransformAsExpr(ctx, expr)|]
1239+
if nonEmpty then upcast UnaryExpression(UnaryNot, expr, ?loc=range) else expr
12391240
| Fable.UnionCaseTest tag ->
12401241
let expected = ofInt tag
12411242
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
@@ -1783,29 +1783,26 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
17831783
Helper.LibCall(com, "Array", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
17841784

17851785
let lists (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
1786+
let meth = Naming.removeGetSetPrefix i.CompiledName |> Naming.lowerFirst
17861787
match i.CompiledName, thisArg, args with
1787-
// Use methods for Head and Tail (instead of Get(ListHead) for example) to check for empty lists
1788-
| ReplaceName
1789-
[ "get_Head", "head"
1790-
"get_Tail", "tail"
1791-
"get_Item", "item"
1792-
"get_Length", "length"
1793-
"GetSlice", "slice" ] methName, Some x, _ ->
1794-
let args = match args with [ExprType Unit] -> [x] | args -> args @ [x]
1795-
Helper.LibCall(com, "List", methName, t, args, i.SignatureArgTypes, ?loc=r) |> Some
1796-
| "get_IsEmpty", Some x, _ -> Test(x, ListTest false, r) |> Some
1797-
| "get_Empty", None, _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1798-
| "Cons", None, [h;t] -> NewList(Some(h,t), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1788+
| ("get_Head" | "get_Tail" | "get_IsEmpty" | "get_Length"), Some x, _ ->
1789+
Helper.LibCall(com, "List", meth, t, [x], i.SignatureArgTypes, ?loc=r) |> Some
1790+
// get r t x meth |> Some
1791+
| ("get_Item" | "GetSlice"), Some x, _ ->
1792+
Helper.LibCall(com, "List", meth, t, args @ [x], i.SignatureArgTypes, ?loc=r) |> Some
1793+
| ("get_Empty" | "Cons"), None, _ ->
1794+
Helper.LibCall(com, "List", meth, t, args, i.SignatureArgTypes, ?loc=r) |> Some
17991795
| ("GetHashCode" | "Equals" | "CompareTo"), Some callee, _ ->
18001796
Helper.InstanceCall(callee, i.CompiledName, t, args, i.SignatureArgTypes, ?loc=r) |> Some
18011797
| _ -> None
18021798

18031799
let listModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) =
18041800
match i.CompiledName, args with
1805-
| "IsEmpty", [x] -> Test(x, ListTest false, r) |> Some
1806-
| "Empty", _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1807-
| "Singleton", [x] ->
1808-
NewList(Some(x, Value(NewList(None, t), None)), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1801+
// | ("Head" | "Tail" | "IsEmpty") as meth, [x] -> get r t x (Naming.lowerFirst meth) |> Some
1802+
// | "IsEmpty", [x] -> Test(x, ListTest false, r) |> Some
1803+
// | "Empty", _ -> NewList(None, (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
1804+
// | "Singleton", [x] ->
1805+
// NewList(Some(x, Value(NewList(None, t), None)), (genArg com ctx r 0 i.GenericArgs)) |> makeValue r |> Some
18091806
// Use a cast to give it better chances of optimization (e.g. converting list
18101807
// literals to arrays) after the beta reduction pass
18111808
| "ToSeq", [x] -> toSeq t x |> Some

0 commit comments

Comments
 (0)