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 / records.rs
9.4 kB 469 lines
1use crate::assert_erl; 2use crate::erlang::*; 3use crate::type_; 4 5#[test] 6fn basic() { 7 insta::assert_snapshot!(record_definition( 8 "PetCat", 9 &[ 10 ("name", type_::tuple(vec![])), 11 ("is_cute", type_::tuple(vec![])) 12 ] 13 )); 14} 15 16#[test] 17fn reserve_words() { 18 // Reserved words are escaped in record names and fields 19 insta::assert_snapshot!(record_definition( 20 "div", 21 &[ 22 ("receive", type_::int()), 23 ("catch", type_::tuple(vec![])), 24 ("unreserved", type_::tuple(vec![])) 25 ] 26 )); 27} 28 29#[test] 30fn type_vars() { 31 // Type vars are printed as `any()` because records don't support generics 32 insta::assert_snapshot!(record_definition( 33 "PetCat", 34 &[ 35 ("name", type_::generic_var(1)), 36 ("is_cute", type_::unbound_var(1)), 37 ("linked", type_::link(type_::int())) 38 ] 39 )); 40} 41 42#[test] 43fn module_types() { 44 // Types are printed with module qualifiers 45 let module_name = "name".into(); 46 insta::assert_snapshot!(record_definition( 47 "PetCat", 48 &[( 49 "name", 50 Arc::new(Type::Named { 51 publicity: Publicity::Public, 52 package: "package".into(), 53 module: module_name, 54 name: "my_type".into(), 55 arguments: vec![], 56 inferred_variant: None, 57 }) 58 )] 59 )); 60} 61 62#[test] 63fn long_definition_formatting() { 64 // Long definition formatting 65 insta::assert_snapshot!(record_definition( 66 "PetCat", 67 &[ 68 ("name", type_::generic_var(1)), 69 ("is_cute", type_::unbound_var(1)), 70 ("linked", type_::link(type_::int())), 71 ( 72 "whatever", 73 type_::list(type_::tuple(vec![ 74 type_::nil(), 75 type_::list(type_::tuple(vec![type_::nil(), type_::nil(), type_::nil()])), 76 type_::nil(), 77 type_::list(type_::tuple(vec![type_::nil(), type_::nil(), type_::nil()])), 78 type_::nil(), 79 type_::list(type_::tuple(vec![type_::nil(), type_::nil(), type_::nil()])), 80 ])) 81 ), 82 ] 83 )); 84} 85 86#[test] 87fn record_accessors() { 88 // We can use record accessors for types with only one constructor 89 assert_erl!( 90 r#" 91pub type Person { Person(name: String, age: Int) } 92pub fn get_age(person: Person) { person.age } 93pub fn get_name(person: Person) { person.name } 94"# 95 ); 96} 97 98#[test] 99fn record_accessor_multiple_variants() { 100 // We can access fields on custom types with multiple variants 101 assert_erl!( 102 " 103pub type Person { 104 Teacher(name: String, title: String) 105 Student(name: String, age: Int) 106} 107pub fn get_name(person: Person) { person.name }" 108 ); 109} 110 111#[test] 112fn record_accessor_multiple_variants_positions_other_than_first() { 113 // We can access fields on custom types with multiple variants 114 // In positions other than the 1st field 115 assert_erl!( 116 " 117pub type Person { 118 Teacher(name: String, age: Int, title: String) 119 Student(name: String, age: Int) 120} 121pub fn get_name(person: Person) { person.name } 122pub fn get_age(person: Person) { person.age }" 123 ); 124} 125 126#[test] 127fn record_accessor_multiple_variants_parameterised_types() { 128 // We can access fields on custom types with multiple variants 129 // In positions other than the 1st field 130 assert_erl!( 131 " 132pub type Person { 133 Teacher(name: String, age: List(Int), title: String) 134 Student(name: String, age: List(Int)) 135} 136pub fn get_name(person: Person) { person.name } 137pub fn get_age(person: Person) { person.age }" 138 ); 139} 140 141#[test] 142fn record_accessor_multiple_with_first_position_different_types() { 143 // We can access fields on custom types with multiple variants 144 // In positions other than the 1st field 145 assert_erl!( 146 " 147pub type Person { 148 Teacher(name: Nil, age: Int) 149 Student(name: String, age: Int) 150} 151pub fn get_age(person: Person) { person.age }" 152 ); 153} 154 155#[test] 156fn record_spread() { 157 // Test binding to a record field with the spread operator 158 assert_erl!( 159 r#" 160pub type Triple { 161 Triple(a: Int, b: Int, c: Int) 162} 163 164pub fn main() { 165 let triple = Triple(1,2,3) 166 let Triple(the_a, ..) = triple 167 the_a 168} 169"# 170 ); 171} 172 173#[test] 174fn record_spread1() { 175 // Test binding to a record field with the spread operator 176 // Test binding to a record field with the spread operator and a labelled argument 177 assert_erl!( 178 r#" 179pub type Triple { 180 Triple(a: Int, b: Int, c: Int) 181} 182 183pub fn main() { 184 let triple = Triple(1,2,3) 185 let Triple(b: the_b, ..) = triple 186 the_b 187} 188"# 189 ); 190} 191 192#[test] 193fn record_spread2() { 194 // Test binding to a record field with the spread operator with both a labelled argument and a positional argument 195 assert_erl!( 196 r#" 197pub type Triple { 198 Triple(a: Int, b: Int, c: Int) 199} 200 201pub fn main() { 202 let triple = Triple(1,2,3) 203 let Triple(the_a, c: the_c, ..) = triple 204 the_c 205} 206"# 207 ); 208} 209 210#[test] 211fn record_spread3() { 212 // Test binding to a record field with the spread operator in a match 213 assert_erl!( 214 r#" 215pub type Triple { 216 Triple(a: Int, b: Int, c: Int) 217} 218 219pub fn main() { 220 let triple = Triple(1,2,3) 221 case triple { 222 Triple(b: the_b, ..) -> the_b 223 } 224} 225"# 226 ); 227} 228 229#[test] 230fn record_updates() { 231 // Record updates 232 assert_erl!( 233 r#" 234pub type Person { Person(name: String, age: Int) } 235 236pub fn main() { 237 let p = Person("Quinn", 27) 238 let new_p = Person(..p, age: 28) 239 new_p 240} 241"# 242 ); 243} 244 245#[test] 246fn record_updates1() { 247 // Record updates with field accesses 248 assert_erl!( 249 r#" 250pub type Person { Person(name: String, age: Int) } 251 252pub fn main() { 253 let p = Person("Quinn", 27) 254 let new_p = Person(..p, age: p.age + 1) 255 new_p 256} 257"# 258 ); 259} 260 261#[test] 262fn record_updates2() { 263 // Record updates with multiple fields 264 assert_erl!( 265 r#" 266pub type Person { Person(name: String, age: Int) } 267 268pub fn main() { 269 let p = Person("Quinn", 27) 270 let new_p = Person(..p, age: 28, name: "Riley") 271 new_p 272} 273"# 274 ); 275} 276 277#[test] 278fn record_updates3() { 279 // Record updates when record is returned from function 280 assert_erl!( 281 r#" 282pub type Person { Person(name: String, age: Int) } 283 284pub fn main() { 285 let new_p = Person(..return_person(), age: 28) 286 new_p 287} 288 289fn return_person() { 290 Person("Quinn", 27) 291} 292"# 293 ); 294} 295 296#[test] 297fn record_updates4() { 298 // Record updates when record is field on another record 299 assert_erl!( 300 r#" 301pub type Car { Car(make: String, model: String, driver: Person) } 302pub type Person { Person(name: String, age: Int) } 303 304pub fn main() { 305 let car = Car(make: "Amphicar", model: "Model 770", driver: Person(name: "John Doe", age: 27)) 306 let new_p = Person(..car.driver, age: 28) 307 new_p 308} 309"# 310 ); 311} 312 313#[test] 314fn record_constants() { 315 assert_erl!( 316 "pub type Test { A } 317const some_test = A 318pub fn a() { A }" 319 ); 320} 321 322// https://github.com/gleam-lang/gleam/issues/1698 323#[test] 324fn pipe_update_subject() { 325 assert_erl!( 326 "pub type Thing { 327 Thing(a: Int, b: Int) 328} 329 330pub fn identity(x) { x } 331 332pub fn main() { 333 let thing = Thing(1, 2) 334 Thing(..thing |> identity, b: 1000) 335}" 336 ); 337} 338 339// https://github.com/gleam-lang/gleam/issues/1698 340#[test] 341fn record_access_block() { 342 assert_erl!( 343 "pub type Thing { 344 Thing(a: Int, b: Int) 345} 346 347pub fn main() { 348 { 349 let thing = Thing(1, 2) 350 thing 351 }.a 352}" 353 ); 354} 355 356// https://github.com/gleam-lang/gleam/issues/1981 357#[test] 358fn imported_qualified_constructor_as_fn_name_escape() { 359 assert_erl!( 360 ("other_package", "other_module", "pub type Let { Let(Int) }"), 361 "import other_module 362 363pub fn main() { 364 other_module.Let 365}" 366 ); 367} 368 369#[test] 370fn nested_record_update() { 371 assert_erl!( 372 "pub type Wibble { 373 Wibble(a: Int, b: Wobble, c: Int) 374} 375 376pub type Wobble { 377 Wobble(a: Int, b: Int) 378} 379 380pub fn main() { 381 let base = Wibble(1, Wobble(2, 3), 4) 382 Wibble(..base, b: Wobble(..base.b, b: 5)) 383}" 384 ); 385} 386 387#[test] 388fn nested_record_update_with_blocks() { 389 assert_erl!( 390 "pub type A { A(b: B) } 391pub type B { B(c: C) } 392pub type C { C(val: Int) } 393 394pub fn main(a: A) { 395 A(..a, b: { 396 B(..a.b, c: { 397 C(..a.b.c, val: 0) 398 }) 399 }) 400}" 401 ) 402} 403 404#[test] 405fn private_unused_records() { 406 assert_erl!( 407 "type A { A(inner: Int) } 408type B { B(String) } 409type C { C(Int) } 410 411pub fn main(x: Int) -> Int { 412 let a = A(x) 413 a.inner 414} 415" 416 ) 417} 418 419#[test] 420fn const_record_update_generic_respecialization() { 421 assert_erl!( 422 " 423pub type Box(a) { 424 Box(name: String, value: a) 425} 426 427pub const base = Box(\"score\", 50) 428pub const updated = Box(..base, value: \"Hello\") 429 430pub fn main() { 431 #(base, updated) 432} 433", 434 ); 435} 436 437#[test] 438fn record_update_with_unlabelled_fields() { 439 assert_erl!( 440 r#" 441pub type Wibble { 442 Wibble(Int, Float, b: Bool, s: String) 443} 444 445pub fn main() { 446 let record = Wibble(1, 3.14, True, "Hello") 447 Wibble(..record, b: False) 448} 449"# 450 ); 451} 452 453#[test] 454fn constant_record_update_with_unlabelled_fields() { 455 assert_erl!( 456 r#" 457pub type Wibble { 458 Wibble(Int, Float, b: Bool, s: String) 459} 460 461pub const record = Wibble(1, 3.14, True, "Hello") 462pub const updated = Wibble(..record, b: False) 463 464pub fn main() { 465 updated 466} 467"# 468 ); 469}