Fork of daniellemaywood.uk/gleam — Wasm codegen work
Something went wrong. Try again.
6.7 kB · 431 lines
Rust
at wasm
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432// SPDX-License-Identifier: Apache-2.0// SPDX-FileCopyrightText: 2025 The Gleam contributors
use crate::assert_js;
const BOOL_MODULE: &str = "pub fn guard( when condition: Bool, return value: a, otherwise callback: fn() -> a,) -> a { case condition { True -> value False -> callback() }}
pub fn lazy_guard( when condition: Bool, return consequence: fn() -> a, otherwise alternative: fn() -> a,) -> a { case condition { True -> consequence() False -> alternative() }}";
const RESULT_MODULE: &str = "pub fn try(result: Result(a, e), apply f: fn(a) -> Result(b, e)) -> Result(b, e) { case result { Ok(value) -> f(value) Error(error) -> Error(error) }}
pub fn map(over result: Result(a, e), with f: fn(a) -> b) -> Result(b, e) { case result { Ok(value) -> Ok(f(value)) Error(error) -> Error(error) }}";
#[test]fn inline_higher_order_function() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), "import gleam/result
pub fn main() { result.map(over: Ok(10), with: double)}
fn double(x) { x + x }" );}
#[test]fn inline_higher_order_function_with_capture() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), "import gleam/result
pub fn main() { result.try(Ok(10), divide(_, 2))}
fn divide(a: Int, b: Int) -> Result(Int, Nil) { case a % b { 0 -> Ok(a / b) _ -> Error(Nil) }}" );}
#[test]fn inline_higher_order_function_anonymous() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), "import gleam/result
pub fn main() { result.try(Ok(10), fn(value) { Ok({ value + 2 } * 4) })}" );}
#[test]fn inline_function_which_calls_other_function() { // This function calls `result.try`, meaning this must be inlined twice to // achieve the desired result. assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), ( "gleam_stdlib", "testing", "import gleam/result.{try}
pub fn always_inline(result, f) -> Result(b, e) { try(result, f)}" ), "import testing
pub fn main() { testing.always_inline(Ok(10), Error)}" );}
#[test]fn inline_function_with_use() { assert_js!( ("gleam_stdlib", "gleam/bool", BOOL_MODULE), "import gleam/bool
pub fn divide(a, b) { use <- bool.guard(when: b == 0, return: 0) a / b}" );}
#[test]fn inline_function_with_use_and_anonymous() { assert_js!( ("gleam_stdlib", "gleam/bool", BOOL_MODULE), r#"import gleam/bool
pub fn divide(a, b) { use <- bool.lazy_guard(b == 0, fn() { panic as "Cannot divide by 0" }) a / b}"# );}
#[test]fn inline_function_with_use_becomes_tail_recursive() { assert_js!( ("gleam_stdlib", "gleam/bool", BOOL_MODULE), "import gleam/bool
pub fn count(from: Int, to: Int) -> Int { use <- bool.guard(when: from >= to, return: from) echo from count(from + 1, to)}" );}
#[test]fn do_not_inline_parameters_used_more_than_once() { // Since the `something` parameter is used more than once in the body of the // function, it should not be inlined, and should be assigned once at the // beginning of the function. assert_js!( ( "gleam_stdlib", "testing", "pub fn always_inline(something) { case something { True -> something False -> False }}" ), "import testing
pub fn main() { testing.always_inline(True)}" );}
#[test]fn do_not_inline_parameters_that_have_side_effects() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), r#"import gleam/result
pub fn main() { result.map(Ok(10), do_side_effects())}
fn do_side_effects() { let function = fn(x) { x + 1 } panic as "Side effects" function}"# );}
#[test]fn inline_anonymous_function_call() { assert_js!( "pub fn main() { fn(a, b) { #(a, b) }(42, False)}" );}
#[test]fn inline_anonymous_function_in_pipe() { assert_js!( "pub fn main() { 1 |> fn(x) { x + 1 } |> fn(y) { y * y }}" );}
#[test]fn inline_function_capture_in_pipe() { // The function capture is desugared to an anonymous function, so it should // be turned into a direct call to `add` assert_js!( "pub fn main() { 1 |> add(4, _)}
fn add(a, b) { a + b }" );}
#[test]fn inlining_works_through_blocks() { assert_js!( "pub fn main() { { fn(x) { Ok(x + 1) } }(41)}" );}
#[test]fn blocks_get_preserved_when_needed() { assert_js!( "pub fn main() { { 4 |> make_adder }(6)}
fn make_adder(a) { fn(b) { a + b }}" );}
#[test]fn blocks_get_preserved_when_needed2() { assert_js!( "pub fn main() { fn(x) { 1 + x }(2) * 3}" );}
#[test]fn parameters_from_nested_functions_are_correctly_inlined() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), "import gleam/result
pub fn halve_all(a, b, c) { use x <- result.try(divide(a, 2)) use y <- result.try(divide(b, 2)) use z <- result.map(divide(c, 2))
#(x, y, z)}
fn divide(a, b) { case a % b { 0 -> Ok(a / b) _ -> Error(Nil) }}" );}
// https://github.com/gleam-lang/gleam/issues/4852#[test]fn inlining_works_properly_with_record_updates() { assert_js!( ("gleam_stdlib", "gleam/result", RESULT_MODULE), "import gleam/result
pub type Wibble { Wibble(a: Int, b: Int)}
pub fn main() { let w = Wibble(1, 2) use b <- result.map(Ok(3)) Wibble(..w, b:)}" );}
// https://github.com/gleam-lang/gleam/issues/4877#[test]fn inline_shadowed_variable() { assert_js!( "pub fn main() { let a = 10 let b = 20
fn(x) { let a = 7 x + a }(a + b)
a}" );}
#[test]fn inline_variable_shadowing_parameter() { assert_js!( "pub fn sum(a, b) { fn(x) { let a = 7 x + a }(a + b)
a}" );}
#[test]fn inline_shadowed_variable_nested() { assert_js!( "pub fn sum(a, b) { fn(x) { let a = 7 fn(y) { let a = 10 y - a }(x + a)
a }(a + b)
a}" );}
#[test]fn inline_variable_shadowed_in_case_pattern() { assert_js!( "pub fn sum() { let a = 10 let b = 20
fn(x) { case 7, 8 { a, b -> a + b + x } }(a + b)
a + b}" );}
#[test]fn inline_variable_shadowing_case_pattern() { assert_js!( "pub fn sum() { case 1, 2 { a, b -> fn(x) { let a = 7 x + a }(a + b) }}" );}