From 9fc8a726af84490a5bee6a3703609f6b562b4e51 Mon Sep 17 00:00:00 2001 From: Nicolas Abril Date: Sat, 15 Jun 2024 19:31:33 +0200 Subject: [PATCH 1/3] Fix pruning of native hvm defs --- src/fun/transform/definition_pruning.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/fun/transform/definition_pruning.rs b/src/fun/transform/definition_pruning.rs index 2270909d..9dcebc83 100644 --- a/src/fun/transform/definition_pruning.rs +++ b/src/fun/transform/definition_pruning.rs @@ -49,8 +49,19 @@ impl Ctx<'_> { } } + fn rm_def(book: &mut Book, def_name: &Name) { + if book.defs.contains_key(def_name) { + book.defs.shift_remove(def_name); + } else if book.hvm_defs.contains_key(def_name) { + book.hvm_defs.shift_remove(def_name); + } else { + unreachable!() + } + } + // Remove unused definitions. - for def in self.book.defs.keys().cloned().collect::>() { + let names = self.book.defs.keys().cloned().chain(self.book.hvm_defs.keys().cloned()).collect::>(); + for def in names { if let Some(use_) = used.get(&def) { match use_ { Used::Main => { @@ -60,7 +71,7 @@ impl Ctx<'_> { // Used by a non-builtin definition. // Prune if `prune_all`, otherwise show a warning. if prune_all { - self.book.defs.shift_remove(&def); + rm_def(self.book, &def); } else { self.info.add_rule_warning("Definition is unused.", WarningType::UnusedDefinition, def); } @@ -69,7 +80,7 @@ impl Ctx<'_> { // Unused, but a user-defined constructor. // Prune if `prune_all`, otherwise nothing. if prune_all { - self.book.defs.shift_remove(&def); + rm_def(self.book, &def); } else { // Don't show warning if it's a user-defined constructor. } @@ -77,7 +88,7 @@ impl Ctx<'_> { } } else { // Unused builtin, can always be pruned. - self.book.defs.shift_remove(&def); + rm_def(self.book, &def); } } } From f8d6d13a249d7a64cef40f428b5aa6359c5bda06 Mon Sep 17 00:00:00 2001 From: Nicolas Abril Date: Sat, 15 Jun 2024 19:32:21 +0200 Subject: [PATCH 2/3] Write log and atan2 as native hvm defs --- docs/builtins.md | 16 ++++++++++++++++ src/fun/builtins.bend | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/builtins.md b/docs/builtins.md index 109c164d..d1ffda39 100644 --- a/docs/builtins.md +++ b/docs/builtins.md @@ -226,3 +226,19 @@ A Natural Number can be written with literals with a `#` before the literal numb ## IO IO Functions are in the **next milestone**! + +## Numeric operations + +### log +```py +def log(x: f24, base: f24) -> f24 +``` +Computes the logarithm of `x` with the specified `base`. + +### atan2 +```py +def atan2(x: f24, y: f24) -> f24 +``` +Computes the arctangent of `y / x`. + +Has the same behaviour as `atan2f` in the C math lib. diff --git a/src/fun/builtins.bend b/src/fun/builtins.bend index 822eef05..21d95372 100644 --- a/src/fun/builtins.bend +++ b/src/fun/builtins.bend @@ -95,7 +95,10 @@ print text = (IO/Call IO/MAGIC "PUT_TEXT" text @x (IO/Done IO/MAGIC x)) #read_file path = (IO/Call IO/MAGIC "GET_FILE" path @x (IO/Done IO/MAGIC x)) #write_file path text = (IO/Call IO/MAGIC "PUT_FILE" (path, text) @x (IO/Done IO/MAGIC x)) +# Returns a monotonically increasing nanosecond timestamp as an u48 encoded as a pair of u24s. get_time = (IO/Call IO/MAGIC "GET_TIME" * @x (IO/Done IO/MAGIC x)) + +# Sleeps for the given number of nanoseconds, given by an u48 encoded as a pair of u24s. sleep hi_lo = (IO/Call IO/MAGIC "PUT_TIME" hi_lo @x (IO/Done IO/MAGIC x)) @@ -110,10 +113,16 @@ defer val = @x (x val) defer_arg defered arg = @x (defered x arg) undefer defered = (defered @x x) -# log :: f24 -> f24 -> f24 + +# Native numeric operations + +# log(x: f24, base: f24) -> f24 # Computes the logarithm of `x` with the specified `base`. -log x base = (| base x) -# atan2 :: f24 -> f24 -> f24 +hvm log: + (x ($([|] $(x ret)) ret)) + +# atan2(x: f24, y: f24) -> f24 # Has the same behaviour as `atan2f` in the C math lib. # Computes the arctangent of the quotient of its two arguments. -atan2 x y = (& x y) +hvm atan2: + ($([&] $(y ret)) (y ret)) From ba8561c3d4dac1327e11551d8b07799fe1a370cc Mon Sep 17 00:00:00 2001 From: Nicolas Abril Date: Sat, 15 Jun 2024 20:51:11 +0200 Subject: [PATCH 3/3] Add native number cast operations --- CHANGELOG.md | 4 +- docs/builtins.md | 18 +++++++ src/fun/builtins.bend | 15 ++++++ src/lib.rs | 6 +-- tests/golden_tests/run_file/hvm_def_cast.bend | 4 +- tests/golden_tests/run_file/num_cast.bend | 48 +++++++++++++++++++ tests/snapshots/run_file__num_cast.bend.snap | 9 ++++ 7 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 tests/golden_tests/run_file/num_cast.bend create mode 100644 tests/snapshots/run_file__num_cast.bend.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index d90b4f46..efa0aae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,9 @@ and this project does not currently adhere to a particular versioning scheme. ### Added -- Add `log` and `atan2` builtin functions. ([#583][gh-583]) - Create new type of top-level definition for writing native HVM definitions. ([#586][gh-586]) +- Add `log` and `atan2` builtin functions. ([#583][gh-583]) +- Add `to_f24`, `to_u24` and `to_i24` number casting builtin functions. ([#582][gh-582]) ## [0.2.35] - 2024-06-06 @@ -340,6 +341,7 @@ and this project does not currently adhere to a particular versioning scheme. [gh-516]: https://github.com/HigherOrderCO/Bend/issues/516 [gh-526]: https://github.com/HigherOrderCO/Bend/issues/526 [gh-528]: https://github.com/HigherOrderCO/Bend/issues/528 +[gh-582]: https://github.com/HigherOrderCO/Bend/issues/582 [gh-583]: https://github.com/HigherOrderCO/Bend/issues/583 [gh-586]: https://github.com/HigherOrderCO/Bend/issues/586 [Unreleased]: https://github.com/HigherOrderCO/Bend/compare/0.2.35...HEAD diff --git a/docs/builtins.md b/docs/builtins.md index d1ffda39..d20dca4d 100644 --- a/docs/builtins.md +++ b/docs/builtins.md @@ -242,3 +242,21 @@ def atan2(x: f24, y: f24) -> f24 Computes the arctangent of `y / x`. Has the same behaviour as `atan2f` in the C math lib. + +### to_f24 +```py +def to_f24(x: any number) -> f24 +``` +Casts any native number to an f24. + +### to_u24 +```py +def to_u24(x: any number) -> u24 +``` +Casts any native number to a u24. + +### to_i24 +```py +def to_i24(x: any number) -> i24 +``` +Casts any native number to an i24. diff --git a/src/fun/builtins.bend b/src/fun/builtins.bend index 21d95372..fd262b3c 100644 --- a/src/fun/builtins.bend +++ b/src/fun/builtins.bend @@ -126,3 +126,18 @@ hvm log: # Computes the arctangent of the quotient of its two arguments. hvm atan2: ($([&] $(y ret)) (y ret)) + +# to_f24(x: native number) -> f24 +# Casts any native number to an f24. +hvm to_f24: + ($([f24] ret) ret) + +# to_u24(x: native number) -> u24 +# Casts any native number to a u24. +hvm to_u24: + ($([u24] ret) ret) + +# to_i24(x: native number) -> i24 +# Casts any native number to an i24. +hvm to_i24: + ($([i24] ret) ret) diff --git a/src/lib.rs b/src/lib.rs index aedaab42..8f361629 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -129,21 +129,21 @@ pub fn desugar_book( ctx.book.make_var_names_unique(); ctx.book.desugar_use(); + ctx.book.make_var_names_unique(); ctx.book.linearize_vars(); // sanity check ctx.check_unbound_vars()?; - // Optimizing passes if opts.float_combinators { ctx.book.float_combinators(MAX_NET_SIZE); } - + // sanity check ctx.check_unbound_refs()?; + // Optimizing passes ctx.prune(opts.prune); - if opts.merge { ctx.book.merge_definitions(); } diff --git a/tests/golden_tests/run_file/hvm_def_cast.bend b/tests/golden_tests/run_file/hvm_def_cast.bend index 0fb66229..eff6aba1 100644 --- a/tests/golden_tests/run_file/hvm_def_cast.bend +++ b/tests/golden_tests/run_file/hvm_def_cast.bend @@ -1,5 +1,5 @@ # Expected +42.0 -hvm to_f24: +hvm to_f24_: ($([f24] a) a) -main = (to_f24 42) \ No newline at end of file +main = (to_f24_ 42) \ No newline at end of file diff --git a/tests/golden_tests/run_file/num_cast.bend b/tests/golden_tests/run_file/num_cast.bend new file mode 100644 index 00000000..cd93d43d --- /dev/null +++ b/tests/golden_tests/run_file/num_cast.bend @@ -0,0 +1,48 @@ +main = +use inf = (** 9.0 (** 9.0 9.0)) +( + (to_u24 0), + (to_u24 1), + (to_u24 123456), + (to_u24 -1), + (to_u24 +1), + (to_u24 +0), + (to_u24 +400), + (to_u24 1.0), + (to_u24 1.5), + (to_u24 -3.0), + (to_u24 -3.5), + (to_u24 inf), # inf + (to_u24 (* -1.0 inf)), # -inf + (to_u24 (/ inf inf)), # nan (inf/inf) + 99999, + (to_i24 0), + (to_i24 1), + (to_i24 123456), + (to_i24 -1), + (to_i24 +1), + (to_i24 +0), + (to_i24 +400), + (to_i24 1.0), + (to_i24 1.5), + (to_i24 -3.0), + (to_i24 -3.5), + (to_i24 inf), # inf + (to_i24 (* -1.0 inf)), # -inf + (to_i24 (/ inf inf)), # nan (inf/inf) + 99999, + (to_f24 0), + (to_f24 1), + (to_f24 123456), + (to_f24 -1), + (to_f24 +1), + (to_f24 +0), + (to_f24 +400), + (to_f24 1.0), + (to_f24 1.5), + (to_f24 -3.0), + (to_f24 -3.5), + (to_f24 inf), # inf + (to_f24 (* -1.0 inf)), # -inf + (to_f24 (/ inf inf)) # nan (inf/inf) +) \ No newline at end of file diff --git a/tests/snapshots/run_file__num_cast.bend.snap b/tests/snapshots/run_file__num_cast.bend.snap new file mode 100644 index 00000000..320e6cb2 --- /dev/null +++ b/tests/snapshots/run_file__num_cast.bend.snap @@ -0,0 +1,9 @@ +--- +source: tests/golden_tests.rs +input_file: tests/golden_tests/run_file/num_cast.bend +--- +NumScott: +(0, (1, (123456, (16777215, (1, (0, (400, (1, (1, (0, (0, (16777215, (0, (0, (99999, (+0, (+1, (+123456, (-1, (+1, (+0, (+400, (+1, (+1, (-3, (-3, (+8388607, (-8388608, (+0, (99999, (0.000, (1.000, (123456.000, (-1.000, (1.000, (0.000, (400.000, (1.000, (1.500, (-3.000, (-3.500, (inf, (-inf, NaN))))))))))))))))))))))))))))))))))))))))))) + +Scott: +(0, (1, (123456, (16777215, (1, (0, (400, (1, (1, (0, (0, (16777215, (0, (0, (99999, (+0, (+1, (+123456, (-1, (+1, (+0, (+400, (+1, (+1, (-3, (-3, (+8388607, (-8388608, (+0, (99999, (0.000, (1.000, (123456.000, (-1.000, (1.000, (0.000, (400.000, (1.000, (1.500, (-3.000, (-3.500, (inf, (-inf, NaN)))))))))))))))))))))))))))))))))))))))))))