diff --git a/src/stdlib/Builtins.fs b/src/stdlib/Builtins.fs index dbe193a..194b275 100644 --- a/src/stdlib/Builtins.fs +++ b/src/stdlib/Builtins.fs @@ -186,11 +186,12 @@ type IExports = /// Make an iterator that computes the function using arguments from each /// of the iterables. Stops when the shortest iterable is exhausted. - abstract map: ('T1 * 'T2 -> 'T3) * IEnumerable<'T1> * IEnumerable<'T2> -> IEnumerable<'T3> + abstract map: System.Func<'T1, 'T2, 'T3> * IEnumerable<'T1> * IEnumerable<'T2> -> IEnumerable<'T3> /// Make an iterator that computes the function using arguments from each /// of the iterables. Stops when the shortest iterable is exhausted. - abstract map: ('T1 * 'T2 * 'T3 -> 'T4) * IEnumerable<'T1> * IEnumerable<'T2> * IEnumerable<'T3> -> IEnumerable<'T4> + abstract map: + System.Func<'T1, 'T2, 'T3, 'T4> * IEnumerable<'T1> * IEnumerable<'T2> * IEnumerable<'T3> -> IEnumerable<'T4> /// Return the Unicode code point for a one-character string. abstract ord: char -> int diff --git a/test/TestBuiltins.fs b/test/TestBuiltins.fs index 5af0fc8..d2c4a69 100644 --- a/test/TestBuiltins.fs +++ b/test/TestBuiltins.fs @@ -120,3 +120,107 @@ let ``test pyNone is None`` () = builtins.bool pyNone |> equal false // None has type NoneType, so isinstance(None, type(None)) holds builtins.isinstance (pyNone, builtins.``type`` pyNone) |> equal true + +[] +let ``test abs with int works`` () = + builtins.abs -5 |> equal 5 + builtins.abs 0 |> equal 0 + builtins.abs 42 |> equal 42 + +[] +let ``test abs with float works`` () = + builtins.abs -3.14 |> equal 3.14 + builtins.abs 0.0 |> equal 0.0 + builtins.abs 2.72 |> equal 2.72 + +[] +let ``test chr and ord round-trip works`` () = + builtins.chr 65 |> equal 'A' + builtins.chr 97 |> equal 'a' + builtins.ord 'A' |> equal 65 + builtins.ord 'a' |> equal 97 + +[] +let ``test chr ord round-trip preserves value`` () = + let code = 9731 // snowman ☃ + builtins.ord (builtins.chr code) |> equal code + +[] +let ``test len with list works`` () = + // F# `int list` compiles to FSharpList (no __len__); convert via builtins.list. + builtins.len (builtins.list (seq { 1..3 })) |> equal 3 + builtins.len (builtins.list Seq.empty) |> equal 0 + +[] +let ``test len with string works`` () = + builtins.len ("hello" |> box) |> equal 5 + builtins.len ("" |> box) |> equal 0 + +[] +let ``test map with single iterable works`` () = + builtins.map ((fun x -> x * 2), [ 1; 2; 3 ]) + |> Seq.toList + |> equal [ 2; 4; 6 ] + +[] +let ``test map with two iterables works`` () = + builtins.map ((fun a b -> a + b), [ 1; 2; 3 ], [ 10; 20; 30 ]) + |> Seq.toList + |> equal [ 11; 22; 33 ] + +[] +let ``test map with three iterables works`` () = + builtins.map ((fun a b c -> a + b + c), [ 1; 2; 3 ], [ 10; 20; 30 ], [ 100; 200; 300 ]) + |> Seq.toList + |> equal [ 111; 222; 333 ] + +[] +let ``test str conversion works`` () = + builtins.str 42 |> equal "42" + builtins.str true |> equal "True" + +[] +let ``test int conversion works`` () = + builtins.int "42" |> equal 42 + builtins.int 3.9 |> equal 3 + // Python's int() truncates toward zero, not floor + builtins.int -3.9 |> equal -3 + +[] +let ``test float conversion works`` () = + builtins.float "3.14" |> equal 3.14 + builtins.float 42 |> equal 42.0 + +[] +let ``test isinstance works`` () = + let pyIntVal: obj = emitPyExpr () "42" + let pyStrVal: obj = emitPyExpr () "'hello'" + builtins.isinstance (pyStrVal, pyStr) |> equal true + builtins.isinstance (pyIntVal, pyInt) |> equal true + +[] +let ``test isinstance returns false for wrong type`` () = + let pyIntVal: obj = emitPyExpr () "42" + builtins.isinstance (pyIntVal, pyStr) |> equal false + +[] +let ``test type returns type object`` () = + let pyStrVal: obj = emitPyExpr () "'hello'" + let pyIntVal: obj = emitPyExpr () "42" + let t = builtins.``type`` pyStrVal + builtins.isinstance (pyStrVal, t) |> equal true + builtins.isinstance (pyIntVal, t) |> equal false + +[] +let ``test bytes from byte array works`` () = + let b = builtins.bytes [| 72uy; 101uy; 108uy; 108uy; 111uy |] + builtins.len b |> equal 5 + b.[0] |> equal 72uy + b.[4] |> equal 111uy + +[] +let ``test bytes from string with encoding works`` () = + let b = builtins.bytes ("ABC", "utf-8") + builtins.len b |> equal 3 + b.[0] |> equal 65uy + b.[2] |> equal 67uy