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 / javascript / tests / functions.rs
9.6 kB 626 lines
1// SPDX-License-Identifier: Apache-2.0 2// SPDX-FileCopyrightText: 2021 The Gleam contributors 3 4use crate::{assert_js, assert_ts_def}; 5 6#[test] 7fn exported_functions() { 8 assert_js!( 9 r#" 10pub fn add(x, y) { 11 x + y 12}"#, 13 ); 14} 15 16#[test] 17fn calling_functions() { 18 assert_js!( 19 r#" 20pub fn twice(f: fn(t) -> t, x: t) -> t { 21 f(f(x)) 22} 23pub fn add_one(x: Int) -> Int { 24 x + 1 25} 26pub fn add_two(x: Int) -> Int { 27 twice(add_one, x) 28} 29 30pub fn take_two(x: Int) -> Int { 31 twice(fn(y) {y - 1}, x) 32} 33"#, 34 ); 35} 36 37#[test] 38fn function_formatting() { 39 assert_js!( 40 r#" 41pub fn add(the_first_variable_that_should_be_added, the_second_variable_that_should_be_added) { 42 the_first_variable_that_should_be_added + the_second_variable_that_should_be_added 43}"#, 44 ); 45} 46 47#[test] 48fn function_formatting1() { 49 assert_js!( 50 r#" 51pub fn this_function_really_does_have_a_ludicrously_unfeasibly_long_name_for_a_function(x, y) { 52x + y 53}"#, 54 ); 55} 56 57#[test] 58fn function_formatting2() { 59 assert_js!( 60 r#" 61pub fn add(x, y) { 62x + y 63} 64 65pub fn long() { 66 add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, add(1, 1))))))))))))))) 67}"#, 68 ); 69} 70 71#[test] 72fn function_formatting3() { 73 assert_js!( 74 r#" 75pub fn math(x, y) { 76 fn() { 77 x + y 78 x - y 79 2 * x 80 } 81}"#, 82 ); 83} 84 85#[test] 86fn function_formatting_typescript() { 87 assert_ts_def!( 88 r#" 89pub fn add(the_first_variable_that_should_be_added, the_second_variable_that_should_be_added) { 90 the_first_variable_that_should_be_added + the_second_variable_that_should_be_added 91}"#, 92 ); 93} 94 95#[test] 96fn function_formatting_typescript1() { 97 assert_ts_def!( 98 r#" 99pub fn this_function_really_does_have_a_ludicrously_unfeasibly_long_name_for_a_function(x, y) { 100x + y 101}"#, 102 ); 103} 104 105#[test] 106fn tail_call() { 107 assert_js!( 108 r#" 109pub fn count(xs, n) { 110 case xs { 111 [] -> n 112 [_, ..xs] -> count(xs, n + 1) 113 } 114} 115"#, 116 ); 117} 118 119#[test] 120fn tail_call_doesnt_clobber_tail_position_tracking() { 121 assert_js!( 122 r#" 123pub fn loop(indentation) { 124 case indentation > 0 { 125 True -> loop(indentation - 1) 126 False -> Nil 127 } 128} 129"#, 130 ); 131} 132 133#[test] 134fn pipe_last() { 135 assert_js!( 136 r#"fn id(x) { x } 137pub fn main() { 138 1 139 |> id 140} 141"#, 142 ); 143} 144 145#[test] 146fn calling_fn_literal() { 147 assert_js!( 148 r#"pub fn main() { 149 fn(x) { x }(1) 150} 151"#, 152 ); 153} 154 155// Don't mistake calling a function with the same name as the current function 156// as tail recursion 157#[test] 158fn shadowing_current() { 159 assert_js!( 160 r#"pub fn main() { 161 let main = fn() { 0 } 162 main() 163} 164"#, 165 ); 166} 167 168#[test] 169fn recursion_with_discards() { 170 assert_js!( 171 r#"pub fn main(f, _) { 172 f() 173 main(f, 1) 174} 175"#, 176 ); 177} 178 179#[test] 180fn no_recur_in_anon_fn() { 181 assert_js!( 182 r#"pub fn main() { 183 fn() { main() } 184 1 185} 186"#, 187 ); 188} 189 190#[test] 191fn case_in_call() { 192 assert_js!( 193 r#"pub fn main(f, x) { 194 f(case x { 195 1 -> 2 196 _ -> 0 197 }) 198} 199"#, 200 ); 201} 202 203#[test] 204fn reserved_word_fn() { 205 assert_js!( 206 r#"pub fn class() { 207 Nil 208} 209"#, 210 ); 211} 212 213#[test] 214fn reserved_word_imported() { 215 assert_js!( 216 ("for", "pub fn class() { 1 }"), 217 r#"import for.{class} 218 219pub fn export() { 220 class() 221} 222"#, 223 ); 224} 225 226#[test] 227fn reserved_word_imported_alias() { 228 assert_js!( 229 ("for", "pub fn class() { 1 }"), 230 r#"import for.{class as while} as function 231 232pub fn export() { 233 let delete = function.class 234 while() 235} 236"#, 237 ); 238} 239 240#[test] 241fn reserved_word_const() { 242 assert_js!( 243 r#"const in = 1 244 245pub fn export() { 246 in 247} 248"#, 249 ); 250} 251 252// https://github.com/gleam-lang/gleam/issues/1208 253#[test] 254fn reserved_word_argument() { 255 assert_js!( 256 r#"pub fn main(with) { 257 with 258} 259"#, 260 ); 261} 262 263// https://github.com/gleam-lang/gleam/issues/1186 264#[test] 265fn multiple_discard() { 266 assert_js!( 267 r#"pub fn main(_, _, _) { 268 1 269} 270"#, 271 ); 272} 273 274#[test] 275fn keyword_in_recursive_function() { 276 assert_js!( 277 r#"pub fn main(with: Int) -> Nil { 278 main(with - 1) 279} 280"#, 281 ); 282} 283 284#[test] 285fn reserved_word_in_function_arguments() { 286 assert_js!( 287 r#"pub fn main(arguments, eval) { 288 #(arguments, eval) 289} 290"#, 291 ); 292} 293 294#[test] 295fn let_last() { 296 assert_js!( 297 r#"pub fn main() { 298 let x = 1 299} 300"#, 301 ); 302} 303 304#[test] 305fn assert_last() { 306 assert_js!( 307 r#"pub fn main() { 308 let assert x = 1 309} 310"#, 311 ); 312} 313 314#[test] 315fn fn_return_fn_typescript() { 316 assert_ts_def!( 317 r#"pub fn main(f: fn(Int) -> Int) { 318 let func = fn(x, y) { f(x) + f(y) } 319 func 320} 321"#, 322 ); 323} 324 325// https://github.com/gleam-lang/gleam/issues/1637 326#[test] 327fn variable_rewriting_in_anon_fn_with_matching_parameter() { 328 assert_js!( 329 r#"pub fn bad() { 330 fn(state) { 331 let state = state 332 state 333 } 334} 335"#, 336 ); 337} 338 339// https://github.com/gleam-lang/gleam/issues/1637 340#[test] 341fn variable_rewriting_in_anon_fn_with_matching_parameter_in_case() { 342 assert_js!( 343 r#"pub fn bad() { 344 fn(state) { 345 let state = case Nil { 346 _ -> state 347 } 348 state 349 } 350} 351"#, 352 ); 353} 354 355// https://github.com/gleam-lang/gleam/issues/1508 356#[test] 357fn pipe_variable_rebinding() { 358 assert_js!( 359 " 360pub fn main() { 361 let version = 1 |> version() 362 version 363} 364 365pub fn version(n) { 366 Ok(1) 367}" 368 ) 369} 370 371#[test] 372fn pipe_shadow_import() { 373 assert_js!( 374 ("wibble", "pub fn println(x: String) { }"), 375 r#" 376 import wibble.{println} 377 pub fn main() { 378 let println = 379 "oh dear" 380 |> println 381 println 382 }"# 383 ); 384} 385 386#[test] 387fn module_const_fn() { 388 assert_js!( 389 r#" 390pub fn int_identity(i: Int) -> Int { i } 391pub const int_identity_alias: fn(Int) -> Int = int_identity 392pub fn use_int_identity_alias() { int_identity_alias(42) } 393 394pub const compound: #(fn(Int) -> Int, fn(Int) -> Int) = #(int_identity, int_identity_alias) 395pub fn use_compound() { compound.0(compound.1(42)) }"# 396 ); 397} 398 399#[test] 400fn module_const_fn1() { 401 assert_ts_def!( 402 r#" 403pub fn int_identity(i: Int) -> Int { i } 404pub const int_identity_alias: fn(Int) -> Int = int_identity 405pub const compound: #(fn(Int) -> Int, fn(Int) -> Int) = 406 #(int_identity, int_identity_alias)"# 407 ) 408} 409 410// https://github.com/gleam-lang/gleam/issues/2399 411#[test] 412fn bad_comma() { 413 assert_js!( 414 r#" 415fn function_with_a_long_name_that_is_intended_to_sit_right_on_the_limit() { 416 Nil 417} 418 419fn identity(x) { 420 x 421} 422 423pub fn main() { 424 function_with_a_long_name_that_is_intended_to_sit_right_on_the_limit() 425 |> identity 426} 427"# 428 ) 429} 430 431// https://github.com/gleam-lang/gleam/issues/2518 432#[test] 433fn function_literals_get_properly_wrapped_1() { 434 assert_js!( 435 r#"pub fn main() { 436 fn(n) { n + 1 }(10) 437} 438"# 439 ); 440} 441 442// https://github.com/gleam-lang/gleam/issues/2518 443#[test] 444fn function_literals_get_properly_wrapped_2() { 445 assert_js!( 446 r#"pub fn main() { 447 { fn(n) { n + 1 } }(10) 448} 449"# 450 ); 451} 452 453// https://github.com/gleam-lang/gleam/issues/2518 454#[test] 455fn function_literals_get_properly_wrapped_3() { 456 assert_js!( 457 r#"pub fn main() { 458 { let a = fn(n) { n + 1 } }(10) 459} 460"# 461 ); 462} 463 464#[test] 465fn labelled_argument_ordering() { 466 // https://github.com/gleam-lang/gleam/issues/3671 467 assert_js!( 468 " 469type A { A } 470type B { B } 471type C { C } 472type D { D } 473 474fn wibble(a a: A, b b: B, c c: C, d d: D) { 475 Nil 476} 477 478pub fn main() { 479 wibble(A, C, D, b: B) 480 wibble(A, C, D, b: B) 481 wibble(B, C, D, a: A) 482 wibble(B, C, a: A, d: D) 483 wibble(B, C, d: D, a: A) 484 wibble(B, D, a: A, c: C) 485 wibble(B, D, c: C, a: A) 486 wibble(C, D, b: B, a: A) 487} 488" 489 ); 490} 491 492// During the implementation of https://github.com/gleam-lang/gleam/pull/4337, 493// a bug was found where this code would compile incorrectly. 494#[test] 495fn two_pipes_in_a_row() { 496 assert_js!( 497 " 498pub type Function(a) { 499 Function(fn() -> a) 500} 501 502pub fn main() { 503 [fn() { 1 } |> Function, fn() { 2 } |> Function] 504} 505" 506 ); 507} 508 509// https://github.com/gleam-lang/gleam/issues/4472 510#[test] 511fn pipe_into_block() { 512 assert_js!( 513 " 514fn side_effects(x) { x } 515 516pub fn main() { 517 1 518 |> side_effects 519 |> { 520 side_effects(2) 521 side_effects 522 } 523} 524" 525 ); 526} 527 528// https://github.com/gleam-lang/gleam/issues/4472 529#[test] 530fn pipe_with_block_in_the_middle() { 531 assert_js!( 532 " 533fn side_effects(x) { x } 534 535pub fn main() { 536 1 537 |> side_effects 538 |> { 539 side_effects(2) 540 side_effects 541 } 542 |> side_effects 543} 544" 545 ); 546} 547 548// https://github.com/gleam-lang/gleam/issues/4533 549#[test] 550fn immediately_invoked_function_expressions_include_statement_level() { 551 assert_js!( 552 " 553fn identity(x) { x } 554 555pub type Wibble { 556 Wibble(a: Int, b: Int) 557} 558 559pub fn main() { 560 let w = Wibble(1, 2) 561 identity(Wibble(..w |> identity, b: 4)) |> identity 562} 563" 564 ); 565} 566 567#[test] 568fn public_function_gets_jsdoc() { 569 assert_js!( 570 " 571/// Hello! This is the documentation of the `main` 572/// function. 573/// 574pub fn main() { 1 } 575" 576 ); 577} 578 579#[test] 580fn internal_function_gets_ignored_jsdoc() { 581 assert_js!( 582 " 583/// Hello! This is the documentation of the `main` 584/// function, which is internal! 585/// 586@internal 587pub fn main() { 1 } 588" 589 ); 590} 591 592#[test] 593fn star_slash_in_jsdoc() { 594 assert_js!( 595 " 596/// */ 597/// 598pub fn main() { 1 } 599" 600 ); 601} 602 603// https://github.com/gleam-lang/gleam/issues/5488 604#[test] 605fn pipeline_has_correct_semicolons() { 606 assert_js!( 607 " 608pub fn main() { 609 1 |> echo |> fn(x) { { x + 1 } * 2 } 610 { 1 + 2 } * 3 611} 612" 613 ); 614} 615 616#[test] 617fn pipeline_with_final_has_correct_semicolon() { 618 assert_js!( 619 " 620pub fn main() { 621 1 |> echo 622 { 1 + 2 } * 3 623} 624" 625 ); 626}