Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / erlang / tests / inlining.rs
4.5 kB 269 lines
1use crate::assert_erl; 2 3const BOOL_MODULE: &str = " 4pub fn guard( 5 when condition: Bool, 6 return value: a, 7 otherwise callback: fn() -> a, 8) -> a { 9 case condition { 10 True -> value 11 False -> callback() 12 } 13} 14 15pub fn lazy_guard( 16 when condition: Bool, 17 return consequence: fn() -> a, 18 otherwise alternative: fn() -> a, 19) -> a { 20 case condition { 21 True -> consequence() 22 False -> alternative() 23 } 24} 25"; 26 27const RESULT_MODULE: &str = " 28pub fn try(result: Result(a, e), apply f: fn(a) -> Result(b, e)) -> Result(b, e) { 29 case result { 30 Ok(value) -> f(value) 31 Error(error) -> Error(error) 32 } 33} 34 35pub fn then(result: Result(a, e), apply f: fn(a) -> Result(b, e)) -> Result(b, e) { 36 try(result, f) 37} 38 39pub fn map(over result: Result(a, e), with f: fn(a) -> b) -> Result(b, e) { 40 case result { 41 Ok(value) -> Ok(f(value)) 42 Error(error) -> Error(error) 43 } 44} 45"; 46 47#[test] 48fn inline_higher_order_function() { 49 assert_erl!( 50 ("gleam_stdlib", "gleam/result", RESULT_MODULE), 51 " 52import gleam/result 53 54pub fn main() { 55 result.map(over: Ok(10), with: double) 56} 57 58fn double(x) { x + x } 59" 60 ); 61} 62 63#[test] 64fn inline_higher_order_function_with_capture() { 65 assert_erl!( 66 ("gleam_stdlib", "gleam/result", RESULT_MODULE), 67 " 68import gleam/result 69 70pub fn main() { 71 result.try(Ok(10), divide(_, 2)) 72} 73 74fn divide(a: Int, b: Int) -> Result(Int, Nil) { 75 case a % b { 76 0 -> Ok(a / b) 77 _ -> Error(Nil) 78 } 79} 80" 81 ); 82} 83 84#[test] 85fn inline_higher_order_function_anonymous() { 86 assert_erl!( 87 ("gleam_stdlib", "gleam/result", RESULT_MODULE), 88 " 89import gleam/result 90 91pub fn main() { 92 result.try(Ok(10), fn(value) { 93 Ok({ value + 2 } * 4) 94 }) 95} 96" 97 ); 98} 99 100#[test] 101fn inline_function_which_calls_other_function() { 102 // `result.then` calls `result.try`, meaning this must be inlined twice to 103 // achieve the desired result. 104 assert_erl!( 105 ("gleam_stdlib", "gleam/result", RESULT_MODULE), 106 " 107import gleam/result 108 109pub fn main() { 110 result.then(Ok(10), Error) 111} 112" 113 ); 114} 115 116#[test] 117fn inline_function_with_use() { 118 assert_erl!( 119 ("gleam_stdlib", "gleam/bool", BOOL_MODULE), 120 " 121import gleam/bool 122 123pub fn divide(a, b) { 124 use <- bool.guard(when: b == 0, return: 0) 125 a / b 126} 127" 128 ); 129} 130 131#[test] 132fn inline_function_with_use_and_anonymous() { 133 assert_erl!( 134 ("gleam_stdlib", "gleam/bool", BOOL_MODULE), 135 r#" 136import gleam/bool 137 138pub fn divide(a, b) { 139 use <- bool.lazy_guard(b == 0, fn() { panic as "Cannot divide by 0" }) 140 a / b 141} 142"# 143 ); 144} 145 146#[test] 147fn inline_function_with_use_becomes_tail_recursive() { 148 assert_erl!( 149 ("gleam_stdlib", "gleam/bool", BOOL_MODULE), 150 " 151import gleam/bool 152 153pub fn count(from: Int, to: Int) -> Int { 154 use <- bool.guard(when: from >= to, return: from) 155 echo from 156 count(from + 1, to) 157} 158" 159 ); 160} 161 162#[test] 163fn do_not_inline_parameters_used_more_than_once() { 164 // We just use `bool.guard` as the name here because it will be inlined 165 assert_erl!( 166 ( 167 "gleam_stdlib", 168 "gleam/bool", 169 " 170pub fn guard(something) { 171 case something { 172 True -> something 173 False -> False 174 } 175} 176" 177 ), 178 " 179import gleam/bool 180 181pub fn main() { 182 bool.guard(True) 183} 184" 185 ); 186} 187 188#[test] 189fn do_not_inline_parameters_that_have_side_effects() { 190 assert_erl!( 191 ("gleam_stdlib", "gleam/result", RESULT_MODULE), 192 r#" 193import gleam/result 194 195pub fn main() { 196 result.map(Ok(10), do_side_effects()) 197} 198 199fn do_side_effects() { 200 let function = fn(x) { x + 1 } 201 panic as "Side effects" 202 function 203} 204"# 205 ); 206} 207 208#[test] 209fn inline_anonymous_function_call() { 210 assert_erl!( 211 " 212pub fn main() { 213 fn(a, b) { #(a, b) }(42, False) 214} 215" 216 ); 217} 218 219#[test] 220fn inline_anonymous_function_in_pipe() { 221 assert_erl!( 222 " 223pub fn main() { 224 1 |> fn(x) { x + 1 } |> fn(y) { y * y } 225} 226" 227 ); 228} 229 230#[test] 231fn inline_function_capture_in_pipe() { 232 // The function capture is desugared to an anonymous function, so it should 233 // be turned into a direct call to `add` 234 assert_erl!( 235 " 236pub fn main() { 237 1 |> add(4, _) 238} 239 240fn add(a, b) { a + b } 241" 242 ); 243} 244 245#[test] 246fn inlining_works_through_blocks() { 247 assert_erl!( 248 " 249pub fn main() { 250 { fn(x) { Ok(x + 1) } }(41) 251} 252" 253 ); 254} 255 256#[test] 257fn blocks_get_preserved_when_needed() { 258 assert_erl!( 259 " 260pub fn main() { 261 { 4 |> make_adder }(6) 262} 263 264fn make_adder(a) { 265 fn(b) { a + b } 266} 267" 268 ); 269}