From 2ca5ed5f4674a86b2e6fbf855bf5ee69cc043663 Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Thu, 9 Feb 2023 13:52:00 +0100 Subject: [PATCH 1/5] Allow implicit int to float conversion. --- src/lang/builtins_math.ml | 3 ++- src/lang/lang_core.ml | 8 +++++++- src/lang/types/ground_type.ml | 28 ++++++++++++++++++++++------ tests/language/casting.liq | 17 +++++++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100755 tests/language/casting.liq diff --git a/src/lang/builtins_math.ml b/src/lang/builtins_math.ml index 79d564e3ac..d5dea35998 100644 --- a/src/lang/builtins_math.ml +++ b/src/lang/builtins_math.ml @@ -86,7 +86,8 @@ let () = match (a, b) with | `Int a, `Int b -> Lang.int (op_int a b) | `Float a, `Float b -> Lang.float (op_float a b) - | _ -> assert false)) + | `Int a, `Float b -> Lang.float (op_float (float a) b) + | `Float a, `Int b -> Lang.float (op_float a (float b)))) in register_op "Multiplication" "*" ( * ) ( *. ); register_op "Division" "/" ( / ) ( /. ); diff --git a/src/lang/lang_core.ml b/src/lang/lang_core.ml index 11f252b2bf..54ad50b467 100644 --- a/src/lang/lang_core.ml +++ b/src/lang/lang_core.ml @@ -292,11 +292,17 @@ let to_string_getter t = | _ -> assert false let to_float t = - match (demeth t).value with Ground (Float s) -> s | _ -> assert false + match (demeth t).value with + | Ground (Float s) -> s + | Ground (Int n) -> float_of_int n + | _ -> assert false let to_float_getter t = match (demeth t).value with | Ground (Float s) -> fun () -> s + | Ground (Int n) -> + let n = float_of_int n in + fun () -> n | Fun _ | FFI _ -> ( fun () -> match (apply t []).value with diff --git a/src/lang/types/ground_type.ml b/src/lang/types/ground_type.ml index 98e08feac0..fdb084ec11 100644 --- a/src/lang/types/ground_type.ml +++ b/src/lang/types/ground_type.ml @@ -37,6 +37,7 @@ module Make (S : Spec) = struct type Type_base.custom += Type let () = types := Type :: !types + let typ = Type let get = function Type -> Type | _ -> assert false let is_descr = function @@ -74,18 +75,33 @@ module Make (S : Spec) = struct Type_base.make (Type_base.Custom handler)) end -module Int = Make (struct - let name = "int" -end) - -let int = Int.descr - module Float = Make (struct let name = "float" end) let float = Float.descr +module Int = struct + module Int = Make (struct + let name = "int" + end) + + include Int + + (* Add int <: float subtyping. *) + let handler = + let subtype _ _ c = assert (c = Int.typ || c = Float.typ) in + { handler with subtype } + + let descr = Type_base.Custom handler + + let () = + Type_base.register_type "int" (fun () -> + Type_base.make (Type_base.Custom handler)) +end + +let int = Int.descr + module String = Make (struct let name = "string" end) diff --git a/tests/language/casting.liq b/tests/language/casting.liq new file mode 100755 index 0000000000..d9de965434 --- /dev/null +++ b/tests/language/casting.liq @@ -0,0 +1,17 @@ +#!../../liquidsoap ../test.liq + +def t(x, y) + if x != y then + print("Failure: got #{x} instead of #{y}") + test.fail() + end +end + +def f() = + def double(x) = 2. * x end + + t(double(3), 6.) + test.pass() +end + +test.check(f) From d62a967fa6a737891e5afb891680099708dcc818 Mon Sep 17 00:00:00 2001 From: Romain Beauxis Date: Thu, 9 Feb 2023 08:20:51 -0600 Subject: [PATCH 2/5] Added more tests. --- tests/language/casting.liq | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/language/casting.liq b/tests/language/casting.liq index d9de965434..6e026a7751 100755 --- a/tests/language/casting.liq +++ b/tests/language/casting.liq @@ -7,10 +7,58 @@ def t(x, y) end end +def incorrect(expr) + print("Incorrect expression #{expr}...\n") + + try + let eval _ = expr + test.fail() + catch err do + print("Got err: #{err}") + end + + print("\n") +end + def f() = def double(x) = 2. * x end t(double(3), 6.) + + ignore(if false then 1. else 2 end) + + incorrect("if false then 1 else 2. end") + + def f(l) = + l = [1, ...l] + l = [2., ...l] + l + end + + incorrect(" + def f(l) = + l = [2., ...l] + l = [1, ...l] + l + end + ") + + def f(l) = + let [x] = l + ignore(x + 2.) + let [x] = l + ignore(x + 1) + end + + incorrect(" + def f(l) = + let [x] = l + ignore(x + 1) + let [x] = l + ignore(x + 2.) + end + ") + test.pass() end From 78be62b60b62a34231b9ebdfa68f41bc4d7e6171 Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Thu, 9 Feb 2023 15:56:58 +0100 Subject: [PATCH 3/5] Changelog entry. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 41dde46b9b..80fcfcda65 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -79,6 +79,7 @@ Changed: - Added `settings.protocol.youtube_dl.timeout` to specify timeout when using `youtube-dl` protocol (#2827). Use `yt-dlp` as default binary for the protocol. +- Allow implicit casting of an integer as a float (#2887). Fixed: From 6137f512ecb02e7720eaf569e13f95850cca4aa0 Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Wed, 15 Feb 2023 08:12:37 +0100 Subject: [PATCH 4/5] Fix test. --- tests/core/meth.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/meth.ml b/tests/core/meth.ml index bfa5aaedb8..28f078e648 100644 --- a/tests/core/meth.ml +++ b/tests/core/meth.ml @@ -34,12 +34,12 @@ let () = (* Test subtyping. *) let () = (* Make sure unifying variables sees top-level methods: - We do: t = ('a).{ f : int } <: t' = int.{ ff : int, f : float } + We do: t = ('a).{ f : int } <: t' = int.{ ff : int, f : string } and make sure that this fails. *) let t = Type.var () in let t = Type.meth "f" ([], Type.make Type.Ground.int) t in let t' = Type.make Type.Ground.int in - let t' = Type.meth "f" ([], Type.make Type.Ground.float) t' in + let t' = Type.meth "f" ([], Type.make Type.Ground.string) t' in let t' = Type.meth "ff" ([], Type.make Type.Ground.int) t' in assert ( try From bd4763e3b6b6bd15558708271f0277f3354011ee Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Sun, 26 Feb 2023 12:40:18 +0100 Subject: [PATCH 5/5] Document. --- doc/content/language.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/content/language.md b/doc/content/language.md index 6b9705a329..9588570f11 100644 --- a/doc/content/language.md +++ b/doc/content/language.md @@ -74,6 +74,9 @@ so that `3` and `3.` are not the same thing: the former is an integer and the latter is a float. This is a source of errors for beginners, but is necessary for typing to work well. +Since version 2.2 of Liquidsoap, you can use an integer where a float is +expected, for instance you can type `sin(3)` instead of `sin(3.)`. + ### Strings Strings are written between double or single quotes,