diff --git a/src/Fable.Core/Fable.Core.Util.fs b/src/Fable.Core/Fable.Core.Util.fs index fcdf323561..efb38081b4 100644 --- a/src/Fable.Core/Fable.Core.Util.fs +++ b/src/Fable.Core/Fable.Core.Util.fs @@ -69,3 +69,27 @@ module Compiler = /// In watch compilations, indicates if the file is being recompiled /// not because of a direct change, but because a dependency has changed let triggeredByDependency: bool = false + + /// Indicates if code is running on .NET (not compiled by Fable) + let isDotnet: bool = true + + /// Indicates if Fable is compiling to JavaScript + let isJavaScript: bool = false + + /// Indicates if Fable is compiling to TypeScript + let isTypeScript: bool = false + + /// Indicates if Fable is compiling to Python + let isPython: bool = false + + /// Indicates if Fable is compiling to Dart + let isDart: bool = false + + /// Indicates if Fable is compiling to Rust + let isRust: bool = false + + /// Indicates if Fable is compiling to PHP + let isPhp: bool = false + + /// Indicates if Fable is compiling to Erlang/BEAM + let isBeam: bool = false diff --git a/src/Fable.Transforms/Beam/Replacements.fs b/src/Fable.Transforms/Beam/Replacements.fs index beca74e4e7..73abed1d76 100644 --- a/src/Fable.Transforms/Beam/Replacements.fs +++ b/src/Fable.Transforms/Beam/Replacements.fs @@ -5478,6 +5478,30 @@ let tryCall match info.CompiledName with | "get_InvariantCulture" -> emitExpr r t [] "undefined" |> Some | _ -> None + | "Fable.Core.Compiler" -> + match info.CompiledName with + | "version" -> makeStrConst Literals.VERSION |> Some + | "majorMinorVersion" -> + try + let m = System.Text.RegularExpressions.Regex.Match(Literals.VERSION, @"^\d+\.\d+") + float m.Value |> makeFloatConst |> Some + with _ -> + "Cannot parse compiler version" + |> addErrorAndReturnNull com ctx.InlinePath r + |> Some + | "debugMode" -> makeBoolConst com.Options.DebugMode |> Some + | "typedArrays" -> makeBoolConst com.Options.TypedArrays |> Some + | "extension" -> makeStrConst com.Options.FileExtension |> Some + | "triggeredByDependency" -> makeBoolConst com.Options.TriggeredByDependency |> Some + | "isDotnet" -> makeBoolConst false |> Some + | "isJavaScript" -> makeBoolConst (com.Options.Language = JavaScript) |> Some + | "isTypeScript" -> makeBoolConst (com.Options.Language = TypeScript) |> Some + | "isPython" -> makeBoolConst (com.Options.Language = Python) |> Some + | "isDart" -> makeBoolConst (com.Options.Language = Dart) |> Some + | "isRust" -> makeBoolConst (com.Options.Language = Rust) |> Some + | "isPhp" -> makeBoolConst (com.Options.Language = Php) |> Some + | "isBeam" -> makeBoolConst (com.Options.Language = Beam) |> Some + | _ -> None | "Fable.Core.BeamInterop" -> match info.CompiledName, args with | Naming.StartsWith "import" suffix, _ -> diff --git a/src/Fable.Transforms/Dart/Replacements.fs b/src/Fable.Transforms/Dart/Replacements.fs index b1e787f770..7ecc077fcb 100644 --- a/src/Fable.Transforms/Dart/Replacements.fs +++ b/src/Fable.Transforms/Dart/Replacements.fs @@ -732,6 +732,14 @@ let fableCoreLib (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp | "typedArrays" -> makeBoolConst com.Options.TypedArrays |> Some | "extension" -> makeStrConst com.Options.FileExtension |> Some | "triggeredByDependency" -> makeBoolConst com.Options.TriggeredByDependency |> Some + | "isDotnet" -> makeBoolConst false |> Some + | "isJavaScript" -> makeBoolConst (com.Options.Language = JavaScript) |> Some + | "isTypeScript" -> makeBoolConst (com.Options.Language = TypeScript) |> Some + | "isPython" -> makeBoolConst (com.Options.Language = Python) |> Some + | "isDart" -> makeBoolConst (com.Options.Language = Dart) |> Some + | "isRust" -> makeBoolConst (com.Options.Language = Rust) |> Some + | "isPhp" -> makeBoolConst (com.Options.Language = Php) |> Some + | "isBeam" -> makeBoolConst (com.Options.Language = Beam) |> Some | _ -> None | Naming.StartsWith "Fable.Core.Dart" rest, _ -> match rest with diff --git a/src/Fable.Transforms/Python/Replacements.fs b/src/Fable.Transforms/Python/Replacements.fs index 6325a88b28..874768dcb6 100644 --- a/src/Fable.Transforms/Python/Replacements.fs +++ b/src/Fable.Transforms/Python/Replacements.fs @@ -954,6 +954,14 @@ let fableCoreLib (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp | "debugMode" -> makeBoolConst com.Options.DebugMode |> Some | "typedArrays" -> makeBoolConst com.Options.TypedArrays |> Some | "extension" -> makeStrConst com.Options.FileExtension |> Some + | "isDotnet" -> makeBoolConst false |> Some + | "isJavaScript" -> makeBoolConst (com.Options.Language = JavaScript) |> Some + | "isTypeScript" -> makeBoolConst (com.Options.Language = TypeScript) |> Some + | "isPython" -> makeBoolConst (com.Options.Language = Python) |> Some + | "isDart" -> makeBoolConst (com.Options.Language = Dart) |> Some + | "isRust" -> makeBoolConst (com.Options.Language = Rust) |> Some + | "isPhp" -> makeBoolConst (com.Options.Language = Php) |> Some + | "isBeam" -> makeBoolConst (com.Options.Language = Beam) |> Some | _ -> None | "Fable.Core.Py", ("python" | "expr_python" as meth) -> let isStatement = meth <> "expr_python" diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs index 446cb86b99..cd4b352eca 100644 --- a/src/Fable.Transforms/Replacements.fs +++ b/src/Fable.Transforms/Replacements.fs @@ -1089,6 +1089,14 @@ let fableCoreLib (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp | "typedArrays" -> makeBoolConst com.Options.TypedArrays |> Some | "extension" -> makeStrConst com.Options.FileExtension |> Some | "triggeredByDependency" -> makeBoolConst com.Options.TriggeredByDependency |> Some + | "isDotnet" -> makeBoolConst false |> Some + | "isJavaScript" -> makeBoolConst (com.Options.Language = JavaScript) |> Some + | "isTypeScript" -> makeBoolConst (com.Options.Language = TypeScript) |> Some + | "isPython" -> makeBoolConst (com.Options.Language = Python) |> Some + | "isDart" -> makeBoolConst (com.Options.Language = Dart) |> Some + | "isRust" -> makeBoolConst (com.Options.Language = Rust) |> Some + | "isPhp" -> makeBoolConst (com.Options.Language = Php) |> Some + | "isBeam" -> makeBoolConst (com.Options.Language = Beam) |> Some | _ -> None | "Fable.Core.JS", ("js" | "expr_js" as meth) -> let isStatement = meth <> "expr_js" diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs index a614ebd0a5..5e900ec2f3 100644 --- a/src/Fable.Transforms/Rust/Replacements.fs +++ b/src/Fable.Transforms/Rust/Replacements.fs @@ -741,6 +741,14 @@ let fableCoreLib (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp | "debugMode" -> makeBoolConst com.Options.DebugMode |> Some | "typedArrays" -> makeBoolConst com.Options.TypedArrays |> Some | "extension" -> makeStrConst com.Options.FileExtension |> Some + | "isDotnet" -> makeBoolConst false |> Some + | "isJavaScript" -> makeBoolConst (com.Options.Language = JavaScript) |> Some + | "isTypeScript" -> makeBoolConst (com.Options.Language = TypeScript) |> Some + | "isPython" -> makeBoolConst (com.Options.Language = Python) |> Some + | "isDart" -> makeBoolConst (com.Options.Language = Dart) |> Some + | "isRust" -> makeBoolConst (com.Options.Language = Rust) |> Some + | "isPhp" -> makeBoolConst (com.Options.Language = Php) |> Some + | "isBeam" -> makeBoolConst (com.Options.Language = Beam) |> Some | _ -> None | "Fable.Core.RustInterop", "op_BangHat" -> List.tryHead args | "Fable.Core.RustInterop", _ -> diff --git a/src/fable-metadata/lib/Fable.Core.dll b/src/fable-metadata/lib/Fable.Core.dll index 17a48dd899..cabadd25bf 100644 Binary files a/src/fable-metadata/lib/Fable.Core.dll and b/src/fable-metadata/lib/Fable.Core.dll differ diff --git a/tests/Beam/MiscTests.fs b/tests/Beam/MiscTests.fs index 190c5802fc..f57f446add 100644 --- a/tests/Beam/MiscTests.fs +++ b/tests/Beam/MiscTests.fs @@ -3,6 +3,7 @@ module Fable.Tests.Misc #nowarn "40" open System +open Fable.Core open FSharp.UMX open Util.Testing open Util2.Extensions @@ -1178,3 +1179,38 @@ let ``test Optimized assignment blocks inside try ... with work`` () = try A.C.Helper.Add5(let mutable x = 2 in let mutable y = 3 in x + y) with _ -> 1 equal 10 res + +[] +let ``test Compiler target flags have correct value per target`` () = + equal false Compiler.isJavaScript + equal false Compiler.isTypeScript + equal false Compiler.isPython + equal false Compiler.isDart + equal false Compiler.isRust +#if FABLE_COMPILER_BEAM + equal true Compiler.isBeam +#else + equal false Compiler.isBeam +#endif +#if FABLE_COMPILER + equal false Compiler.isDotnet +#else + equal true Compiler.isDotnet +#endif + equal false (Compiler.isJavaScript || Compiler.isTypeScript) + +[] +let ``test Compiler target flags eliminate dead branches`` () = + let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isTypeScript then "typescript" + elif Compiler.isPython then "python" + elif Compiler.isDart then "dart" + elif Compiler.isRust then "rust" + elif Compiler.isBeam then "beam" + else "dotnet" +#if FABLE_COMPILER_BEAM + equal "beam" target +#else + equal "dotnet" target +#endif diff --git a/tests/Dart/src/MiscTests.fs b/tests/Dart/src/MiscTests.fs index c5513fd1c6..92e77e7f20 100644 --- a/tests/Dart/src/MiscTests.fs +++ b/tests/Dart/src/MiscTests.fs @@ -1,6 +1,7 @@ module Fable.Tests.Dart.Misc open System +open Fable.Core open Util let increase (x: int ref) = @@ -129,3 +130,34 @@ let tests() = throwsError "This is invalid (Parameter 'arg')" (fun () -> invalidArg "arg" "This is invalid" ) + + testCase "Compiler target flags have correct value per target" <| fun () -> + equal false Compiler.isJavaScript + equal false Compiler.isTypeScript + equal false Compiler.isPython +#if FABLE_COMPILER_DART + equal true Compiler.isDart +#else + equal false Compiler.isDart +#endif + equal false Compiler.isRust +#if FABLE_COMPILER + equal false Compiler.isDotnet +#else + equal true Compiler.isDotnet +#endif + equal false (Compiler.isJavaScript || Compiler.isTypeScript) + + testCase "Compiler target flags eliminate dead branches" <| fun () -> + let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isTypeScript then "typescript" + elif Compiler.isPython then "python" + elif Compiler.isDart then "dart" + elif Compiler.isRust then "rust" + else "dotnet" +#if FABLE_COMPILER_DART + equal "dart" target +#else + equal "dotnet" target +#endif diff --git a/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.fs b/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.fs new file mode 100644 index 0000000000..4911c60c4a --- /dev/null +++ b/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.fs @@ -0,0 +1,12 @@ +module ConditionalTargetBranching + +open Fable.Core + +let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isPython then "python" + else "dotnet" + +let targetFromFamily = + if Compiler.isJavaScript || Compiler.isTypeScript then "js-family" + else "other" diff --git a/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.jsx.expected b/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.jsx.expected new file mode 100644 index 0000000000..7705bb98d9 --- /dev/null +++ b/tests/Integration/Integration/data/conditionalTargetBranching/ConditionalTargetBranching.jsx.expected @@ -0,0 +1,3 @@ +export const target = "javascript"; + +export const targetFromFamily = "js-family"; \ No newline at end of file diff --git a/tests/Integration/Integration/data/conditionalTargetBranching/conditionalTargetBranching.fsproj b/tests/Integration/Integration/data/conditionalTargetBranching/conditionalTargetBranching.fsproj new file mode 100644 index 0000000000..8de8b6d281 --- /dev/null +++ b/tests/Integration/Integration/data/conditionalTargetBranching/conditionalTargetBranching.fsproj @@ -0,0 +1,20 @@ + + + + net10.0 + Major + true + + + + + + + + + + ../../../../../src/Fable.Core/bin/Release/netstandard2.0/Fable.Core.dll + + + + diff --git a/tests/Js/Main/MiscTests.fs b/tests/Js/Main/MiscTests.fs index 8e0d62f525..62d886518e 100644 --- a/tests/Js/Main/MiscTests.fs +++ b/tests/Js/Main/MiscTests.fs @@ -609,6 +609,47 @@ let tests = ".js" #endif Compiler.extension.EndsWith(ext) |> equal true + + testCase "isJavaScript || isTypeScript is true for JS family targets" <| fun _ -> + equal true (Compiler.isJavaScript || Compiler.isTypeScript) + equal false (Compiler.isPython || Compiler.isDart || Compiler.isRust || Compiler.isBeam) + + testCase "Compiler target flags have correct value per target" <| fun _ -> +#if FABLE_COMPILER_JAVASCRIPT + equal true Compiler.isJavaScript + equal false Compiler.isTypeScript +#endif +#if FABLE_COMPILER_TYPESCRIPT + equal false Compiler.isJavaScript + equal true Compiler.isTypeScript +#endif + equal false Compiler.isPython + equal false Compiler.isDart + equal false Compiler.isRust +#if FABLE_COMPILER + equal false Compiler.isDotnet +#else + equal true Compiler.isDotnet +#endif + equal true (Compiler.isJavaScript || Compiler.isTypeScript) + + testCase "Compiler target flags eliminate dead branches" <| fun _ -> + let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isTypeScript then "typescript" + elif Compiler.isPython then "python" + else "dotnet" + let family = + if Compiler.isJavaScript || Compiler.isTypeScript then "js-family" + else "other" +#if FABLE_COMPILER_JAVASCRIPT + equal "javascript" target + equal "js-family" family +#endif +#if FABLE_COMPILER_TYPESCRIPT + equal "typescript" target + equal "js-family" family +#endif #endif testCase "Values of autogenerated functions are not replaced by optimizations" <| fun () -> // See #1583 diff --git a/tests/Python/TestMisc.fs b/tests/Python/TestMisc.fs index 95994941dc..9dcdad824d 100644 --- a/tests/Python/TestMisc.fs +++ b/tests/Python/TestMisc.fs @@ -531,6 +531,29 @@ let ``test Can access compiler options`` () = let ``test Can access extension for generated files`` () = Compiler.extension.EndsWith(".py") |> equal true +[] +let ``test Compiler target flags have correct value per target`` () = + equal false Compiler.isJavaScript + equal false Compiler.isTypeScript + equal true Compiler.isPython + equal false Compiler.isDart + equal false Compiler.isRust +#if FABLE_COMPILER + equal false Compiler.isDotnet +#else + equal true Compiler.isDotnet +#endif + equal false (Compiler.isJavaScript || Compiler.isTypeScript) + +[] +let ``test Compiler target flags eliminate dead branches`` () = + let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isTypeScript then "typescript" + elif Compiler.isPython then "python" + else "dotnet" + equal "python" target + #endif [] diff --git a/tests/Rust/tests/src/MiscTests.fs b/tests/Rust/tests/src/MiscTests.fs index 9b07f9cfaa..6b5e99aef6 100644 --- a/tests/Rust/tests/src/MiscTests.fs +++ b/tests/Rust/tests/src/MiscTests.fs @@ -587,6 +587,31 @@ let ``Can check compiler version with constant`` () = // let ``Can access extension for generated files`` () = // Compiler.extension.EndsWith(".js") |> equal true +[] +let ``Compiler target flags have correct value per target`` () = + equal false Compiler.isJavaScript + equal false Compiler.isTypeScript + equal false Compiler.isPython + equal false Compiler.isDart + equal true Compiler.isRust +#if FABLE_COMPILER + equal false Compiler.isDotnet +#else + equal true Compiler.isDotnet +#endif + equal false (Compiler.isJavaScript || Compiler.isTypeScript) + +[] +let ``Compiler target flags eliminate dead branches`` () = + let target = + if Compiler.isJavaScript then "javascript" + elif Compiler.isTypeScript then "typescript" + elif Compiler.isPython then "python" + elif Compiler.isDart then "dart" + elif Compiler.isRust then "rust" + else "dotnet" + equal "rust" target + #endif []