From 5b806eb651cf49e58e824926212c55a94963b485 Mon Sep 17 00:00:00 2001 From: Alfonso Garcia-Caro Date: Thu, 24 Nov 2022 00:21:48 +0900 Subject: [PATCH] Support ValueOption module --- src/Fable.Transforms/Dart/Replacements.fs | 18 ++++++++++-------- src/Fable.Transforms/Replacements.fs | 7 ++++--- tests/Dart/src/OptionTests.fs | 16 ++++++++++++++++ tests/Js/Main/OptionTests.fs | 16 ++++++++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/Fable.Transforms/Dart/Replacements.fs b/src/Fable.Transforms/Dart/Replacements.fs index aae86e3891..3f40a9d96b 100644 --- a/src/Fable.Transforms/Dart/Replacements.fs +++ b/src/Fable.Transforms/Dart/Replacements.fs @@ -1484,17 +1484,18 @@ let nullables (com: ICompiler) (_: Context) r (t: Type) (i: CallInfo) (thisArg: | "get_HasValue", Some c -> makeEqOp r c (makeNull()) BinaryUnequal |> Some | _ -> None -// See fable-library/Option.ts for more info on how options behave in Fable runtime -let options (com: ICompiler) (_: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = +let options isStruct (com: ICompiler) (_: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg with + | "get_None", _ -> NewOption(None, t.Generics.Head, isStruct) |> makeValue r |> Some + | "Some", _ -> NewOption(List.tryHead args, t.Generics.Head, isStruct) |> makeValue r |> Some | "get_Value", Some c -> getOptionValue r t c |> Some | "get_IsSome", Some c -> Test(c, OptionTest true, r) |> Some | "get_IsNone", Some c -> Test(c, OptionTest false, r) |> Some | _ -> None -let optionModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) = +let optionModule isStruct (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) = match i.CompiledName, args with - | "None", _ -> NewOption(None, t, false) |> makeValue r |> Some + | "None", _ -> NewOption(None, t, isStruct) |> makeValue r |> Some | "GetValue", [c] -> getOptionValue r t c |> Some | "IsSome", [c] -> Test(c, OptionTest true, r) |> Some | "IsNone", [c] -> Test(c, OptionTest false, r) |> Some @@ -2708,10 +2709,11 @@ let private replacedModules = Types.queue, bclType Types.iset, hashSets Types.idisposable, disposables - Types.option, options - Types.valueOption, options + Types.option, options false + Types.valueOption, options true "System.Nullable`1", nullables - "Microsoft.FSharp.Core.OptionModule", optionModule + "Microsoft.FSharp.Core.OptionModule", optionModule false + "Microsoft.FSharp.Core.ValueOption", optionModule true "Microsoft.FSharp.Core.ResultModule", results Types.bigint, bigints "Microsoft.FSharp.Core.NumericLiterals.NumericLiteralI", bigints @@ -2892,7 +2894,7 @@ let tryType = function Some(getNumberFullName false kind info, f, []) | String -> Some(Types.string, strings, []) | Tuple(genArgs, _) as t -> Some(getTypeFullName false t, tuples, genArgs) - | Option(genArg, _) -> Some(Types.option, options, [genArg]) + | Option(genArg, isStruct) -> Some(Types.option, options isStruct, [genArg]) | Array(genArg,_) -> Some(Types.array, arrays, [genArg]) | List genArg -> Some(Types.list, lists, [genArg]) | Builtin kind -> diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs index fe638b92d4..095656acac 100644 --- a/src/Fable.Transforms/Replacements.fs +++ b/src/Fable.Transforms/Replacements.fs @@ -1687,11 +1687,11 @@ let options isStruct (com: ICompiler) (_: Context) r (t: Type) (i: CallInfo) (th | "get_IsNone", Some c -> Test(c, OptionTest false, r) |> Some | _ -> None -let optionModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) = +let optionModule isStruct (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) = let toArray r t arg = Helper.LibCall(com, "Option", "toArray", Array(t, MutableArray), [arg], ?loc=r) match i.CompiledName, args with - | "None", _ -> NewOption(None, t, false) |> makeValue r |> Some + | "None", _ -> NewOption(None, t, isStruct) |> makeValue r |> Some | "GetValue", [c] -> Helper.LibCall(com, "Option", "value", t, args, ?loc=r) |> Some | ("OfObj" | "OfNullable"), _ -> @@ -2900,7 +2900,8 @@ let private replacedModules = Types.option, options false Types.valueOption, options true "System.Nullable`1", nullables - "Microsoft.FSharp.Core.OptionModule", optionModule + "Microsoft.FSharp.Core.OptionModule", optionModule false + "Microsoft.FSharp.Core.ValueOption", optionModule true "Microsoft.FSharp.Core.ResultModule", results Types.bigint, bigints "Microsoft.FSharp.Core.NumericLiterals.NumericLiteralI", bigints diff --git a/tests/Dart/src/OptionTests.fs b/tests/Dart/src/OptionTests.fs index 2217ba9271..9d61d8000f 100644 --- a/tests/Dart/src/OptionTests.fs +++ b/tests/Dart/src/OptionTests.fs @@ -74,6 +74,14 @@ let tests() = Option.isNone o2 |> equal false Option.isSome o2 |> equal true + testCase "ValueOption.isSome/isNone works" <| fun () -> + let o1: int voption = ValueNone + let o2 = ValueSome 5 + ValueOption.isNone o1 |> equal true + ValueOption.isSome o1 |> equal false + ValueOption.isNone o2 |> equal false + ValueOption.isSome o2 |> equal true + testCase "Option.IsSome/IsNone works" <| fun () -> let o1: int option = None let o2 = Some 5 @@ -82,6 +90,14 @@ let tests() = o2.IsNone |> equal false o2.IsSome |> equal true + testCase "ValueOption.IsSome/IsNone works" <| fun () -> + let o1: int voption = ValueNone + let o2 = Some 5 + o1.IsNone |> equal true + o1.IsSome |> equal false + o2.IsNone |> equal false + o2.IsSome |> equal true + testCase "Option.iter works" <| fun () -> // See #198 let mutable res = false let getOnlyOnce = diff --git a/tests/Js/Main/OptionTests.fs b/tests/Js/Main/OptionTests.fs index f3e1aaa56f..9ad378602d 100644 --- a/tests/Js/Main/OptionTests.fs +++ b/tests/Js/Main/OptionTests.fs @@ -80,6 +80,14 @@ let tests = Option.isNone o2 |> equal false Option.isSome o2 |> equal true + testCase "ValueOption.isSome/isNone works" <| fun () -> + let o1: int voption = ValueNone + let o2 = ValueSome 5 + ValueOption.isNone o1 |> equal true + ValueOption.isSome o1 |> equal false + ValueOption.isNone o2 |> equal false + ValueOption.isSome o2 |> equal true + testCase "Option.IsSome/IsNone works" <| fun () -> let o1 = None let o2 = Some 5 @@ -88,6 +96,14 @@ let tests = o2.IsNone |> equal false o2.IsSome |> equal true + testCase "ValueOption.IsSome/IsNone works" <| fun () -> + let o1: int voption = ValueNone + let o2 = Some 5 + o1.IsNone |> equal true + o1.IsSome |> equal false + o2.IsNone |> equal false + o2.IsSome |> equal true + testCase "Option.iter works" <| fun () -> // See #198 let mutable res = false let getOnlyOnce =