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