Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rust] Added missing ResizeArray methods and tests #3896

Merged
merged 1 commit into from
Sep 22, 2024
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
8 changes: 6 additions & 2 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

* [Rust] Added support for Dictionary/HashSet comparers (by @ncave)
* [Rust] Updated support for interface object expressions (by @ncave)
* [Rust] Added missing ResizeArray methods and tests (by @ncave)

## 4.21.0 - 2024-09-19

### Added

* [JS/TS] Add support for `OrdinalIgnoreCase` overload for `String.EndsWith` (#3892) (by @goswinr)
* [JS/TS] Add `uri.Port`, `uri.IsDefaultPort` (by @MangelMaxime)
* [Rust] Added support for Dictionary/HashSet comparers (by @ncave)
* [Rust] Updated support for interface object expressions (by @ncave)

### Changed

Expand Down
134 changes: 46 additions & 88 deletions src/Fable.Transforms/Rust/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ let makeRefFromMutableFunc com ctx r t (value: Expr) = value

let toNativeIndex expr = TypeCast(expr, UNativeInt.Number)

let toLowerFirstWithArgsCountSuffix (args: Expr list) meth =
let argCount = List.length args
let meth = Naming.lowerFirst meth

if argCount > 1 then
meth + (string argCount)
else
meth

let toChar com (arg: Expr) =
match arg.Type with
| Char -> arg
Expand Down Expand Up @@ -338,7 +347,6 @@ let emitFormat (com: ICompiler) r t (args: Expr list) macro =
let unboxedArgs = args |> FSharp2Fable.Util.unboxBoxedArgs
Helper.LibCall(com, "String", macro, t, unboxedArgs)


let getMut expr =
Helper.InstanceCall(expr, "get_mut", expr.Type, [])

Expand Down Expand Up @@ -1601,79 +1609,39 @@ let seqModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg

let resizeArrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
match i.CompiledName, thisArg, args with
| ".ctor", _, [] ->
// makeArray (getElementType t) [] |> Some
Helper.LibCall(com, "NativeArray", "new_empty", t, [], ?loc = r) |> Some
| ".ctor", _, [ ExprTypeAs(Number(Int32, _), idx) ] ->
Helper.LibCall(com, "NativeArray", "new_with_capacity", t, [ idx ], ?loc = r)
|> Some
// Optimize expressions like `ResizeArray [|1|]` or `ResizeArray [1]`
| ".ctor", _, [ ArrayOrListLiteral(vals, typ) ] -> makeArray typ vals |> Some
| ".ctor", _, [] -> Helper.LibCall(com, "NativeArray", "new_empty", t, args, ?loc = r) |> Some
| ".ctor", _, [ ExprType(Number(Int32, _)) ] ->
Helper.LibCall(com, "NativeArray", "new_with_capacity", t, args, ?loc = r)
|> Some
| ".ctor", _, [ ExprType(IEnumerable) ] ->
Helper.LibCall(com, "NativeArray", "new_from_enumerable", t, args, ?loc = r)
|> Some
| ".ctor", _, [ arg ] -> toArray com t arg |> Some
| "get_Capacity", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Capacity", t, [ ar ], ?loc = r) |> Some
| "get_Count", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some
| "get_Item", Some ar, [ idx ] -> getExpr r t ar idx |> Some
| "set_Item", Some ar, [ idx; value ] -> setExpr r ar idx value |> Some
| "Add", Some(MaybeCasted(ar)), [ arg ] ->
Helper.LibCall(com, "NativeArray", "add", t, [ ar; arg ], ?loc = r) |> Some
| "Remove", Some(MaybeCasted(ar)), [ arg ] ->
Helper.LibCall(com, "Array", "removeInPlace", t, [ arg; ar ], ?loc = r) |> Some
| "RemoveAll", Some ar, [ arg ] ->
Helper.LibCall(com, "Array", "removeAllInPlace", t, [ arg; ar ], ?loc = r)
|> Some
| "FindIndex", Some ar, [ arg ] ->
Helper.LibCall(com, "NativeArray", "FindIndex", t, [ ar; arg ], ?loc = r)
|> Some
| "FindLastIndex", Some ar, [ arg ] ->
Helper.LibCall(com, "Array", "findLastIndex", t, [ arg; ar ], ?loc = r) |> Some
| "ForEach", Some ar, [ arg ] -> makeInstanceCall r t i ar "forEach" [ arg ] |> Some
| "GetEnumerator", Some(MaybeCasted(ar)), _ ->
Helper.LibCall(com, "Seq", "Enumerable::ofArray", t, [ ar ], ?loc = r) |> Some
| "get_Count", Some(MaybeCasted(ar)), _ -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some
| "Clear", Some(MaybeCasted(ar)), [] -> makeInstanceCall r t i (getMut ar) "clear" [] |> Some
| "ConvertAll", Some ar, [ arg ] -> Helper.LibCall(com, "Array", "map", t, [ arg; ar ], ?loc = r) |> Some
| "Find", Some ar, [ arg ] ->
let opt = Helper.LibCall(com, "Array", "tryFind", t, [ arg; ar ], ?loc = r)

Helper.LibCall(com, "Option", "defaultArg", t, [ opt; getZero com ctx t ], ?loc = r)
|> Some
| "Exists", Some ar, [ arg ] ->
Helper.LibCall(com, "Array", "exists", t, [ arg; ar ], i.SignatureArgTypes, ?loc = r)
|> Some
| "FindLast", Some ar, [ arg ] ->
let opt = Helper.LibCall(com, "Array", "tryFindBack", t, [ arg; ar ], ?loc = r)

Helper.LibCall(com, "Option", "defaultArg", t, [ opt; getZero com ctx t ], ?loc = r)
|> Some
| "FindAll", Some ar, [ arg ] -> Helper.LibCall(com, "Array", "filter", t, [ arg; ar ], ?loc = r) |> Some
| "AddRange", Some ar, [ arg ] ->
Helper.LibCall(com, "Array", "addRangeInPlace", t, [ arg; ar ], ?loc = r)
|> Some
| "GetRange", Some ar, [ idx; cnt ] ->
Helper.LibCall(com, "Array", "getSubArray", t, [ ar; idx; cnt ], ?loc = r)
|> Some
| "Contains", Some(MaybeCasted(ar)), [ arg ] ->
Helper.LibCall(com, "Array", "contains", t, [ arg; ar ], i.SignatureArgTypes, ?loc = r)
|> Some
| "IndexOf", Some ar, [ arg ] ->
Helper.LibCall(com, "Array", "indexOf", t, [ ar; arg ], i.SignatureArgTypes, ?loc = r)
|> Some
| "Insert", Some ar, [ idx; arg ] -> makeInstanceCall r t i (getMut ar) "insert" [ toNativeIndex idx; arg ] |> Some
| "InsertRange", Some ar, [ idx; arg ] ->
Helper.LibCall(com, "Array", "insertRangeInPlace", t, [ idx; arg; ar ], ?loc = r)
|> Some
| "RemoveRange", Some ar, args -> makeInstanceCall r t i ar "splice" args |> Some
| "RemoveAt", Some ar, [ idx ] -> makeInstanceCall r t i (getMut ar) "remove" [ toNativeIndex idx ] |> Some
| "Reverse", Some ar, [] -> makeInstanceCall r t i (getMut ar) "reverse" args |> Some
| "Sort", Some ar, [] ->
// can't use .sort() as it needs T: Ord
Helper.LibCall(com, "Array", "sortInPlace", t, [ ar ], i.SignatureArgTypes, ?loc = r)
| ("Add" | "AddRange" | "Clear" | "Contains" | "ConvertAll" | "Exists" | "GetRange" | "Slice" | "ForEach" | "FindAll" | "Find" | "FindLast" | "FindIndex" | "FindLastIndex" | "Insert" | "InsertRange" | "Remove" | "RemoveAt" | "RemoveAll" | "RemoveRange" | "ToArray" | "TrimExcess" | "TrueForAll") as meth,
Some ar,
args ->
// methods without overrides
let meth = Naming.lowerFirst meth
Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some
| ("BinarySearch" | "CopyTo" | "IndexOf" | "LastIndexOf" | "Reverse") as meth, Some ar, args ->
// methods with some overrides
let meth = meth |> toLowerFirstWithArgsCountSuffix args
Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some
| "Sort", Some ar, [] -> Helper.LibCall(com, "NativeArray", "sort", t, (ar :: args), ?loc = r) |> Some
| "Sort", Some ar, [ ExprType(DelegateType _) ] ->
Helper.LibCall(com, "NativeArray", "sortBy", t, (ar :: args), ?loc = r) |> Some
| "Sort", Some ar, [ comparer ] ->
Helper.LibCall(com, "NativeArray", "sortWith", t, (ar :: args), ?loc = r)
|> Some
| "Sort", Some ar, [ index; count; comparer ] ->
Helper.LibCall(com, "NativeArray", "sortWith2", t, (ar :: args), ?loc = r)
|> Some
| "Sort", Some ar, [ ExprType(DelegateType _) as comparer ] ->
let cmp = Helper.LibCall(com, "Native", "makeCompare", t, [ comparer ], ?loc = r)

makeInstanceCall r t i (getMut ar) "sort_by" [ cmp ] |> Some
// | "Sort", Some ar, [arg] ->
// Helper.LibCall(com, "Array", "sortInPlaceWithComparer", t, [ar; arg], i.SignatureArgTypes, ?loc=r) |> Some
| "ToArray", Some ar, [] -> Helper.LibCall(com, "NativeArray", "new_copy", t, [ ar ], ?loc = r) |> Some
| _ -> None

let collectionExtensions
Expand Down Expand Up @@ -1743,30 +1711,22 @@ let copyToArray (com: ICompiler) r t (i: CallInfo) args =

let arrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
match i.CompiledName, thisArg, args with
| "get_Length", Some ar, _ -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some
| "get_Length", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some
| "get_Item", Some ar, [ idx ] -> getExpr r t ar idx |> Some
| "set_Item", Some ar, [ idx; value ] -> setExpr r ar idx value |> Some
| "Clone", Some ar, _ -> Helper.LibCall(com, "NativeArray", "new_copy", t, [ ar ], ?loc = r) |> Some
| "Clone", Some ar, _ -> Helper.LibCall(com, "NativeArray", "toArray", t, [ ar ], ?loc = r) |> Some
| "Copy", None, [ _source; _sourceIndex; _target; _targetIndex; _count ] -> copyToArray com r t i args
| "Copy", None, [ source; target; count ] ->
copyToArray com r t i [ source; makeIntConst 0; target; makeIntConst 0; count ]
| "ConvertAll", None, [ source; mapping ] ->
Helper.LibCall(com, "Array", "map", t, [ mapping; source ], ?loc = r) |> Some
| "IndexOf", None, [ ar; arg ] ->
Helper.LibCall(com, "Array", "indexOf", t, args, i.SignatureArgTypes, ?loc = r)
|> Some
Helper.LibCall(com, "NativeArray", "convertAll", t, args, ?loc = r) |> Some
| "IndexOf", None, [ ar; arg ] -> Helper.LibCall(com, "NativeArray", "indexOf", t, args, ?loc = r) |> Some
| "GetEnumerator", Some ar, _ -> Helper.LibCall(com, "Seq", "Enumerable::ofArray", t, [ ar ], ?loc = r) |> Some
| "Reverse", None, [ ar ] -> makeInstanceCall r t i (getMut ar) "reverse" [] |> Some
| "Sort", None, [ ar ] ->
// can't use .sort() as it needs T: Ord
Helper.LibCall(com, "Array", "sortInPlace", t, [ ar ], i.SignatureArgTypes, ?loc = r)
|> Some
| "Reverse", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "reverse", t, args, ?loc = r) |> Some
| "Sort", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "sort", t, args, ?loc = r) |> Some
| "Sort", None, [ ar; ExprType(DelegateType _) as comparer ] ->
let cmp = Helper.LibCall(com, "Native", "makeCompare", t, [ comparer ], ?loc = r)

