Skip to content

Commit

Permalink
Fix #2614 #2615
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsogarciacaro committed Nov 23, 2021
1 parent 7f494c4 commit a69e20d
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 2 deletions.
1 change: 1 addition & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ match BUILD_ARGS_LOWER with
| "test-integration"::_ -> testIntegration()
| "quicktest"::_ ->
buildLibraryIfNotExists()
removeDirRecursive "src/quicktest/fable_modules"
run "dotnet watch --project src/Fable.Cli run -- watch --cwd ../quicktest --exclude Fable.Core --noCache --runScript"

| "run"::_ ->
Expand Down
18 changes: 16 additions & 2 deletions src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,10 @@ let toInt com (ctx: Context) r targetType (args: Expr list) =
| JsNumber UInt32 -> emitJsExpr None (Number UInt32) [arg] "$0 >>> 0"
| _ -> failwithf "Unexpected non-integer type %A" typeTo
match sourceType, targetType with
| Char, _ -> Helper.InstanceCall(args.Head, "charCodeAt", targetType, [makeIntConst 0])
| Char, _ ->
match targetType, args with
| Number kind, Value(CharConstant c, r)::_ -> Value(NumberConstant(float c, kind), r)
| _ -> Helper.InstanceCall(args.Head, "charCodeAt", targetType, [makeIntConst 0])
| String, _ -> stringToInt com ctx r targetType args
| Builtin BclBigInt, _ -> Helper.LibCall(com, "BigInt", castBigIntMethod targetType, targetType, args)
| NumberExt typeFrom, NumberExt typeTo ->
Expand Down Expand Up @@ -696,7 +699,12 @@ let applyOp (com: ICompiler) (ctx: Context) r t opName (args: Expr list) argType
Operation(Logical(op, left, right), Boolean, r)
let nativeOp opName argTypes args =
match opName, args with
| Operators.addition, [left; right] -> binOp BinaryPlus left right
| Operators.addition, [left; right] ->
match argTypes with
| Char::_ ->
let toUInt16 e = toInt com ctx None (Number UInt16) [e]
Operation(Binary(BinaryPlus, toUInt16 left, toUInt16 right), Number UInt16, r) |> toChar
| _ -> binOp BinaryPlus left right
| Operators.subtraction, [left; right] -> binOp BinaryMinus left right
| Operators.multiply, [left; right] -> binOp BinaryMultiply left right
| (Operators.division | Operators.divideByInt), [left; right] ->
Expand Down Expand Up @@ -1622,6 +1630,12 @@ let operators (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr o
| "Sign", _ ->
let args = toFloat com ctx r t args |> List.singleton
Helper.LibCall(com, "Util", "sign", t, args, i.SignatureArgTypes, ?loc=r) |> Some
| "DivRem", _ ->
let modName =
match i.SignatureArgTypes with
| Builtin (BclInt64)::_ -> "Long"
| _ -> "Int32"
Helper.LibCall(com, modName, "divRem", t, args, i.SignatureArgTypes, ?loc=r) |> Some
// Numbers
| ("Infinity"|"InfinitySingle"), _ ->
Helper.GlobalIdent("Number", "POSITIVE_INFINITY", t, ?loc=r) |> Some
Expand Down
11 changes: 11 additions & 0 deletions src/fable-library/Int32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,14 @@ export function op_UnaryNegation_Int16(x: number) {
export function op_UnaryNegation_Int32(x: number) {
return x === -2147483648 ? x : -x;
}

export function divRem(x: number, y: number, out?: FSharpRef<number>) {
const div = ~~(x / y);
const rem = x % y;
if (out != null) {
out.contents = rem;
return div;
} else {
return [div, rem];
}
}
11 changes: 11 additions & 0 deletions src/fable-library/Long.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,14 @@ export function ticksToUnixEpochMilliseconds(ticks: Long) {
// }
// };
// }

export function divRem(x: Long, y: Long, out?: FSharpRef<Long>) {
const div = op_Division(x, y);
const rem = op_Modulus(x, y);
if (out != null) {
out.contents = rem;
return div;
} else {
return [div, rem];
}
}
22 changes: 22 additions & 0 deletions tests/Main/ArithmeticTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ let tests =
testCase "Infix modulo can be generated" <| fun () ->
4 % 3 |> equal 1

testCase "Math.DivRem works with ints" <| fun () ->
Math.DivRem(5, 2) |> equal (2, 1)
Math.DivRem(4, 2) |> equal (2, 0)

testCase "Math.DivRem works with ints and ref" <| fun () ->
let rem = ref -1
Math.DivRem(5, 2, rem) |> equal 2
rem.Value |> equal 1
Math.DivRem(4, 2, rem) |> equal 2
rem.Value |> equal 0

testCase "Math.DivRem works with longs" <| fun () ->
Math.DivRem(5L, 2L) |> equal (2L, 1L)
Math.DivRem(4L, 2L) |> equal (2L, 0L)

testCase "Math.DivRem works with longs and ref" <| fun () ->
let rem = ref -1L
Math.DivRem(5L, 2L, rem) |> equal 2L
rem.Value |> equal 1L
Math.DivRem(4L, 2L, rem) |> equal 2L
rem.Value |> equal 0L

testCase "Evaluation order is preserved by generated code" <| fun () ->
(4 - 2) * 2 + 1 |> equal 5

Expand Down
4 changes: 4 additions & 0 deletions tests/Main/CharTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,8 @@ let tests =
|> failwithf "Unexpected result '%c'"
with
| _ -> ()

testCase "Char addition works" <| fun _ ->
'A' + 'B' |> int |> equal 131
'A' + char 7 |> int |> equal 72
]

0 comments on commit a69e20d

Please sign in to comment.