Skip to content

Commit

Permalink
More char conversion tests (#4057)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave authored Feb 19, 2025
1 parent 8e69e80 commit f486eb2
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 160 deletions.
70 changes: 36 additions & 34 deletions src/Fable.Transforms/Dart/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -72,37 +72,6 @@ let makeDecimal com r t (x: decimal) =
let makeDecimalFromExpr com r t (e: Expr) =
Helper.LibCall(com, "Decimal", "default", t, [ e ], isConstructor = true, ?loc = r)

let toChar (arg: Expr) =
match arg.Type with
// TODO: Check length
| String -> Helper.InstanceCall(arg, "codeUnitAt", Char, [ makeIntConst 0 ])
| Char -> arg
| _ -> TypeCast(arg, Char)

let charToString =
function
| Value(CharConstant v, r) -> Value(StringConstant(string<char> v), r)
| e -> Helper.GlobalCall("String", String, [ e ], memb = "fromCharCode")

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| String -> head
| Char -> charToString head
// | Builtin BclGuid when tail.IsEmpty -> head
// | Builtin (BclGuid|BclTimeSpan|BclTimeOnly|BclDateOnly as bt) ->
// Helper.LibCall(com, coreModFor bt, "toString", String, args)
// | Number(Int16,_) -> Helper.LibCall(com, "Util", "int16ToString", String, args)
// | Number(Int32,_) -> Helper.LibCall(com, "Util", "int32ToString", String, args)
// | Number((Int64|UInt64),_) -> Helper.LibCall(com, "Long", "toString", String, args)
// | Number(BigInt,_) -> Helper.LibCall(com, "BigInt", "toString", String, args)
// | Number(Decimal,_) -> Helper.LibCall(com, "Decimal", "toString", String, args)
| _ -> Helper.InstanceCall(head, "toString", String, tail)

let getParseParams (kind: NumberKind) =
let isFloatOrDecimal, numberModule, unsigned, bitsize =
match kind with
Expand Down Expand Up @@ -254,6 +223,37 @@ let toInt com (ctx: Context) r targetType (args: Expr list) =

TypeCast(arg, targetType)

let toChar com (ctx: Context) r (arg: Expr) =
match arg.Type with
// TODO: Check length
| Char -> arg
| String -> Helper.InstanceCall(arg, "codeUnitAt", Char, [ makeIntConst 0 ])
| _ -> TypeCast(arg, Char)

let charToString =
function
| Value(CharConstant v, r) -> Value(StringConstant(string<char> v), r)
| e -> Helper.GlobalCall("String", String, [ e ], memb = "fromCharCode")

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| String -> head
| Char -> charToString head
// | Builtin BclGuid when tail.IsEmpty -> head
// | Builtin (BclGuid|BclTimeSpan|BclTimeOnly|BclDateOnly as bt) ->
// Helper.LibCall(com, coreModFor bt, "toString", String, args)
// | Number(Int16,_) -> Helper.LibCall(com, "Util", "int16ToString", String, args)
// | Number(Int32,_) -> Helper.LibCall(com, "Util", "int32ToString", String, args)
// | Number((Int64|UInt64),_) -> Helper.LibCall(com, "Long", "toString", String, args)
// | Number(BigInt,_) -> Helper.LibCall(com, "BigInt", "toString", String, args)
// | Number(Decimal,_) -> Helper.LibCall(com, "Decimal", "toString", String, args)
| _ -> Helper.InstanceCall(head, "toString", String, tail)

let round com (args: Expr list) =
match args.Head.Type with
| Number(Decimal, _) ->
Expand Down Expand Up @@ -297,7 +297,7 @@ let applyOp (com: ICompiler) (ctx: Context) r t opName (args: Expr list) =
toInt com ctx None (Number(UInt16, NumberInfo.Empty)) [ e ]

Operation(Binary(op, toUInt16 left, toUInt16 right), Tags.empty, UInt16.Number, r)
|> toChar
|> toChar com ctx r

let truncateUnsigned operation = // see #1550
match t with
Expand Down Expand Up @@ -976,7 +976,7 @@ let operators (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr o
_ -> toInt com ctx r t args |> Some
| ("ToSingle" | "ToDouble"), _ -> toFloat com ctx r t args |> Some
| "ToDecimal", _ -> toDecimal com ctx r t args |> Some
| "ToChar", _ -> toChar args.Head |> Some
| "ToChar", _ -> toChar com ctx r args.Head |> Some
| "ToString", _ -> toString com ctx r args |> Some
| "CreateSequence", [ xs ] -> TypeCast(xs, t) |> Some
| ("CreateDictionary" | "CreateReadOnlyDictionary"), [ arg ] ->
Expand Down Expand Up @@ -2194,6 +2194,7 @@ let decimals (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
_ -> applyOp com ctx r t i.CompiledName args |> Some
| "op_Explicit", _ ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| Int8
Expand Down Expand Up @@ -2261,6 +2262,7 @@ let bigints (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
|> Some
| None, "op_Explicit" ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| Int8
Expand Down Expand Up @@ -2677,7 +2679,7 @@ let convert (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr option) (
| "ToSingle"
| "ToDouble" -> toFloat com ctx r t args |> Some
| "ToDecimal" -> toDecimal com ctx r t args |> Some
| "ToChar" -> toChar args.Head |> Some
| "ToChar" -> toChar com ctx r args.Head |> Some
| "ToString" -> toString com ctx r args |> Some
| "ToBase64String"
| "FromBase64String" ->
Expand Down
72 changes: 38 additions & 34 deletions src/Fable.Transforms/Python/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -138,37 +138,6 @@ let makeRefFromMutableFunc com ctx r t (value: Expr) =
let makeEqOpStrict range left right op =
Operation(Binary(op, left, right), [ "strict" ], Boolean, range)

let toChar (arg: Expr) =
match arg.Type with
| Char
| String -> arg
| _ -> Helper.GlobalCall("chr", Char, [ arg ])

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| Char -> TypeCast(head, String)
| String -> head
| Builtin BclGuid when tail.IsEmpty -> Helper.GlobalCall("str", String, [ head ], ?loc = r)
| Builtin(BclGuid | BclTimeSpan as bt) -> Helper.LibCall(com, coreModFor bt, "toString", String, args)
| Number((Int64 | UInt64 | BigInt), _) -> Helper.LibCall(com, "util", "int64_to_string", String, args)
| Number(Int8, _)
| Number(UInt8, _) -> Helper.LibCall(com, "util", "int8_to_string", String, args)
| Number(Int16, _) -> Helper.LibCall(com, "util", "int16_to_string", String, args)
| Number(Int32, _) -> Helper.LibCall(com, "util", "int32_to_string", String, args)
| Number(Decimal, _) -> Helper.LibCall(com, "decimal", "toString", String, args)
| Number _ -> Helper.LibCall(com, "types", "toString", String, [ head ], ?loc = r)
| Array _
| List _ -> Helper.LibCall(com, "types", "seqToString", String, [ head ], ?loc = r)
// | DeclaredType(ent, _) when ent.IsFSharpUnion || ent.IsFSharpRecord || ent.IsValueType ->
// Helper.InstanceCall(head, "toString", String, [], ?loc=r)
// | DeclaredType(ent, _) ->
| _ -> Helper.LibCall(com, "types", "toString", String, [ head ], ?loc = r)

let getParseParams (kind: NumberKind) =
let isFloatOrDecimal, numberModule, unsigned, bitsize =
match kind with
Expand Down Expand Up @@ -357,6 +326,39 @@ let toInt com (ctx: Context) r targetType (args: Expr list) =
addWarning com ctx.InlinePath r "Cannot make conversion because source type is unknown"
TypeCast(args.Head, targetType)

let toChar com (ctx: Context) r (arg: Expr) =
match arg.Type with
| Char
| String -> arg
| _ ->
let code = toInt com ctx r UInt16.Number [ arg ]
Helper.GlobalCall("chr", Char, [ code ])

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| Char -> TypeCast(head, String)
| String -> head
| Builtin BclGuid when tail.IsEmpty -> Helper.GlobalCall("str", String, [ head ], ?loc = r)
| Builtin(BclGuid | BclTimeSpan as bt) -> Helper.LibCall(com, coreModFor bt, "toString", String, args)
| Number((Int64 | UInt64 | BigInt), _) -> Helper.LibCall(com, "util", "int64_to_string", String, args)
| Number(Int8, _)
| Number(UInt8, _) -> Helper.LibCall(com, "util", "int8_to_string", String, args)
| Number(Int16, _) -> Helper.LibCall(com, "util", "int16_to_string", String, args)
| Number(Int32, _) -> Helper.LibCall(com, "util", "int32_to_string", String, args)
| Number(Decimal, _) -> Helper.LibCall(com, "decimal", "toString", String, args)
| Number _ -> Helper.LibCall(com, "types", "toString", String, [ head ], ?loc = r)
| Array _
| List _ -> Helper.LibCall(com, "types", "seqToString", String, [ head ], ?loc = r)
// | DeclaredType(ent, _) when ent.IsFSharpUnion || ent.IsFSharpRecord || ent.IsValueType ->
// Helper.InstanceCall(head, "toString", String, [], ?loc=r)
// | DeclaredType(ent, _) ->
| _ -> Helper.LibCall(com, "types", "toString", String, [ head ], ?loc = r)

let round com (args: Expr list) =
match args.Head.Type with
| Number(Decimal, _) ->
Expand Down Expand Up @@ -393,7 +395,7 @@ let applyOp (com: ICompiler) (ctx: Context) r t opName (args: Expr list) =
let toUInt16 e = toInt com ctx None UInt16.Number [ e ]

Operation(Binary(op, toUInt16 left, toUInt16 right), Tags.empty, UInt16.Number, r)
|> toChar
|> toChar com ctx r

let truncateUnsigned operation = // see #1550
match t with
Expand Down Expand Up @@ -1051,7 +1053,7 @@ let operators (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr o
| "ToUInt64", _ -> toLong com ctx r true t args |> Some
| ("ToSingle" | "ToDouble"), _ -> toFloat com ctx r t args |> Some
| "ToDecimal", _ -> toDecimal com ctx r t args |> Some
| "ToChar", _ -> toChar args.Head |> Some
| "ToChar", _ -> toChar com ctx r args.Head |> Some
| "ToString", _ -> toString com ctx r args |> Some
| "CreateSequence", [ xs ] -> toSeq t xs |> Some
| ("CreateDictionary" | "CreateReadOnlyDictionary"), [ arg ] -> makeDictionary com ctx r t arg |> Some
Expand Down Expand Up @@ -2105,6 +2107,7 @@ let decimals (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
_ -> applyOp com ctx r t i.CompiledName args |> Some
| "op_Explicit", _ ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| Int64 -> toLong com ctx r false t args |> Some
Expand Down Expand Up @@ -2163,6 +2166,7 @@ let bigints (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
|> Some
| None, "op_Explicit" ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| Int64 -> toLong com ctx r false t args |> Some
Expand Down Expand Up @@ -2532,7 +2536,7 @@ let convert (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr option) (
| "ToSingle"
| "ToDouble" -> toFloat com ctx r t args |> Some
| "ToDecimal" -> toDecimal com ctx r t args |> Some
| "ToChar" -> toChar args.Head |> Some
| "ToChar" -> toChar com ctx r args.Head |> Some
| "ToString" -> toString com ctx r args |> Some
| "ToBase64String"
| "FromBase64String" ->
Expand Down
78 changes: 41 additions & 37 deletions src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -155,39 +155,6 @@ let makeRefFromMutableFunc com ctx r t (value: Expr) =

makeRefCell com r t [ getter; setter ]

let toChar com (ctx: Context) r targetType (arg: Expr) =
match arg.Type with
| Char -> arg
| String -> TypeCast(arg, Char)
| Number(Decimal, _) -> Helper.LibCall(com, "Decimal", "toChar", Char, [ arg ], ?loc = r)
| _ -> Helper.GlobalCall("String", Char, [ arg ], memb = "fromCharCode")

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| String -> head
| Char -> TypeCast(head, String)
| Builtin BclGuid when tail.IsEmpty -> head
| Builtin(BclGuid | BclTimeSpan | BclTimeOnly | BclDateOnly as bt) ->
Helper.LibCall(com, coreModFor bt, "toString", String, args)
| Number(Int16, _) -> Helper.LibCall(com, "Util", "int16ToString", String, args)
| Number(Int32, _) -> Helper.LibCall(com, "Util", "int32ToString", String, args)
| Number(Int64, _) -> Helper.LibCall(com, "Util", "int64ToString", String, args)
| Number(NativeInt, _) -> Helper.LibCall(com, "Util", "int64ToString", String, args)
| Number(BigInt, _) -> Helper.LibCall(com, "BigInt", "toString", String, args)
| Number(Decimal, _) -> Helper.LibCall(com, "Decimal", "toString", String, args)
| Number _ -> Helper.InstanceCall(head, "toString", String, tail)
| Array _
| List _ -> Helper.LibCall(com, "Types", "seqToString", String, [ head ], ?loc = r)
// | DeclaredType(ent, _) when ent.IsFSharpUnion || ent.IsFSharpRecord || ent.IsValueType ->
// Helper.InstanceCall(head, "toString", String, [], ?loc=r)
// | DeclaredType(ent, _) ->
| _ -> Helper.LibCall(com, "Types", "toString", String, [ head ], ?loc = r)

let getParseParams (kind: NumberKind) =
let isFloatOrDecimal, numberModule, unsigned, bitsize =
match kind with
Expand Down Expand Up @@ -354,6 +321,42 @@ let toInt com (ctx: Context) r targetType (args: Expr list) =
addWarning com ctx.InlinePath r "Cannot make conversion because source type is unknown"
TypeCast(args.Head, targetType)

let toChar com (ctx: Context) r (arg: Expr) =
match arg.Type with
| Char -> arg
| String -> TypeCast(arg, Char)
| Number(BigInt, _) -> Helper.LibCall(com, "BigInt", "toChar", Char, [ arg ], ?loc = r)
| Number(Decimal, _) -> Helper.LibCall(com, "Decimal", "toChar", Char, [ arg ], ?loc = r)
| _ ->
let code = toInt com ctx r UInt16.Number [ arg ]
Helper.GlobalCall("String", Char, [ code ], memb = "fromCharCode")

let toString com (ctx: Context) r (args: Expr list) =
match args with
| [] ->
"toString is called with empty args"
|> addErrorAndReturnNull com ctx.InlinePath r
| head :: tail ->
match head.Type with
| String -> head
| Char -> TypeCast(head, String)
| Builtin BclGuid when tail.IsEmpty -> head
| Builtin(BclGuid | BclTimeSpan | BclTimeOnly | BclDateOnly as bt) ->
Helper.LibCall(com, coreModFor bt, "toString", String, args)
| Number(Int16, _) -> Helper.LibCall(com, "Util", "int16ToString", String, args)
| Number(Int32, _) -> Helper.LibCall(com, "Util", "int32ToString", String, args)
| Number(Int64, _) -> Helper.LibCall(com, "Util", "int64ToString", String, args)
| Number(NativeInt, _) -> Helper.LibCall(com, "Util", "int64ToString", String, args)
| Number(BigInt, _) -> Helper.LibCall(com, "BigInt", "toString", String, args)
| Number(Decimal, _) -> Helper.LibCall(com, "Decimal", "toString", String, args)
| Number _ -> Helper.InstanceCall(head, "toString", String, tail)
| Array _
| List _ -> Helper.LibCall(com, "Types", "seqToString", String, [ head ], ?loc = r)
// | DeclaredType(ent, _) when ent.IsFSharpUnion || ent.IsFSharpRecord || ent.IsValueType ->
// Helper.InstanceCall(head, "toString", String, [], ?loc=r)
// | DeclaredType(ent, _) ->
| _ -> Helper.LibCall(com, "Types", "toString", String, [ head ], ?loc = r)

let round com (args: Expr list) =
match args.Head.Type with
| Number(Decimal, _) ->
Expand Down Expand Up @@ -381,7 +384,7 @@ let applyOp (com: ICompiler) (ctx: Context) r t opName (args: Expr list) =
let toUInt16 e = toInt com ctx None UInt16.Number [ e ]

Operation(Binary(op, toUInt16 left, toUInt16 right), Tags.empty, UInt16.Number, r)
|> toChar com ctx r t
|> toChar com ctx r

let truncateUnsigned operation = // see #1550
match t with
Expand Down Expand Up @@ -1217,7 +1220,7 @@ let operators (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr o
| ("ToInt64" | "ToUInt64" | "ToIntPtr" | "ToUIntPtr"), _ -> toLong com ctx r t args |> Some
| ("ToSingle" | "ToDouble"), _ -> toFloat com ctx r t args |> Some
| "ToDecimal", _ -> toDecimal com ctx r t args |> Some
| "ToChar", _ -> toChar com ctx r t args.Head |> Some
| "ToChar", _ -> toChar com ctx r args.Head |> Some
| "ToString", _ -> toString com ctx r args |> Some
| "CreateSequence", [ xs ] -> TypeCast(xs, t) |> Some
| ("CreateDictionary" | "CreateReadOnlyDictionary"), [ arg ] -> makeDictionary com ctx r t arg |> Some
Expand Down Expand Up @@ -2455,14 +2458,14 @@ let decimals (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
_ -> applyOp com ctx r t i.CompiledName args |> Some
| "op_Explicit", _ ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| BigIntegers _ -> toLong com ctx r t args |> Some
| Integers _ -> toInt com ctx r t args |> Some
| Floats _ -> toFloat com ctx r t args |> Some
| Decimal -> toDecimal com ctx r t args |> Some
| _ -> None
| Char -> toChar com ctx r t args.Head |> Some
| _ -> None
| ("Ceiling" | "Floor" | "Round" | "Truncate" | "Min" | "Max" | "MinMagnitude" | "MaxMagnitude" | "Clamp" | "Add" | "Subtract" | "Multiply" | "Divide" | "Remainder" | "Negate" as meth),
_ ->
Expand Down Expand Up @@ -2502,6 +2505,7 @@ let bigints (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg:
| _ -> None
| "op_Explicit", None ->
match t with
| Char -> toChar com ctx r args.Head |> Some
| Number(kind, _) ->
match kind with
| BigIntegers _ -> toLong com ctx r t args |> Some
Expand Down Expand Up @@ -2927,7 +2931,7 @@ let convert (com: ICompiler) (ctx: Context) r t (i: CallInfo) (_: Expr option) (
| "ToSingle"
| "ToDouble" -> toFloat com ctx r t args |> Some
| "ToDecimal" -> toDecimal com ctx r t args |> Some
| "ToChar" -> toChar com ctx r t args.Head |> Some
| "ToChar" -> toChar com ctx r args.Head |> Some
| "ToString" -> toString com ctx r args |> Some
| "ToBase64String"
| "FromBase64String" ->
Expand Down
Loading

0 comments on commit f486eb2

Please sign in to comment.