makeInstanceCall r t i (getMut ar) "sort_by" [ cmp ] |> Some
// | "Sort", None, [ar; arg] ->
// Helper.LibCall(com, "Array", "sortInPlaceWithComparer", t, [ar; arg], i.SignatureArgTypes, ?loc=r) |> Some
Helper.LibCall(com, "NativeArray", "sortBy", t, args, ?loc = r) |> Some
| "Sort", None, [ ar; comparer ] -> Helper.LibCall(com, "NativeArray", "sortWith", t, args, ?loc = r) |> Some
| _ -> None

let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) =
Expand All @@ -1783,7 +1743,7 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
| "ToList", args ->
Helper.LibCall(com, "List", "ofArray", t, args, i.SignatureArgTypes, ?loc = r)
|> Some
| ("Length" | "Count"), [ ar ] -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some
| ("Length" | "Count"), [ ar ] -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some
| "Item", [ idx; ar ] -> getExpr r t ar idx |> Some
| "Get", [ ar; idx ] -> getExpr r t ar idx |> Some
| "Set", [ ar; idx; value ] -> setExpr r ar idx value |> Some
Expand All @@ -1792,9 +1752,7 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex
| "Empty", [] -> createArray com ctx r t i (makeIntConst 0) None |> Some
| "Singleton", [ value ] -> createArray com ctx r t i (makeIntConst 1) (Some value) |> Some
| "IsEmpty", [ ar ] -> makeInstanceCall r t i ar "is_empty" [] |> Some
| "Copy", [ ar ] ->
Helper.LibCall(com, "NativeArray", "new_copy", t, args, i.SignatureArgTypes, ?loc = r)
|> Some
| "Copy", [ ar ] -> Helper.LibCall(com, "NativeArray", "toArray", t, args, ?loc = r) |> Some
| "CopyTo", args -> copyToArray com r t i args
| ("Concat" | "Transpose" as meth), [ arg ] ->
Helper.LibCall(com, "Array", Naming.lowerFirst meth, t, [ toArray com t arg ], i.SignatureArgTypes, ?loc = r)
Expand Down
35 changes: 0 additions & 35 deletions src/fable-library-rust/src/Array.fs
Original file line number Diff line number Diff line change
Expand Up @@ -467,41 +467,6 @@ let truncate (count: int) (source: 'T[]) : 'T[] =

getSubArray source 0 count

// let addInPlace (x: 'T) (source: 'T[]) =
// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported"
// pushImpl source x |> ignore

// let addRangeInPlace (range: seq<'T>) (source: 'T[]) =
// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported"
// for x in range do
// addInPlace x source

// let insertRangeInPlace index (range: seq<'T>) (source: 'T[]) =
// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported"
// let mutable i = index
// for x in range do
// insertImpl source i x |> ignore
// i <- i + 1

// let removeInPlace (item: 'T) (source: 'T[]) =
// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported"
// let i = indexOfImpl source item 0
// if i > -1 then
// spliceImpl source i 1 |> ignore
// true
// else
// false

// let removeAllInPlace predicate (source: 'T[]) =
// let rec countRemoveAll count =
// let i = findIndexImpl predicate source
// if i > -1 then
// spliceImpl source i 1 |> ignore
// countRemoveAll count + 1
// else
// count
// countRemoveAll 0

// TODO: Check array lengths
let copyTo (source: 'T[]) sourceIndex (target: 'T[]) targetIndex count =
let diff = targetIndex - sourceIndex
Expand Down
12 changes: 6 additions & 6 deletions src/fable-library-rust/src/Interop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub mod ListExt {
}

pub mod SetExt {
use crate::Native_::{makeCompare, seq_to_iter, Func2, Vec};
use crate::Native_::{make_compare, seq_to_iter, Func2, Vec};
use crate::Set_::{add, compareTo, empty, equals, toSeq, Set};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
Expand Down Expand Up @@ -98,13 +98,13 @@ pub mod SetExt {

impl<T: Clone + PartialOrd> PartialOrd for Set<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(makeCompare(Func2::from(compareTo))(self, other))
Some(make_compare(Func2::from(compareTo))(self, other))
}
}

impl<T: Clone + PartialOrd> Ord for Set<T> {
fn cmp(&self, other: &Self) -> Ordering {
makeCompare(Func2::from(compareTo))(self, other)
make_compare(Func2::from(compareTo))(self, other)
}
}

Expand Down Expand Up @@ -147,7 +147,7 @@ pub mod SetExt {

pub mod MapExt {
use crate::Map_::{add, compareTo, empty, equals, iterate, toSeq, Map};
use crate::Native_::{makeCompare, seq_to_iter, Func2, Vec};
use crate::Native_::{make_compare, seq_to_iter, Func2, Vec};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};

Expand Down Expand Up @@ -181,13 +181,13 @@ pub mod MapExt {

impl<K: Clone + PartialOrd, V: Clone + PartialOrd> PartialOrd for Map<K, V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(makeCompare(Func2::from(compareTo))(self, other))
Some(make_compare(Func2::from(compareTo))(self, other))
}
}

impl<K: Clone + PartialOrd, V: Clone + PartialOrd> Ord for Map<K, V> {
fn cmp(&self, other: &Self) -> Ordering {
makeCompare(Func2::from(compareTo))(self, other)
make_compare(Func2::from(compareTo))(self, other)
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/fable-library-rust/src/Native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,16 @@ pub mod Native_ {
}
}

pub fn makeCompare<T: Clone + 'static>(
pub fn partial_compare<T: PartialOrd>(x: &T, y: &T) -> Ordering {
match x.partial_cmp(y) {
Some(ordering) => ordering,
None if y == y => Ordering::Less, // y is not NaN
None if x == x => Ordering::Greater, // x is not NaN
None => Ordering::Equal,
}
}

pub fn make_compare<T: Clone + 'static>(
comparer: Func2<T, T, i32>,
) -> impl Fn(&T, &T) -> Ordering {
move |x, y| match comparer(x.clone(), y.clone()) {
Expand Down
Loading
Loading