Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* [All] Add support for `Guid.CreateVersion7()` and `Guid.CreateVersion7(DateTimeOffset)`
* [Rust] Add missing `System.Random` implementation and tests (by @ncave)
* [Rust] Add missing `Array`, `List` and `Seq` module members and tests: `randomChoice`, `randomChoiceBy`, `randomChoiceWith`, `randomChoices`, `randomChoicesBy`, `randomChoicesWith`, `randomSample`, `randomSampleBy`, `randomSampleWith`, `randomShuffle`, `randomShuffleBy`, `randomShuffleWith` (by @ncave)
* [Beam] Implement missing DateTimeOffset members, add DateOnly and TimeOnly support
* [All] Add support for `Guid.CreateVersion7()` and `Guid.CreateVersion7(DateTimeOffset)` (by @OnurGumus)
* [All] Add missing `Array`, `List`, and `Seq` random choice/shuffle/sample members and tests (by @ncave)
* [Dart/Rust] Add missing `System.Random` implementations and tests (by @ncave)
* [Beam] Implement missing DateTimeOffset members, add DateOnly and TimeOnly support (by @dbrattli)

### Fixed

* [All] Fix unnecessary object allocations during AST traversal when visiting `Import` expressions (by Repo Assist)
* [Beam] Fix `System.Random.Next(0)` implementation (by @ncave)
* [Python] Fix `System.Random` seeded implementation (by @ncave)
* [Beam] Fix `System.Random` seeded implementation to use per-instance state (by @dbrattli)
* [Dart] Fix `Array.compareWith` comparing lengths before elements, producing wrong results for arrays with common prefixes (fixes #2961)
* [Python] Fix unsafe option unwrapping in `DateTimeOffset.get_Offset` and regex replacements (by @dbrattli)
* [All] Replace unsafe option `.Value` unwrapping with safe alternatives in Python/Replacements.fs and Rust/Fable2Rust.fs (code scanning alerts IONIDE-006)
Expand Down
11 changes: 7 additions & 4 deletions src/Fable.Compiler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* [All] Add support for `Guid.CreateVersion7()` and `Guid.CreateVersion7(DateTimeOffset)`
* [Rust] Add missing `System.Random` implementation and tests (by @ncave)
* [Rust] Add missing `Array`, `List` and `Seq` module members and tests: `randomChoice`, `randomChoiceBy`, `randomChoiceWith`, `randomChoices`, `randomChoicesBy`, `randomChoicesWith`, `randomSample`, `randomSampleBy`, `randomSampleWith`, `randomShuffle`, `randomShuffleBy`, `randomShuffleWith` (by @ncave)
* [Beam] Implement missing DateTimeOffset members, add DateOnly and TimeOnly support
* [All] Add support for `Guid.CreateVersion7()` and `Guid.CreateVersion7(DateTimeOffset)` (by @OnurGumus)
* [All] Add missing `Array`, `List`, and `Seq` random choice/shuffle/sample members and tests (by @ncave)
* [Dart/Rust] Add missing `System.Random` implementations and tests (by @ncave)
* [Beam] Implement missing DateTimeOffset members, add DateOnly and TimeOnly support (by @dbrattli)

### Fixed

* [All] Fix unnecessary object allocations during AST traversal when visiting `Import` expressions (by Repo Assist)
* [Beam] Fix `System.Random.Next(0)` implementation (by @ncave)
* [Python] Fix `System.Random` seeded implementation (by @ncave)
* [Beam] Fix `System.Random` seeded implementation to use per-instance state (by @dbrattli)
* [Dart] Fix `Array.compareWith` comparing lengths before elements, producing wrong results for arrays with common prefixes (fixes #2961)
* [Python] Fix unsafe option unwrapping in `DateTimeOffset.get_Offset` and regex replacements (by @dbrattli)
* [All] Replace unsafe option `.Value` unwrapping with safe alternatives in Python/Replacements.fs and Rust/Fable2Rust.fs (code scanning alerts IONIDE-006)
Expand Down
134 changes: 127 additions & 7 deletions src/Fable.Transforms/Beam/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,35 @@ let private listModule
| "OfArray", [ arr ] -> derefArr r arr |> Some
| "OfSeq", [ seq ] -> emitExpr r t [ seq ] "fable_utils:to_list($0)" |> Some
| "ToSeq", [ list ] -> Some(List.head args)
| "RandomShuffleBy", [ randomizer; list ] ->
Helper.LibCall(com, "fable_list", "random_shuffle_by", t, [ randomizer; list ])
|> Some
| "RandomShuffleWith", [ random; list ] ->
Helper.LibCall(com, "fable_list", "random_shuffle_with", t, [ random; list ])
|> Some
| "RandomShuffle", [ list ] -> Helper.LibCall(com, "fable_list", "random_shuffle", t, [ list ]) |> Some
| "RandomChoiceBy", [ randomizer; list ] ->
Helper.LibCall(com, "fable_list", "random_choice_by", t, [ randomizer; list ])
|> Some
| "RandomChoiceWith", [ random; list ] ->
Helper.LibCall(com, "fable_list", "random_choice_with", t, [ random; list ])
|> Some
| "RandomChoice", [ list ] -> Helper.LibCall(com, "fable_list", "random_choice", t, [ list ]) |> Some
| "RandomChoicesBy", [ randomizer; count; list ] ->
Helper.LibCall(com, "fable_list", "random_choices_by", t, [ randomizer; count; list ])
|> Some
| "RandomChoicesWith", [ random; count; list ] ->
Helper.LibCall(com, "fable_list", "random_choices_with", t, [ random; count; list ])
|> Some
| "RandomChoices", [ count; list ] ->
Helper.LibCall(com, "fable_list", "random_choices", t, [ count; list ]) |> Some
| "RandomSampleBy", [ randomizer; count; list ] ->
Helper.LibCall(com, "fable_list", "random_sample_by", t, [ randomizer; count; list ])
|> Some
| "RandomSampleWith", [ random; count; list ] ->
Helper.LibCall(com, "fable_list", "random_sample_with", t, [ random; count; list ])
|> Some
| "RandomSample", [ count; list ] -> Helper.LibCall(com, "fable_list", "random_sample", t, [ count; list ]) |> Some
| _ -> None

/// Beam-specific FSharpList instance method replacements.
Expand Down Expand Up @@ -2119,6 +2148,91 @@ let private arrayModule
let a1 = derefArr r a1
let a2 = derefArr r a2
Helper.LibCall(com, "fable_list", "compare_with", t, [ fn; a1; a2 ]) |> Some
| "RandomShuffleBy", [ randomizer; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_shuffle_by", t, [ randomizer; lst ])
|> wrapArr com r t
|> Some
| "RandomShuffleWith", [ random; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_shuffle_with", t, [ random; lst ])
|> wrapArr com r t
|> Some
| "RandomShuffle", [ arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_shuffle", t, [ lst ])
|> wrapArr com r t
|> Some
| "RandomShuffleInPlaceBy", [ randomizer; arr ] ->
let lst = derefArr r arr

let shuffled =
Helper.LibCall(com, "fable_list", "random_shuffle_by", Any, [ randomizer; lst ])

emitExpr r t [ arr; shuffled ] "begin erlang:put($0, $1), ok end" |> Some
| "RandomShuffleInPlaceWith", [ random; arr ] ->
let lst = derefArr r arr

let shuffled =
Helper.LibCall(com, "fable_list", "random_shuffle_with", Any, [ random; lst ])

emitExpr r t [ arr; shuffled ] "begin erlang:put($0, $1), ok end" |> Some
| "RandomShuffleInPlace", [ arr ] ->
let lst = derefArr r arr
let shuffled = Helper.LibCall(com, "fable_list", "random_shuffle", Any, [ lst ])
emitExpr r t [ arr; shuffled ] "begin erlang:put($0, $1), ok end" |> Some
| "RandomChoiceBy", [ randomizer; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_choice_by", t, [ randomizer; lst ])
|> Some
| "RandomChoiceWith", [ random; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_choice_with", t, [ random; lst ])
|> Some
| "RandomChoice", [ arr ] ->
let lst = derefArr r arr
Helper.LibCall(com, "fable_list", "random_choice", t, [ lst ]) |> Some
| "RandomChoicesBy", [ randomizer; count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_choices_by", t, [ randomizer; count; lst ])
|> wrapArr com r t
|> Some
| "RandomChoicesWith", [ random; count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_choices_with", t, [ random; count; lst ])
|> wrapArr com r t
|> Some
| "RandomChoices", [ count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_choices", t, [ count; lst ])
|> wrapArr com r t
|> Some
| "RandomSampleBy", [ randomizer; count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_sample_by", t, [ randomizer; count; lst ])
|> wrapArr com r t
|> Some
| "RandomSampleWith", [ random; count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_sample_with", t, [ random; count; lst ])
|> wrapArr com r t
|> Some
| "RandomSample", [ count; arr ] ->
let lst = derefArr r arr

Helper.LibCall(com, "fable_list", "random_sample", t, [ count; lst ])
|> wrapArr com r t
|> Some
// === Transform ops: deref input(s) AND wrap result ===
| "Map", [ fn; arr ] ->
let arr = derefArr r arr
Expand Down Expand Up @@ -3936,18 +4050,24 @@ let private randoms
match args with
| [ seed ] -> Helper.LibCall(com, "fable_random", "new_seeded", t, [ seed ], ?loc = r) |> Some
| _ -> Helper.LibCall(com, "fable_random", "new", t, [], ?loc = r) |> Some
| "Next", Some _ ->
| "Next", Some thisArg ->
match args with
| [] -> Helper.LibCall(com, "fable_random", "next", t, [], ?loc = r) |> Some
| [ maxVal ] -> Helper.LibCall(com, "fable_random", "next", t, [ maxVal ], ?loc = r) |> Some
| [] -> Helper.LibCall(com, "fable_random", "next", t, [ thisArg ], ?loc = r) |> Some
| [ maxVal ] ->
Helper.LibCall(com, "fable_random", "next", t, [ thisArg; maxVal ], ?loc = r)
|> Some
| [ minVal; maxVal ] ->
Helper.LibCall(com, "fable_random", "next", t, [ minVal; maxVal ], ?loc = r)
Helper.LibCall(com, "fable_random", "next", t, [ thisArg; minVal; maxVal ], ?loc = r)
|> Some
| _ -> None
| "NextDouble", Some _ -> Helper.LibCall(com, "fable_random", "next_double", t, [], ?loc = r) |> Some
| "NextBytes", Some _ ->
| "NextDouble", Some thisArg ->
Helper.LibCall(com, "fable_random", "next_double", t, [ thisArg ], ?loc = r)
|> Some
| "NextBytes", Some thisArg ->
match args with
| [ arr ] -> Helper.LibCall(com, "fable_random", "next_bytes", t, [ arr ], ?loc = r) |> Some
| [ arr ] ->
Helper.LibCall(com, "fable_random", "next_bytes", t, [ thisArg; arr ], ?loc = r)
|> Some
| _ -> None
| _ -> None

Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Dart/Fable2Dart.fs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ module Util =
| "Fable.Core.Dart.DartNullable`1", [ genArg ] -> Nullable genArg
| Types.regexGroup, _ -> Nullable String
| Types.regexMatch, _ -> makeTypeRefFromName "Match" []
| "System.Random", _ -> libTypeRef com ctx "Random" "Random" []
// We use `dynamic` for Exception because there is no single type that catches all errors in Dart
// (except when inherited as base class, then it's getExceptionType, see transformInheritedClass)
| Types.exception_, _ -> Dynamic // getExceptionType com ctx
Expand Down
18 changes: 13 additions & 5 deletions src/Fable.Transforms/Dart/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,7 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
let t = genArg com ctx r 0 i.GenericArgs
makeArrayWithRange r t [] |> Some
| "IsEmpty", [ ar ] -> getFieldWith r t ar "isEmpty" |> Some
| "Contains", [ value; ar ] -> Helper.LibCall(com, "Array", "contains", t, [ value; ar ], ?loc = r) |> Some
| "CopyTo", args -> copyToArray com r t i args
| ("Distinct" | "DistinctBy" | "Except" | "GroupBy" | "CountBy" as meth), args ->
let meth = Naming.lowerFirst meth
Expand Down Expand Up @@ -3076,11 +3077,18 @@ let globalization
let random (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
match i.CompiledName, thisArg with
| ".ctor", _ ->
match args with
| [] -> Helper.LibCall(com, "Random", "nonSeeded", t, [], [], ?loc = r) |> Some
| args ->
Helper.LibCall(com, "Random", "seeded", t, args, i.SignatureArgTypes, genArgs = i.GenericArgs, ?loc = r)
|> Some
Helper.LibCall(
com,
"Random",
"Random",
t,
args,
i.SignatureArgTypes,
genArgs = i.GenericArgs,
isConstructor = true,
?loc = r
)
|> Some
// Not yet supported
| ("NextInt64" | "NextSingle"), _ -> None
| meth, Some thisArg ->
Expand Down
32 changes: 17 additions & 15 deletions src/Fable.Transforms/Python/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3254,30 +3254,32 @@ let globalization
ObjectExpr([], t, None) |> Some
| _ -> None

let random (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr option) (args: Expr list) =
match i.CompiledName with
| ".ctor" -> ObjectExpr([], t, None) |> Some
| "Next" ->
let random (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
match i.CompiledName, thisArg with
| ".ctor", _ ->
Helper.LibCall(com, "util", "create_random", t, args, i.SignatureArgTypes, ?loc = r)
|> Some
| "Next", Some thisArg ->
let min, max =
match args with
| [] -> makeIntConst 0, makeIntConst System.Int32.MaxValue
| [ max ] -> makeIntConst 0, max
| [ min; max ] -> min, max
| _ -> FableError "Unexpected arg count for Random.Next" |> raise

Helper.LibCall(com, "util", "randint", t, [ min; max ], [ min.Type; max.Type ], ?loc = r)
|> Some
| "NextDouble" ->
let ranExpr = Helper.ImportedCall("random", "random", t, [], [])
Helper.LibCall(com, "core", "float64", t, [ ranExpr ], ?loc = r) |> Some
| "NextBytes" ->
let byteArray =
match args with
| [ b ] -> b
| _ -> FableError "Unexpected arg count for Random.NextBytes" |> raise
let args = [ thisArg; min; max ]
let argTypes = [ thisArg.Type; min.Type; max.Type ]
Helper.LibCall(com, "util", "random_int", t, args, argTypes, ?loc = r) |> Some
| "NextDouble", Some thisArg ->
let args = [ thisArg ]
let argTypes = [ thisArg.Type ]

Helper.LibCall(com, "util", "random_bytes", t, [ byteArray ], [ byteArray.Type ], ?loc = r)
Helper.LibCall(com, "util", "random_double", t, args, argTypes, ?loc = r)
|> Some
| "NextBytes", Some thisArg ->
let args = thisArg :: args
let argTypes = thisArg.Type :: i.SignatureArgTypes
Helper.LibCall(com, "util", "random_bytes", t, args, argTypes, ?loc = r) |> Some
| _ -> None

let cancels (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
Expand Down
Loading
Loading