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

Configure Feed

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

Implement singletons for fieldless variants

author
Gears
committer
Louis Pilfold
date (Jun 11, 2026, 11:11 AM +0100) commit 203b0e86 parent 6c54c781
+848 -208
+4
CHANGELOG.md
··· 26 26 functions, constants, module names, and `as` patterns. 27 27 ([Giacomo Cavalieri](https://github.com/giacomocavalieri)) 28 28 29 + - The compiler now generates singleton values for variants with no fields on the 30 + JavaScript target, allowing for faster comparison in most cases. 31 + ([Surya Rose](https://github.com/GearsDatapacks)) 32 + 29 33 ### Build tool 30 34 31 35 - The build tool now generates Hexdocs URLs using the new format of
+26 -6
compiler-core/src/exhaustiveness.rs
··· 479 479 }, 480 480 Variant { 481 481 index: usize, 482 + used_name: EcoString, 482 483 name: EcoString, 483 484 module: Option<EcoString>, 484 485 fields: Vec<Id<Pattern>>, ··· 736 737 #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] 737 738 pub enum VariantMatch { 738 739 ExplicitlyMatchedOn { 740 + /// The locally used name, including any alias 741 + used_name: EcoString, 742 + /// The original name of the variant 739 743 name: EcoString, 740 744 module: Option<EcoString>, 741 745 }, ··· 745 749 } 746 750 747 751 impl VariantMatch { 748 - pub(crate) fn name(&self) -> EcoString { 752 + pub(crate) fn used_name(&self) -> EcoString { 749 753 match self { 750 - VariantMatch::ExplicitlyMatchedOn { name, module: _ } => name.clone(), 754 + VariantMatch::ExplicitlyMatchedOn { used_name, .. } => used_name.clone(), 755 + VariantMatch::NeverExplicitlyMatchedOn { name } => name.clone(), 756 + } 757 + } 758 + 759 + pub(crate) fn variant_name(&self) -> EcoString { 760 + match self { 761 + VariantMatch::ExplicitlyMatchedOn { name, .. } => name.clone(), 751 762 VariantMatch::NeverExplicitlyMatchedOn { name } => name.clone(), 752 763 } 753 764 } 754 765 755 766 pub(crate) fn module(&self) -> Option<EcoString> { 756 767 match self { 757 - VariantMatch::ExplicitlyMatchedOn { name: _, module } => module.clone(), 768 + VariantMatch::ExplicitlyMatchedOn { module, .. } => module.clone(), 758 769 VariantMatch::NeverExplicitlyMatchedOn { name: _ } => None, 759 770 } 760 771 } ··· 2954 2965 // Then we have to update all variant checks with any new name/module 2955 2966 // we might have discovered from the pattern to make sure we're using 2956 2967 // the correct qualification to refer to each constructor. 2957 - if let Pattern::Variant { name, module, .. } = pattern { 2968 + if let Pattern::Variant { 2969 + used_name, 2970 + name, 2971 + module, 2972 + .. 2973 + } = pattern 2974 + { 2958 2975 for index in indices_of_overlapping_checks { 2959 2976 let (check, _) = self 2960 2977 .choices ··· 2963 2980 if let RuntimeCheck::Variant { match_, .. } = check { 2964 2981 *match_ = VariantMatch::ExplicitlyMatchedOn { 2965 2982 module: module.clone(), 2983 + used_name: used_name.clone(), 2966 2984 name: name.clone(), 2967 2985 } 2968 2986 } ··· 3412 3430 module, 3413 3431 .. 3414 3432 } => { 3415 - let index = constructor.expect_ref("must be inferred").constructor_index as usize; 3433 + let constructor = constructor.expect_ref("must be inferred"); 3434 + let index = constructor.constructor_index as usize; 3416 3435 let module = module.as_ref().map(|(module, _)| module.clone()); 3417 3436 let fields = arguments 3418 3437 .iter() 3419 3438 .map(|argument| self.register(&argument.value)) 3420 3439 .collect_vec(); 3421 3440 self.insert(Pattern::Variant { 3422 - name: name.clone(), 3441 + used_name: name.clone(), 3442 + name: constructor.name.clone(), 3423 3443 module, 3424 3444 index, 3425 3445 fields,
+132 -6
compiler-core/src/javascript.rs
··· 6 6 mod typescript; 7 7 8 8 use std::cell::RefCell; 9 - use std::collections::HashMap; 9 + use std::collections::{HashMap, HashSet}; 10 10 use std::rc::Rc; 11 11 12 12 use debug_ignore::DebugIgnore; ··· 223 223 self.register_prelude_usage(&mut imports, "Empty", Some("$Empty")); 224 224 }; 225 225 226 + if self.tracker.list_empty_const_used { 227 + self.register_prelude_usage( 228 + &mut imports, 229 + "List$Empty$const", 230 + Some("$List$Empty$const"), 231 + ); 232 + }; 233 + 226 234 if self.tracker.list_non_empty_class_used || self.tracker.echo_used { 227 235 self.register_prelude_usage(&mut imports, "NonEmpty", Some("$NonEmpty")); 228 236 }; ··· 303 311 self.register_prelude_usage(&mut imports, "sizedFloat", None); 304 312 } 305 313 314 + for (variant, alias) in self.tracker.variant_constants_used.iter() { 315 + let path = self.import_path(&variant.package, &variant.module); 316 + let member = Member { 317 + name: eco_format!("{}${}$const", variant.type_name, variant.name), 318 + alias: alias.as_ref().map(|alias| alias.to_doc()), 319 + }; 320 + imports.register_module(path, [], [member]); 321 + } 322 + 323 + // If we have some Gleam code that looks something like this: 324 + // ```gleam 325 + // import option.{None} 326 + // 327 + // pub fn main() { 328 + // None 329 + // } 330 + // ``` 331 + // 332 + // Here, the generated JavaScript code for `main` will look something 333 + // like this: 334 + // 335 + // ```javascript 336 + // export function main() { 337 + // return Option$None$const; 338 + // } 339 + // ``` 340 + // 341 + // The `None` variant is technically being imported, but we don't 342 + // actually use the generated `None` class in the JavaScript code, so 343 + // we don't want to import it. 344 + // 345 + // However, if we are pattern matching on the `None` variant, there 346 + // will be some code that looks like `if (value instanceof None)`, in 347 + // which case we still need to import `None`. Therefore we remove all 348 + // variants which are used as singleton constants, and that are not used 349 + // in pattern matching. 350 + // 351 + imports.filter_unused_variants( 352 + self.tracker 353 + .variant_constants_used 354 + .keys() 355 + .filter(|variant| !self.tracker.variants_used_in_instanceof.contains(variant)) 356 + .map(|variant| { 357 + let path = self.import_path(&variant.package, &variant.module); 358 + (path, variant.name.clone()) 359 + }), 360 + ); 361 + 306 362 let echo_definition = self.echo_definition(&mut imports); 307 363 let sourcemap_reference = self.sourcemap_reference(); 308 364 let type_reference = self.type_reference(); ··· 377 433 ) { 378 434 let path = self.import_path(&self.module.type_info.package, PRELUDE_MODULE_NAME); 379 435 let member = Member { 380 - name: name.to_doc(), 436 + name: name.into(), 381 437 alias: alias.map(|a| a.to_doc()), 382 438 }; 383 439 imports.register_module(path, [], [member]); ··· 470 526 return class_definition; 471 527 } 472 528 529 + let constructor_singleton = if constructor.arguments.is_empty() { 530 + self.variant_constructor_constant(constructor, type_name) 531 + .append(line()) 532 + } else { 533 + nil() 534 + }; 473 535 let constructor_definition = self.variant_constructor_definition(constructor, type_name); 474 536 let variant_check_definition = self.variant_check_definition(constructor, type_name); 475 537 let fields_definition = self.variant_fields_definition(constructor, type_name); ··· 477 539 docvec![ 478 540 class_definition, 479 541 line(), 542 + constructor_singleton, 480 543 constructor_definition, 481 544 line(), 482 545 variant_check_definition, ··· 484 547 ] 485 548 } 486 549 550 + /// Generate a singleton constant for a variant with no fields. This means 551 + /// that all values of a particular variant are the same underlying reference, 552 + /// allowing them to be compared more efficiently. 553 + /// 554 + fn variant_constructor_constant( 555 + &self, 556 + constructor: &'a TypedRecordConstructor, 557 + type_name: &'a str, 558 + ) -> Document<'a> { 559 + docvec![ 560 + self.source_map_tracker(constructor.location.start), 561 + "export const ", 562 + type_name, 563 + "$", 564 + constructor.name.as_str(), 565 + "$const", 566 + " =", 567 + docvec![break_("", " "), "new ", constructor.name.as_str(), "();"] 568 + .group() 569 + .nest(INDENT) 570 + ] 571 + } 572 + 487 573 fn variant_constructor_definition( 488 574 &self, 489 575 constructor: &'a TypedRecordConstructor, 490 576 type_name: &'a str, 491 577 ) -> Document<'a> { 578 + // If the constructor has no fields, return the singleton constant 579 + // instead. 580 + if constructor.arguments.is_empty() { 581 + return docvec![ 582 + "export const ", 583 + type_name, 584 + "$", 585 + constructor.name.as_str(), 586 + " = () =>", 587 + docvec![ 588 + break_("", " "), 589 + type_name, 590 + "$", 591 + constructor.name.as_str(), 592 + "$const;" 593 + ] 594 + .group() 595 + .nest(INDENT), 596 + ]; 597 + } 598 + 492 599 let mut arguments = Vec::new(); 493 600 494 601 for (index, parameter) in constructor.arguments.iter().enumerate() { ··· 754 861 imports 755 862 } 756 863 757 - fn import_path(&self, package: &'a str, module: &'a str) -> EcoString { 864 + fn import_path(&self, package: &str, module: &str) -> EcoString { 758 865 // TODO: strip shared prefixed between current module and imported 759 866 // module to avoid descending and climbing back out again 760 867 if package == self.module.type_info.package || package.is_empty() { ··· 801 908 self.register_in_scope(n); 802 909 maybe_escape_identifier(n).to_doc() 803 910 }); 804 - let name = maybe_escape_identifier(&i.name).to_doc(); 911 + let name = maybe_escape_identifier(&i.name); 805 912 Member { name, alias } 806 913 }); 807 914 ··· 815 922 publicity: Publicity, 816 923 name: &'a str, 817 924 module: &'a str, 818 - fun: &'a str, 925 + fun: &EcoString, 819 926 ) { 820 927 let needs_escaping = !is_usable_js_identifier(name); 821 928 let member = Member { 822 - name: fun.to_doc(), 929 + name: fun.clone(), 823 930 alias: if name == fun && !needs_escaping { 824 931 None 825 932 } else if needs_escaping { ··· 1254 1361 pub ok_used: bool, 1255 1362 pub list_used: bool, 1256 1363 pub list_empty_class_used: bool, 1364 + pub list_empty_const_used: bool, 1257 1365 pub list_non_empty_class_used: bool, 1258 1366 pub prepend_used: bool, 1259 1367 pub error_used: bool, ··· 1276 1384 pub codepoint_utf32_bit_array_segment_used: bool, 1277 1385 pub float_bit_array_segment_used: bool, 1278 1386 pub echo_used: bool, 1387 + /// Keeps track of each time a fieldless variant is constructed, so we can 1388 + /// import the singleton constant. Optionally contains an alias, if the variant 1389 + /// was imported unqualified and aliased. 1390 + pub variant_constants_used: HashMap<TypeVariant, Option<EcoString>>, 1391 + /// Fieldless variants that are used in `instanceof` checks during pattern 1392 + /// matching or comparison. If we're only using a fieldless variant for 1393 + /// construction, we don't need to import the variant class itself, just it 1394 + /// singleton constant. However, if we are using `instanceof`, we still need 1395 + /// to import it. 1396 + pub variants_used_in_instanceof: HashSet<TypeVariant>, 1397 + } 1398 + 1399 + #[derive(Debug, PartialEq, Eq, Hash)] 1400 + pub struct TypeVariant { 1401 + package: EcoString, 1402 + module: EcoString, 1403 + type_name: EcoString, 1404 + name: EcoString, 1279 1405 } 1280 1406 1281 1407 fn bool(bool: bool) -> Document<'static> {
+29 -5
compiler-core/src/javascript/decision.rs
··· 12 12 }, 13 13 format::break_block, 14 14 javascript::{ 15 + TypeVariant, 15 16 expression::{eco_string_int, string}, 16 17 maybe_escape_property, 17 18 }, ··· 274 275 /// Here we will first need to check that the list is not empty: 275 276 /// 276 277 /// ```js 277 - /// if (value instanceOf $NonEmptyList) { 278 + /// if (value instanceof $NonEmptyList) { 278 279 /// // ... 279 280 /// } else { 280 281 /// return []; ··· 288 289 /// first item of the list, so we need to actually create a variable for it: 289 290 /// 290 291 /// ```js 291 - /// if (value instanceOf $NonEmptyList) { 292 + /// if (value instanceof $NonEmptyList) { 292 293 /// let $ = value.head; 293 294 /// if ($ === 1) { 294 295 /// // ... ··· 1338 1339 // Some variants like `Bool` and `Result` are special cased and checked 1339 1340 // in a different way from all other variants. 1340 1341 RuntimeCheck::Variant { match_, .. } if variable.type_.is_bool() => { 1341 - match match_.name().as_str() { 1342 + match match_.used_name().as_str() { 1342 1343 "True" => value.to_doc(), 1343 1344 _ => docvec!["!", value], 1344 1345 } 1345 1346 } 1346 1347 1347 - RuntimeCheck::Variant { match_, index, .. } => { 1348 + RuntimeCheck::Variant { 1349 + match_, 1350 + index, 1351 + fields, 1352 + .. 1353 + } => { 1348 1354 if variable.type_.is_result() && match_.module().is_none() { 1349 1355 if *index == 0 { 1350 1356 self.expression_generator.tracker.ok_used = true; ··· 1358 1364 .map(|module| eco_format!("${module}.")) 1359 1365 .unwrap_or_default(); 1360 1366 1361 - docvec![value, " instanceof ", qualification, match_.name()] 1367 + // If this variant has no fields, register it as being used 1368 + // so that we know to import it. 1369 + if fields.is_empty() 1370 + && let Some((package, module, type_name)) = 1371 + variable.type_.named_type_name_and_package() 1372 + { 1373 + _ = self 1374 + .expression_generator 1375 + .tracker 1376 + .variants_used_in_instanceof 1377 + .insert(TypeVariant { 1378 + package, 1379 + module, 1380 + type_name, 1381 + name: match_.variant_name(), 1382 + }); 1383 + } 1384 + 1385 + docvec![value, " instanceof ", qualification, match_.used_name()] 1362 1386 } 1363 1387 1364 1388 RuntimeCheck::NonEmptyList { .. } => {
+166 -57
compiler-core/src/javascript/expression.rs
··· 389 389 tail, 390 390 ) 391 391 } 392 + None if elements.is_empty() => this.empty_list(), 392 393 None => { 393 394 this.tracker.list_used = true; 394 395 list(elements.iter().map(|element| this.wrap_expression(element))) ··· 508 509 self.wrap_return(document) 509 510 ] 510 511 } 512 + } 513 + 514 + /// Return the singleton empty list; all empty lists are the same underlying 515 + /// reference, which makes comparison faster. 516 + fn empty_list(&mut self) -> Document<'static> { 517 + self.tracker.list_empty_const_used = true; 518 + "$List$Empty$const".to_doc() 511 519 } 512 520 513 521 fn negate_with(&mut self, with: &'static str, value: &'a TypedExpr) -> Document<'a> { ··· 811 819 812 820 fn variable(&mut self, name: &'a EcoString, constructor: &'a ValueConstructor) -> Document<'a> { 813 821 match &constructor.variant { 814 - ValueConstructorVariant::Record { arity, .. } => { 822 + ValueConstructorVariant::Record { 823 + arity, 824 + name: variant_name, 825 + .. 826 + } => { 815 827 let type_ = constructor.type_.clone(); 816 - let tracker = &mut self.tracker; 817 - record_constructor(type_, None, name, *arity, tracker) 828 + self.record_constructor(type_, None, variant_name, name, *arity) 818 829 } 819 830 ValueConstructorVariant::ModuleFn { .. } 820 831 | ValueConstructorVariant::ModuleConstant { .. } ··· 1869 1880 name, 1870 1881 constructor: 1871 1882 ValueConstructor { 1872 - variant: ValueConstructorVariant::Record { arity: 0, .. }, 1883 + variant: 1884 + ValueConstructorVariant::Record { 1885 + arity: 0, 1886 + name: variant_name, 1887 + .. 1888 + }, 1873 1889 .. 1874 1890 }, 1875 1891 .. ··· 1877 1893 let left_doc = self.not_in_tail_position(Some(Ordering::Strict), |this| { 1878 1894 this.wrap_expression(left) 1879 1895 }); 1880 - Some(self.singleton_equal(left_doc, None, name, should_be_equal)) 1896 + Some(self.singleton_equal( 1897 + left_doc, 1898 + None, 1899 + name.clone(), 1900 + should_be_equal, 1901 + variant_name.clone(), 1902 + right.type_(), 1903 + )) 1881 1904 } 1882 1905 TypedExpr::ModuleSelect { 1883 1906 module_alias, ··· 1887 1910 let left_doc = self.not_in_tail_position(Some(Ordering::Strict), |this| { 1888 1911 this.wrap_expression(left) 1889 1912 }); 1890 - Some(self.singleton_equal(left_doc, Some(module_alias), name, should_be_equal)) 1913 + Some(self.singleton_equal( 1914 + left_doc, 1915 + Some(module_alias), 1916 + name.clone(), 1917 + should_be_equal, 1918 + name.clone(), 1919 + right.type_(), 1920 + )) 1891 1921 } 1892 1922 // Empty lists are implemented as a variant with no fields, so we can 1893 1923 // use `instanceof` for a faster check. ··· 1896 1926 this.wrap_expression(left) 1897 1927 }); 1898 1928 self.tracker.list_empty_class_used = true; 1899 - Some(self.singleton_equal(left_doc, None, "$Empty".into(), should_be_equal)) 1929 + Some(self.singleton_equal( 1930 + left_doc, 1931 + None, 1932 + "$Empty".into(), 1933 + should_be_equal, 1934 + "Empty".into(), 1935 + right.type_(), 1936 + )) 1900 1937 } 1901 1938 TypedExpr::Int { .. } 1902 1939 | TypedExpr::Float { .. } ··· 1926 1963 } 1927 1964 1928 1965 fn singleton_equal( 1929 - &self, 1966 + &mut self, 1930 1967 value: Document<'a>, 1931 1968 module: Option<&'a str>, 1932 - name: &'a str, 1969 + name: EcoString, 1933 1970 should_be_equal: bool, 1971 + variant_name: EcoString, 1972 + type_: Arc<Type>, 1934 1973 ) -> Document<'a> { 1974 + // If we're using this variant unqualified, register it as used so that 1975 + // we know to import it. This `instanceof` check only happens if the 1976 + // variant has no fields, so we don't need to check that here. 1977 + if module.is_none() 1978 + && let Some((package, module, type_name)) = type_.named_type_name_and_package() 1979 + { 1980 + _ = self 1981 + .tracker 1982 + .variants_used_in_instanceof 1983 + .insert(TypeVariant { 1984 + package, 1985 + module, 1986 + type_name, 1987 + name: variant_name, 1988 + }); 1989 + } 1935 1990 let record = if let Some(module) = module { 1936 1991 docvec!["$", module, ".", name] 1937 1992 } else { ··· 2089 2144 2090 2145 ModuleValueConstructor::Record { 2091 2146 name, arity, type_, .. 2092 - } => record_constructor(type_.clone(), Some(module), name, *arity, self.tracker), 2147 + } => self.record_constructor(type_.clone(), Some(module), name, name, *arity), 2093 2148 } 2094 2149 } 2095 2150 ··· 2132 2187 ), 2133 2188 2134 2189 Constant::List { elements, tail, .. } => { 2190 + if tail.is_none() && elements.is_empty() { 2191 + return self.empty_list(); 2192 + } 2193 + 2135 2194 self.tracker.list_used = true; 2136 2195 let list = match tail { 2137 2196 // There's no tail in the list, we join all the elements and ··· 2209 2268 && arity != 0 2210 2269 { 2211 2270 let arity = arity as u16; 2212 - return record_constructor(type_.clone(), None, name, arity, self.tracker); 2271 + return self.record_constructor(type_.clone(), None, &tag, name, arity); 2213 2272 } 2214 2273 2215 2274 // Otherwise we're always constructing a record! Even if there's ··· 2520 2579 module, 2521 2580 name, 2522 2581 .. 2523 - }) if let ValueConstructorVariant::Record { arity: 0, .. } = constructor.variant => { 2582 + }) if let ValueConstructorVariant::Record { 2583 + arity: 0, 2584 + name: variant_name, 2585 + .. 2586 + } = &constructor.variant => 2587 + { 2524 2588 let left_doc = self.guard(left); 2525 2589 Some(self.singleton_equal( 2526 2590 left_doc, 2527 2591 module.as_ref().map(|(module, _)| module.as_str()), 2528 - name, 2592 + name.clone(), 2529 2593 should_be_equal, 2594 + variant_name.clone(), 2595 + right.type_(), 2530 2596 )) 2531 2597 } 2532 2598 ClauseGuard::Constant(Constant::List { ··· 2536 2602 }) if elements.is_empty() => { 2537 2603 let left_doc = self.guard(left); 2538 2604 self.tracker.list_empty_class_used = true; 2539 - Some(self.singleton_equal(left_doc, None, "$Empty", should_be_equal)) 2605 + Some(self.singleton_equal( 2606 + left_doc, 2607 + None, 2608 + "$Empty".into(), 2609 + should_be_equal, 2610 + "Empty".into(), 2611 + right.type_(), 2612 + )) 2540 2613 } 2541 - _ => None, 2614 + ClauseGuard::Block { .. } 2615 + | ClauseGuard::BinaryOperator { .. } 2616 + | ClauseGuard::Not { .. } 2617 + | ClauseGuard::Var { .. } 2618 + | ClauseGuard::TupleIndex { .. } 2619 + | ClauseGuard::FieldAccess { .. } 2620 + | ClauseGuard::ModuleSelect { .. } 2621 + | ClauseGuard::Constant(_) 2622 + | ClauseGuard::Invalid { .. } => None, 2542 2623 } 2543 2624 } 2544 2625 ··· 2595 2676 pub fn source_map_tracker(&mut self, start_index: u32) -> Document<'a> { 2596 2677 create_cursor_position_observer(&self.source_map_builder, self.line_numbers, start_index) 2597 2678 } 2679 + 2680 + pub(crate) fn record_constructor( 2681 + &mut self, 2682 + type_: Arc<Type>, 2683 + qualifier: Option<&'a str>, 2684 + variant_name: &EcoString, 2685 + name: &'a EcoString, 2686 + arity: u16, 2687 + ) -> Document<'a> { 2688 + if qualifier.is_none() && type_.is_result_constructor() { 2689 + if name == "Ok" { 2690 + self.tracker.ok_used = true; 2691 + } else if name == "Error" { 2692 + self.tracker.error_used = true; 2693 + } 2694 + } 2695 + if type_.is_bool() && name == "True" { 2696 + "true".to_doc() 2697 + } else if type_.is_bool() { 2698 + "false".to_doc() 2699 + } else if type_.is_nil() { 2700 + "undefined".to_doc() 2701 + } else if arity == 0 2702 + && let Some((package, module, type_name)) = type_.named_type_name_and_package() 2703 + { 2704 + // If the variant has no fields, return the singleton constant so 2705 + // that all values of the variant are the same underlying reference, 2706 + // and are faster to compare. 2707 + match qualifier { 2708 + Some(module) => docvec!["$", module, ".", type_name, "$", name, "$const"], 2709 + None => { 2710 + if module != self.module_name { 2711 + let alias = if name == variant_name { 2712 + None 2713 + } else { 2714 + Some(eco_format!("{}${}$const", type_name, name)) 2715 + }; 2716 + // Since this constant is an implementation detail and not 2717 + // present in Gleam code, we need to track it so that we 2718 + // import it, as it doesn't appear directly in the `import`s 2719 + // in the source code. 2720 + _ = self.tracker.variant_constants_used.insert( 2721 + TypeVariant { 2722 + package, 2723 + module, 2724 + type_name: type_name.clone(), 2725 + name: variant_name.clone(), 2726 + }, 2727 + alias, 2728 + ); 2729 + } 2730 + docvec![type_name, "$", name, "$const"] 2731 + } 2732 + } 2733 + } else { 2734 + let vars = (0..arity).map(|i| eco_format!("var{i}").to_doc()); 2735 + let body = docvec![ 2736 + "return ", 2737 + construct_record(qualifier, name, vars.clone()), 2738 + ";" 2739 + ]; 2740 + docvec![ 2741 + docvec![wrap_arguments(vars), " => {", break_("", " "), body] 2742 + .nest(INDENT) 2743 + .append(break_("", " ")) 2744 + .group(), 2745 + "}", 2746 + ] 2747 + } 2748 + } 2598 2749 } 2599 2750 2600 2751 #[derive(Clone, Copy)] ··· 2947 3098 "})()", 2948 3099 ] 2949 3100 .group() 2950 - } 2951 - 2952 - pub(crate) fn record_constructor<'a>( 2953 - type_: Arc<Type>, 2954 - qualifier: Option<&'a str>, 2955 - name: &'a str, 2956 - arity: u16, 2957 - tracker: &mut UsageTracker, 2958 - ) -> Document<'a> { 2959 - if qualifier.is_none() && type_.is_result_constructor() { 2960 - if name == "Ok" { 2961 - tracker.ok_used = true; 2962 - } else if name == "Error" { 2963 - tracker.error_used = true; 2964 - } 2965 - } 2966 - if type_.is_bool() && name == "True" { 2967 - "true".to_doc() 2968 - } else if type_.is_bool() { 2969 - "false".to_doc() 2970 - } else if type_.is_nil() { 2971 - "undefined".to_doc() 2972 - } else if arity == 0 { 2973 - match qualifier { 2974 - Some(module) => docvec!["new $", module, ".", name, "()"], 2975 - None => docvec!["new ", name, "()"], 2976 - } 2977 - } else { 2978 - let vars = (0..arity).map(|i| eco_format!("var{i}").to_doc()); 2979 - let body = docvec![ 2980 - "return ", 2981 - construct_record(qualifier, name, vars.clone()), 2982 - ";" 2983 - ]; 2984 - docvec![ 2985 - docvec![wrap_arguments(vars), " => {", break_("", " "), body] 2986 - .nest(INDENT) 2987 - .append(break_("", " ")) 2988 - .group(), 2989 - "}", 2990 - ] 2991 - } 2992 3101 } 2993 3102 2994 3103 fn u8_slice<'a>(bytes: &[u8]) -> Document<'a> {
+30 -11
compiler-core/src/javascript/import.rs
··· 46 46 self.imports 47 47 .into_values() 48 48 .sorted_by(|a, b| a.path.cmp(&b.path)) 49 - .map(|import| Import::into_doc(import, codegen_target)), 49 + .map(|import| import.into_doc(codegen_target)), 50 50 ); 51 51 52 52 if self.exports.is_empty() { ··· 81 81 82 82 pub fn is_empty(&self) -> bool { 83 83 self.imports.is_empty() && self.exports.is_empty() 84 + } 85 + 86 + /// Remove variants which are imported in Gleam code, but not needed to be 87 + /// imported because singleton constants are used instead. 88 + /// 89 + pub fn filter_unused_variants<I>(&mut self, unused: I) 90 + where 91 + I: Iterator<Item = (EcoString, EcoString)>, 92 + { 93 + for (path, name) in unused { 94 + if let Some(import_) = self.imports.get_mut(&path) 95 + && let Some(index) = import_ 96 + .unqualified 97 + .iter() 98 + .position(|member| member.name == name) 99 + { 100 + _ = import_.unqualified.remove(index); 101 + } 102 + } 84 103 } 85 104 } 86 105 ··· 146 165 147 166 #[derive(Debug)] 148 167 pub struct Member<'a> { 149 - pub name: Document<'a>, 168 + pub name: EcoString, 150 169 pub alias: Option<Document<'a>>, 151 170 } 152 171 153 172 impl<'a> Member<'a> { 154 173 fn into_doc(self) -> Document<'a> { 155 174 match self.alias { 156 - None => self.name, 175 + None => self.name.to_doc(), 157 176 Some(alias) => docvec![self.name, " as ", alias], 158 177 } 159 178 } ··· 173 192 "./multiple/times".into(), 174 193 [], 175 194 [Member { 176 - name: "one".to_doc(), 195 + name: "one".into(), 177 196 alias: None, 178 197 }], 179 198 ); ··· 183 202 [], 184 203 [ 185 204 Member { 186 - name: "one".to_doc(), 205 + name: "one".into(), 187 206 alias: None, 188 207 }, 189 208 Member { 190 - name: "one".to_doc(), 209 + name: "one".into(), 191 210 alias: Some("onee".to_doc()), 192 211 }, 193 212 Member { 194 - name: "two".to_doc(), 213 + name: "two".into(), 195 214 alias: Some("twoo".to_doc()), 196 215 }, 197 216 ], ··· 202 221 [], 203 222 [ 204 223 Member { 205 - name: "three".to_doc(), 224 + name: "three".into(), 206 225 alias: None, 207 226 }, 208 227 Member { 209 - name: "four".to_doc(), 228 + name: "four".into(), 210 229 alias: None, 211 230 }, 212 231 ], ··· 217 236 [], 218 237 [ 219 238 Member { 220 - name: "one".to_doc(), 239 + name: "one".into(), 221 240 alias: None, 222 241 }, 223 242 Member { 224 - name: "two".to_doc(), 243 + name: "two".into(), 225 244 alias: None, 226 245 }, 227 246 ],
+2 -2
compiler-core/src/javascript/tests.rs
··· 173 173 importable_modules: &modules, 174 174 warnings: &TypeWarningEmitter::null(), 175 175 direct_dependencies: &HashMap::new(), 176 - dev_dependencies: &std::collections::HashSet::new(), 176 + dev_dependencies: &HashSet::new(), 177 177 target_support: TargetSupport::Enforced, 178 178 package_config: &dep_config, 179 179 } ··· 199 199 importable_modules: &modules, 200 200 warnings: &TypeWarningEmitter::null(), 201 201 direct_dependencies: &direct_dependencies, 202 - dev_dependencies: &std::collections::HashSet::new(), 202 + dev_dependencies: &HashSet::new(), 203 203 target_support: TargetSupport::NotEnforced, 204 204 package_config: &config, 205 205 }
+98
compiler-core/src/javascript/tests/custom_types.rs
··· 1070 1070 "#, 1071 1071 ); 1072 1072 } 1073 + 1074 + #[test] 1075 + fn singleton_for_two_aliased_variants() { 1076 + assert_js!( 1077 + ("wibble", "pub type Wibble { Wibble }"), 1078 + ("wobble", "pub type Wibble { Wibble }"), 1079 + " 1080 + import wobble.{Wibble as Wobble} 1081 + import wibble.{Wibble as Wubble} 1082 + 1083 + pub fn main() { 1084 + #(Wobble, Wubble) 1085 + } 1086 + " 1087 + ); 1088 + } 1089 + 1090 + #[test] 1091 + fn fieldless_variant_still_imported_if_used_in_instanceof_comparison() { 1092 + assert_js!( 1093 + ("wibble", "pub type Wibble { Wibble Wobble }"), 1094 + " 1095 + import wibble.{Wibble} 1096 + 1097 + pub fn main() { 1098 + let x = Wibble 1099 + x == Wibble 1100 + } 1101 + " 1102 + ); 1103 + } 1104 + 1105 + #[test] 1106 + fn fieldless_variant_still_imported_if_used_in_instanceof_comparison_in_guard() { 1107 + assert_js!( 1108 + ("wibble", "pub type Wibble { Wibble Wobble }"), 1109 + " 1110 + import wibble.{Wibble} 1111 + 1112 + pub fn main() { 1113 + let x = Wibble 1114 + case x { 1115 + _ if x == Wibble -> 1 1116 + _ -> 2 1117 + } 1118 + } 1119 + " 1120 + ); 1121 + } 1122 + 1123 + #[test] 1124 + fn aliased_variant_still_imported_if_used_in_instanceof_comparison() { 1125 + assert_js!( 1126 + ("wibble", "pub type Wibble { Wibble Wobble }"), 1127 + " 1128 + import wibble.{Wibble as Wobble} 1129 + 1130 + pub fn main() { 1131 + let x = Wobble 1132 + x == Wobble 1133 + } 1134 + " 1135 + ); 1136 + } 1137 + 1138 + #[test] 1139 + fn aliased_variant_still_imported_if_used_in_instanceof_comparison_in_guard() { 1140 + assert_js!( 1141 + ("wibble", "pub type Wibble { Wibble Wobble }"), 1142 + " 1143 + import wibble.{Wibble as Wobble} 1144 + 1145 + pub fn go(x) { 1146 + case x { 1147 + _ if x == Wobble -> Wobble 1148 + _ -> wibble.Wobble 1149 + } 1150 + } 1151 + " 1152 + ); 1153 + } 1154 + 1155 + #[test] 1156 + fn aliased_variant_still_imported_if_used_in_pattern_matching() { 1157 + assert_js!( 1158 + ("wibble", "pub type Wibble { Wibble Wobble }"), 1159 + " 1160 + import wibble.{Wibble as Wobble} 1161 + 1162 + pub fn go(x) { 1163 + case x { 1164 + Wobble -> wibble.Wobble 1165 + _ -> Wobble 1166 + } 1167 + } 1168 + " 1169 + ); 1170 + }
+3 -3
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__assert__prova.snap
··· 12 12 13 13 14 14 ----- COMPILED JAVASCRIPT 15 - import { Ok, toList, makeError, isEqual } from "../gleam.mjs"; 15 + import { Ok, List$Empty$const as $List$Empty$const, makeError, isEqual } from "../gleam.mjs"; 16 16 17 17 const FILEPATH = "src/module.gleam"; 18 18 ··· 21 21 } 22 22 23 23 export function main() { 24 - let $ = new Ok(toList([])); 24 + let $ = new Ok($List$Empty$const); 25 25 let $1 = new Ok( 26 26 (() => { 27 - let _pipe = toList([]); 27 + let _pipe = $List$Empty$const; 28 28 return id(_pipe); 29 29 })(), 30 30 );
+6 -3
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__shadowed_bools_and_nil.snap
··· 18 18 const FILEPATH = "src/module.gleam"; 19 19 20 20 export class True extends $CustomType {} 21 - export const True$True = () => new True(); 21 + export const True$True$const = new True(); 22 + export const True$True = () => True$True$const; 22 23 export const True$isTrue = (value) => value instanceof True; 23 24 24 25 export class False extends $CustomType {} 25 - export const True$False = () => new False(); 26 + export const True$False$const = new False(); 27 + export const True$False = () => True$False$const; 26 28 export const True$isFalse = (value) => value instanceof False; 27 29 28 30 export class Nil extends $CustomType {} 29 - export const True$Nil = () => new Nil(); 31 + export const True$Nil$const = new Nil(); 32 + export const True$Nil = () => True$Nil$const; 30 33 export const True$isNil = (value) => value instanceof Nil; 31 34 32 35 export function go(x, y) {
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__case_branches_guards_are_wrapped_in_parentheses.snap
··· 13 13 14 14 15 15 ----- COMPILED JAVASCRIPT 16 - import { toList, Empty as $Empty } from "../gleam.mjs"; 16 + import { Empty as $Empty, List$Empty$const as $List$Empty$const } from "../gleam.mjs"; 17 17 18 18 export function anything() { 19 19 while (true) { 20 - let $ = toList([]); 20 + let $ = $List$Empty$const; 21 21 if (!($ instanceof $Empty)) { 22 22 let $1 = $.tail; 23 23 if ($1 instanceof $Empty && false || true) {
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__constructor_function_in_guard.snap
··· 12 12 13 13 14 14 ----- COMPILED JAVASCRIPT 15 - import { Ok, toList, Empty as $Empty } from "../gleam.mjs"; 15 + import { Ok, toList, Empty as $Empty, List$Empty$const as $List$Empty$const } from "../gleam.mjs"; 16 16 17 17 export function func(x) { 18 - let $ = toList([]); 18 + let $ = $List$Empty$const; 19 19 if (toList([(var0) => { return new Ok(var0); }]) instanceof $Empty) { 20 20 return true; 21 21 } else {
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__custom_type_constructor_imported_and_aliased.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 import * as $other_module from "../../package/other_module.mjs"; 17 - import { A as B } from "../../package/other_module.mjs"; 17 + import { A as B, T$A$const as T$B$const } from "../../package/other_module.mjs"; 18 18 19 19 export function func() { 20 - let $ = new B(); 20 + let $ = T$B$const; 21 21 let x = $; 22 22 if (x instanceof B) { 23 23 return true;
+3 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__guard_pattern_does_not_shadow_outer_scope.snap
··· 38 38 export const Option$Some$0 = (value) => value[0]; 39 39 40 40 export class None extends $CustomType {} 41 - export const Option$None = () => new None(); 41 + export const Option$None$const = new None(); 42 + export const Option$None = () => Option$None$const; 42 43 export const Option$isNone = (value) => value instanceof None; 43 44 44 45 export class Container extends $CustomType { ··· 57 58 let $ = new Some(1); 58 59 let x$1 = $[0]; 59 60 if (x$1 < 0) { 60 - return new Container(new None()); 61 + return new Container(Option$None$const); 61 62 } else { 62 63 return new Container(x); 63 64 }
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__imported_aliased_ok.snap
··· 20 20 import { Ok as Y, CustomType as $CustomType, isEqual } from "../gleam.mjs"; 21 21 22 22 export class Ok extends $CustomType {} 23 - export const X$Ok = () => new Ok(); 23 + export const X$Ok$const = new Ok(); 24 + export const X$Ok = () => X$Ok$const; 24 25 export const X$isOk = (value) => value instanceof Ok; 25 26 26 27 export function func() {
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__imported_ok.snap
··· 20 20 import { Ok, toList, Empty as $Empty, CustomType as $CustomType } from "../gleam.mjs"; 21 21 22 22 export class Ok extends $CustomType {} 23 - export const X$Ok = () => new Ok(); 23 + export const X$Ok$const = new Ok(); 24 + export const X$Ok = () => X$Ok$const; 24 25 export const X$isOk = (value) => value instanceof Ok; 25 26 26 27 export function func(x) {
+6 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__consts__constant_constructor_gets_pure_annotation.snap
··· 13 13 14 14 15 15 ----- COMPILED JAVASCRIPT 16 - import { toList, CustomType as $CustomType } from "../gleam.mjs"; 16 + import { 17 + toList, 18 + List$Empty$const as $List$Empty$const, 19 + CustomType as $CustomType, 20 + } from "../gleam.mjs"; 17 21 18 22 export class X extends $CustomType { 19 23 constructor($0, $1) { ··· 29 33 30 34 export const x = /* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"])); 31 35 32 - export const y = /* @__PURE__ */ new X(1, /* @__PURE__ */ toList([])); 36 + export const y = /* @__PURE__ */ new X(1, $List$Empty$const);
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__consts__imported_aliased_ok.snap
··· 17 17 import { Ok as Y, CustomType as $CustomType } from "../gleam.mjs"; 18 18 19 19 export class Ok extends $CustomType {} 20 - export const X$Ok = () => new Ok(); 20 + export const X$Ok$const = new Ok(); 21 + export const X$Ok = () => X$Ok$const; 21 22 export const X$isOk = (value) => value instanceof Ok; 22 23 23 24 export const y = (var0) => { return new Y(var0); };
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__consts__imported_ok.snap
··· 17 17 import { Ok, CustomType as $CustomType } from "../gleam.mjs"; 18 18 19 19 export class Ok extends $CustomType {} 20 - export const X$Ok = () => new Ok(); 20 + export const X$Ok$const = new Ok(); 21 + export const X$Ok = () => X$Ok$const; 21 22 export const X$isOk = (value) => value instanceof Ok; 22 23 23 24 export const y = (var0) => { return new Ok(var0); };
+26
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__aliased_variant_still_imported_if_used_in_instanceof_comparison.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wibble.{Wibble as Wobble}\n\npub fn main() {\n let x = Wobble\n x == Wobble\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble Wobble } 8 + 9 + -- main.gleam 10 + 11 + import wibble.{Wibble as Wobble} 12 + 13 + pub fn main() { 14 + let x = Wobble 15 + x == Wobble 16 + } 17 + 18 + 19 + ----- COMPILED JAVASCRIPT 20 + import * as $wibble from "../wibble.mjs"; 21 + import { Wibble as Wobble, Wibble$Wibble$const as Wibble$Wobble$const } from "../wibble.mjs"; 22 + 23 + export function main() { 24 + let x = Wibble$Wobble$const; 25 + return x instanceof Wobble; 26 + }
+31
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__aliased_variant_still_imported_if_used_in_instanceof_comparison_in_guard.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wibble.{Wibble as Wobble}\n\npub fn go(x) {\n case x {\n _ if x == Wobble -> Wobble\n _ -> wibble.Wobble\n }\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble Wobble } 8 + 9 + -- main.gleam 10 + 11 + import wibble.{Wibble as Wobble} 12 + 13 + pub fn go(x) { 14 + case x { 15 + _ if x == Wobble -> Wobble 16 + _ -> wibble.Wobble 17 + } 18 + } 19 + 20 + 21 + ----- COMPILED JAVASCRIPT 22 + import * as $wibble from "../wibble.mjs"; 23 + import { Wibble as Wobble, Wibble$Wibble$const as Wibble$Wobble$const } from "../wibble.mjs"; 24 + 25 + export function go(x) { 26 + if (x instanceof Wobble) { 27 + return Wibble$Wobble$const; 28 + } else { 29 + return $wibble.Wibble$Wobble$const; 30 + } 31 + }
+31
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__aliased_variant_still_imported_if_used_in_pattern_matching.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wibble.{Wibble as Wobble}\n\npub fn go(x) {\n case x {\n Wobble -> wibble.Wobble\n _ -> Wobble\n }\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble Wobble } 8 + 9 + -- main.gleam 10 + 11 + import wibble.{Wibble as Wobble} 12 + 13 + pub fn go(x) { 14 + case x { 15 + Wobble -> wibble.Wobble 16 + _ -> Wobble 17 + } 18 + } 19 + 20 + 21 + ----- COMPILED JAVASCRIPT 22 + import * as $wibble from "../wibble.mjs"; 23 + import { Wibble as Wobble, Wibble$Wibble$const as Wibble$Wobble$const } from "../wibble.mjs"; 24 + 25 + export function go(x) { 26 + if (x instanceof Wobble) { 27 + return $wibble.Wibble$Wobble$const; 28 + } else { 29 + return Wibble$Wobble$const; 30 + } 31 + }
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__equality_with_non_singleton_variant.snap
··· 18 18 import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; 19 19 20 20 export class Variant extends $CustomType {} 21 - export const Thing$Variant = () => new Variant(); 21 + export const Thing$Variant$const = new Variant(); 22 + export const Thing$Variant = () => Thing$Variant$const; 22 23 export const Thing$isVariant = (value) => value instanceof Variant; 23 24 24 25 export class Other extends $CustomType {
+26
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__fieldless_variant_still_imported_if_used_in_instanceof_comparison.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wibble.{Wibble}\n\npub fn main() {\n let x = Wibble\n x == Wibble\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble Wobble } 8 + 9 + -- main.gleam 10 + 11 + import wibble.{Wibble} 12 + 13 + pub fn main() { 14 + let x = Wibble 15 + x == Wibble 16 + } 17 + 18 + 19 + ----- COMPILED JAVASCRIPT 20 + import * as $wibble from "../wibble.mjs"; 21 + import { Wibble, Wibble$Wibble$const } from "../wibble.mjs"; 22 + 23 + export function main() { 24 + let x = Wibble$Wibble$const; 25 + return x instanceof Wibble; 26 + }
+33
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__fieldless_variant_still_imported_if_used_in_instanceof_comparison_in_guard.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wibble.{Wibble}\n\npub fn main() {\n let x = Wibble\n case x {\n _ if x == Wibble -> 1\n _ -> 2\n }\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble Wobble } 8 + 9 + -- main.gleam 10 + 11 + import wibble.{Wibble} 12 + 13 + pub fn main() { 14 + let x = Wibble 15 + case x { 16 + _ if x == Wibble -> 1 17 + _ -> 2 18 + } 19 + } 20 + 21 + 22 + ----- COMPILED JAVASCRIPT 23 + import * as $wibble from "../wibble.mjs"; 24 + import { Wibble, Wibble$Wibble$const } from "../wibble.mjs"; 25 + 26 + export function main() { 27 + let x = Wibble$Wibble$const; 28 + if (x instanceof Wibble) { 29 + return 1; 30 + } else { 31 + return 2; 32 + } 33 + }
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__guard_equality_with_non_singleton_variant.snap
··· 21 21 import { CustomType as $CustomType, isEqual } from "../gleam.mjs"; 22 22 23 23 export class Variant extends $CustomType {} 24 - export const Thing$Variant = () => new Variant(); 24 + export const Thing$Variant$const = new Variant(); 25 + export const Thing$Variant = () => Thing$Variant$const; 25 26 export const Thing$isVariant = (value) => value instanceof Variant; 26 27 27 28 export class Other extends $CustomType {
+2 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__mixed_singleton_and_non_singleton.snap
··· 29 29 export const Result$Ok$0 = (value) => value.value; 30 30 31 31 export class Error extends $CustomType {} 32 - export const Result$Error = () => new Error(); 32 + export const Result$Error$const = new Error(); 33 + export const Result$Error = () => Result$Error$const; 33 34 export const Result$isError = (value) => value instanceof Error; 34 35 35 36 export function is_error(r) {
+6 -3
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__multiple_singleton_constructors.snap
··· 23 23 import { CustomType as $CustomType } from "../gleam.mjs"; 24 24 25 25 export class Loading extends $CustomType {} 26 - export const Status$Loading = () => new Loading(); 26 + export const Status$Loading$const = new Loading(); 27 + export const Status$Loading = () => Status$Loading$const; 27 28 export const Status$isLoading = (value) => value instanceof Loading; 28 29 29 30 export class Success extends $CustomType {} 30 - export const Status$Success = () => new Success(); 31 + export const Status$Success$const = new Success(); 32 + export const Status$Success = () => Status$Success$const; 31 33 export const Status$isSuccess = (value) => value instanceof Success; 32 34 33 35 export class Error extends $CustomType {} 34 - export const Status$Error = () => new Error(); 36 + export const Status$Error$const = new Error(); 37 + export const Status$Error = () => Status$Error$const; 35 38 export const Status$isError = (value) => value instanceof Error; 36 39 37 40 export function is_loading(s) {
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__new_type_import_syntax.snap
··· 13 13 14 14 ----- COMPILED JAVASCRIPT 15 15 import * as $a from "../../package/a.mjs"; 16 - import { A } from "../../package/a.mjs"; 16 + import { A$A$const } from "../../package/a.mjs"; 17 17 18 18 export function main() { 19 - return new A(); 19 + return A$A$const; 20 20 }
+1 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__qualified.snap
··· 18 18 import * as $other from "../other.mjs"; 19 19 20 20 export function main() { 21 - return new $other.One(); 21 + return $other.One$One$const; 22 22 }
+30
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__singleton_for_two_aliased_variants.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\nimport wobble.{Wibble as Wobble}\nimport wibble.{Wibble as Wubble}\n\npub fn main() {\n #(Wobble, Wubble)\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + -- wibble.gleam 7 + pub type Wibble { Wibble } 8 + 9 + -- wobble.gleam 10 + pub type Wibble { Wibble } 11 + 12 + -- main.gleam 13 + 14 + import wobble.{Wibble as Wobble} 15 + import wibble.{Wibble as Wubble} 16 + 17 + pub fn main() { 18 + #(Wobble, Wubble) 19 + } 20 + 21 + 22 + ----- COMPILED JAVASCRIPT 23 + import * as $wibble from "../wibble.mjs"; 24 + import { Wibble$Wibble$const as Wibble$Wubble$const } from "../wibble.mjs"; 25 + import * as $wobble from "../wobble.mjs"; 26 + import { Wibble$Wibble$const as Wibble$Wobble$const } from "../wobble.mjs"; 27 + 28 + export function main() { 29 + return [Wibble$Wobble$const, Wibble$Wubble$const]; 30 + }
+4 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__singleton_in_case_guard.snap
··· 21 21 import { CustomType as $CustomType } from "../gleam.mjs"; 22 22 23 23 export class Active extends $CustomType {} 24 - export const State$Active = () => new Active(); 24 + export const State$Active$const = new Active(); 25 + export const State$Active = () => State$Active$const; 25 26 export const State$isActive = (value) => value instanceof Active; 26 27 27 28 export class Inactive extends $CustomType {} 28 - export const State$Inactive = () => new Inactive(); 29 + export const State$Inactive$const = new Inactive(); 30 + export const State$Inactive = () => State$Inactive$const; 29 31 export const State$isInactive = (value) => value instanceof Inactive; 30 32 31 33 export function process(s) {
+4 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__singleton_record_equality.snap
··· 18 18 import { CustomType as $CustomType } from "../gleam.mjs"; 19 19 20 20 export class Wibble extends $CustomType {} 21 - export const Wibble$Wibble = () => new Wibble(); 21 + export const Wibble$Wibble$const = new Wibble(); 22 + export const Wibble$Wibble = () => Wibble$Wibble$const; 22 23 export const Wibble$isWibble = (value) => value instanceof Wibble; 23 24 24 25 export class Wobble extends $CustomType {} 25 - export const Wibble$Wobble = () => new Wobble(); 26 + export const Wibble$Wobble$const = new Wobble(); 27 + export const Wibble$Wobble = () => Wibble$Wobble$const; 26 28 export const Wibble$isWobble = (value) => value instanceof Wobble; 27 29 28 30 export function is_wibble(w) {
+4 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__singleton_record_inequality.snap
··· 18 18 import { CustomType as $CustomType } from "../gleam.mjs"; 19 19 20 20 export class Wibble extends $CustomType {} 21 - export const Wibble$Wibble = () => new Wibble(); 21 + export const Wibble$Wibble$const = new Wibble(); 22 + export const Wibble$Wibble = () => Wibble$Wibble$const; 22 23 export const Wibble$isWibble = (value) => value instanceof Wibble; 23 24 24 25 export class Wobble extends $CustomType {} 25 - export const Wibble$Wobble = () => new Wobble(); 26 + export const Wibble$Wobble$const = new Wobble(); 27 + export const Wibble$Wobble = () => Wibble$Wobble$const; 26 28 export const Wibble$isWobble = (value) => value instanceof Wobble; 27 29 28 30 export function is_not_wibble(w) {
+4 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__singleton_record_reverse_order.snap
··· 18 18 import { CustomType as $CustomType } from "../gleam.mjs"; 19 19 20 20 export class Wibble extends $CustomType {} 21 - export const Wibble$Wibble = () => new Wibble(); 21 + export const Wibble$Wibble$const = new Wibble(); 22 + export const Wibble$Wibble = () => Wibble$Wibble$const; 22 23 export const Wibble$isWibble = (value) => value instanceof Wibble; 23 24 24 25 export class Wobble extends $CustomType {} 25 - export const Wibble$Wobble = () => new Wobble(); 26 + export const Wibble$Wobble$const = new Wobble(); 27 + export const Wibble$Wobble = () => Wibble$Wobble$const; 26 28 export const Wibble$isWobble = (value) => value instanceof Wobble; 27 29 28 30 export function is_wibble_reverse(w) {
+3 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__types_must_be_rendered_before_functions.snap
··· 12 12 import { CustomType as $CustomType } from "../gleam.mjs"; 13 13 14 14 export class One extends $CustomType {} 15 - export const One$One = () => new One(); 15 + export const One$One$const = new One(); 16 + export const One$One = () => One$One$const; 16 17 export const One$isOne = (value) => value instanceof One; 17 18 18 19 export function one() { 19 - return new One(); 20 + return One$One$const; 20 21 }
+5 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_const.snap
··· 17 17 import { CustomType as $CustomType } from "../gleam.mjs"; 18 18 19 19 export class This extends $CustomType {} 20 - export const Mine$This = () => new This(); 20 + export const Mine$This$const = new This(); 21 + export const Mine$This = () => Mine$This$const; 21 22 export const Mine$isThis = (value) => value instanceof This; 22 23 23 24 export class ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant extends $CustomType {} 25 + export const Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant$const = 26 + new ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant(); 24 27 export const Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant = () => 25 - new ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant(); 28 + Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant$const; 26 29 export const Mine$isThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant = (value) => 27 30 value instanceof ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant; 28 31
+1 -1
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_imported.snap
··· 16 16 import * as $other from "../other.mjs"; 17 17 18 18 export function main() { 19 - return new $other.Two(); 19 + return $other.One$Two$const; 20 20 }
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_imported_unqualified.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 import * as $other from "../other.mjs"; 17 - import { Two } from "../other.mjs"; 17 + import { One$Two$const } from "../other.mjs"; 18 18 19 19 export function main() { 20 - return new Two(); 20 + return One$Two$const; 21 21 }
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_imported_unqualified_aliased.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 import * as $other from "../other.mjs"; 17 - import { Two as Three } from "../other.mjs"; 17 + import { One$Two$const as One$Three$const } from "../other.mjs"; 18 18 19 19 export function main() { 20 - return new Three(); 20 + return One$Three$const; 21 21 }
+7 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_literal.snap
··· 19 19 import { CustomType as $CustomType } from "../gleam.mjs"; 20 20 21 21 export class This extends $CustomType {} 22 - export const Mine$This = () => new This(); 22 + export const Mine$This$const = new This(); 23 + export const Mine$This = () => Mine$This$const; 23 24 export const Mine$isThis = (value) => value instanceof This; 24 25 25 26 export class ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant extends $CustomType {} 27 + export const Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant$const = 28 + new ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant(); 26 29 export const Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant = () => 27 - new ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant(); 30 + Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant$const; 28 31 export const Mine$isThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant = (value) => 29 32 value instanceof ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant; 30 33 31 34 export function go() { 32 - new This(); 33 - return new ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant(); 35 + Mine$This$const; 36 + return Mine$ThatOneIsAMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchMuchLongerVariant$const; 34 37 }
+4 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__zero_arity_type_with_import_alias_and_same_named_local_type.snap
··· 35 35 import { Active as WibbleActive } from "../wibble.mjs"; 36 36 37 37 export class Active extends $CustomType {} 38 - export const WobbleStatus$Active = () => new Active(); 38 + export const WobbleStatus$Active$const = new Active(); 39 + export const WobbleStatus$Active = () => WobbleStatus$Active$const; 39 40 export const WobbleStatus$isActive = (value) => value instanceof Active; 40 41 41 42 export class Disabled extends $CustomType {} 42 - export const WobbleStatus$Disabled = () => new Disabled(); 43 + export const WobbleStatus$Disabled$const = new Disabled(); 44 + export const WobbleStatus$Disabled = () => WobbleStatus$Disabled$const; 43 45 export const WobbleStatus$isDisabled = (value) => value instanceof Disabled; 44 46 45 47 export function is_wibble_active(s) {
+8 -8
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__functions__labelled_argument_ordering.snap
··· 41 41 } 42 42 43 43 export function main() { 44 - wibble(new A(), new B(), new C(), new D()); 45 - wibble(new A(), new B(), new C(), new D()); 46 - wibble(new A(), new B(), new C(), new D()); 47 - wibble(new A(), new B(), new C(), new D()); 48 - wibble(new A(), new B(), new C(), new D()); 49 - wibble(new A(), new B(), new C(), new D()); 50 - wibble(new A(), new B(), new C(), new D()); 51 - return wibble(new A(), new B(), new C(), new D()); 44 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 45 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 46 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 47 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 48 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 49 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 50 + wibble(A$A$const, B$B$const, C$C$const, D$D$const); 51 + return wibble(A$A$const, B$B$const, C$C$const, D$D$const); 52 52 }
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__lists__list_constants.snap
··· 9 9 10 10 11 11 ----- COMPILED JAVASCRIPT 12 - import { toList } from "../gleam.mjs"; 12 + import { toList, List$Empty$const as $List$Empty$const } from "../gleam.mjs"; 13 13 14 - export const a = /* @__PURE__ */ toList([]); 14 + export const a = $List$Empty$const; 15 15 16 16 export const b = /* @__PURE__ */ toList([1, 2, 3]);
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__lists__list_literals.snap
··· 13 13 14 14 15 15 ----- COMPILED JAVASCRIPT 16 - import { toList, prepend as listPrepend } from "../gleam.mjs"; 16 + import { toList, List$Empty$const as $List$Empty$const, prepend as listPrepend } from "../gleam.mjs"; 17 17 18 18 export function go(x) { 19 - toList([]); 19 + $List$Empty$const; 20 20 toList([1]); 21 21 toList([1, 2]); 22 22 return listPrepend(1, listPrepend(2, x));
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__lists__tight_empty_list.snap
··· 10 10 11 11 12 12 ----- COMPILED JAVASCRIPT 13 - import { toList } from "../gleam.mjs"; 13 + import { List$Empty$const as $List$Empty$const } from "../gleam.mjs"; 14 14 15 15 export function go(func) { 16 - let huuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuge_variable = toList([]); 16 + let huuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuge_variable = $List$Empty$const; 17 17 return huuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuge_variable; 18 18 }
+32 -30
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__sourcemaps__sourcemap_custom_type_definition.snap
··· 22 22 4 | * Wibble 23 23 5 | */ 24 24 6 |export class Wibble extends $CustomType {} 25 - 7 |export const Wibble$Wibble = () => new Wibble(); 26 - 8 |export const Wibble$isWibble = (value) => value instanceof Wibble; 27 - 9 | 28 - 10 |/** 29 - 11 | * Wobble 30 - 12 | */ 31 - 13 |export class Wobble extends $CustomType { 32 - 14 | constructor(field) { 33 - 15 | super(); 34 - 16 | this.field = field; 35 - 17 | } 36 - 18 |} 37 - 19 |export const Wibble$Wobble = (field) => new Wobble(field); 38 - 20 |export const Wibble$isWobble = (value) => value instanceof Wobble; 39 - 21 |export const Wibble$Wobble$field = (value) => value.field; 40 - 22 |export const Wibble$Wobble$0 = (value) => value.field; 41 - 23 | 42 - 24 |/** 43 - 25 | * Wabble 44 - 26 | */ 45 - 27 |export class Wabble extends $CustomType { 46 - 28 | constructor($0) { 47 - 29 | super(); 48 - 30 | this[0] = $0; 49 - 31 | } 50 - 32 |} 51 - 33 |export const Wibble$Wabble = ($0) => new Wabble($0); 52 - 34 |export const Wibble$isWabble = (value) => value instanceof Wabble; 53 - 35 |export const Wibble$Wabble$0 = (value) => value[0]; 25 + 7 |export const Wibble$Wibble$const = new Wibble(); 26 + 8 |export const Wibble$Wibble = () => Wibble$Wibble$const; 27 + 9 |export const Wibble$isWibble = (value) => value instanceof Wibble; 28 + 10 | 29 + 11 |/** 30 + 12 | * Wobble 31 + 13 | */ 32 + 14 |export class Wobble extends $CustomType { 33 + 15 | constructor(field) { 34 + 16 | super(); 35 + 17 | this.field = field; 36 + 18 | } 37 + 19 |} 38 + 20 |export const Wibble$Wobble = (field) => new Wobble(field); 39 + 21 |export const Wibble$isWobble = (value) => value instanceof Wobble; 40 + 22 |export const Wibble$Wobble$field = (value) => value.field; 41 + 23 |export const Wibble$Wobble$0 = (value) => value.field; 42 + 24 | 43 + 25 |/** 44 + 26 | * Wabble 45 + 27 | */ 46 + 28 |export class Wabble extends $CustomType { 47 + 29 | constructor($0) { 48 + 30 | super(); 49 + 31 | this[0] = $0; 50 + 32 | } 51 + 33 |} 52 + 34 |export const Wibble$Wabble = ($0) => new Wabble($0); 53 + 35 |export const Wibble$isWabble = (value) => value instanceof Wabble; 54 + 36 |export const Wibble$Wabble$0 = (value) => value[0]; 54 55 55 56 ----- SOURCE MAP 56 57 File: my/mod.mjs ··· 83 84 84 85 85 86 export class Wibble extends $CustomType {} 86 - export const Wibble$Wibble = () => new Wibble(); 87 + export const Wibble$Wibble$const = new Wibble(); 88 + export const Wibble$Wibble = () => Wibble$Wibble$const; 87 89 export const Wibble$isWibble = (value) => value instanceof Wibble; 88 90 89 91
+15 -13
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__sourcemaps__sourcemap_custom_type_definition_with_unused.snap
··· 26 26 4 | * Wibble 27 27 5 | */ 28 28 6 |export class Wibble extends $CustomType {} 29 - 7 |export const Wibble$Wibble = () => new Wibble(); 30 - 8 |export const Wibble$isWibble = (value) => value instanceof Wibble; 31 - 9 | 32 - 10 |export class Wobble extends $CustomType { 33 - 11 | constructor($0) { 34 - 12 | super(); 35 - 13 | this[0] = $0; 36 - 14 | } 37 - 15 |} 38 - 16 |export const Wobble$Wobble = ($0) => new Wobble($0); 39 - 17 |export const Wobble$isWobble = (value) => value instanceof Wobble; 40 - 18 |export const Wobble$Wobble$0 = (value) => value[0]; 29 + 7 |export const Wibble$Wibble$const = new Wibble(); 30 + 8 |export const Wibble$Wibble = () => Wibble$Wibble$const; 31 + 9 |export const Wibble$isWibble = (value) => value instanceof Wibble; 32 + 10 | 33 + 11 |export class Wobble extends $CustomType { 34 + 12 | constructor($0) { 35 + 13 | super(); 36 + 14 | this[0] = $0; 37 + 15 | } 38 + 16 |} 39 + 17 |export const Wobble$Wobble = ($0) => new Wobble($0); 40 + 18 |export const Wobble$isWobble = (value) => value instanceof Wobble; 41 + 19 |export const Wobble$Wobble$0 = (value) => value[0]; 41 42 42 43 ----- SOURCE MAP 43 44 File: my/mod.mjs ··· 70 71 } 71 72 72 73 export class Wibble extends $CustomType {} 73 - export const Wibble$Wibble = () => new Wibble(); 74 + export const Wibble$Wibble$const = new Wibble(); 75 + export const Wibble$Wibble = () => Wibble$Wibble$const; 74 76 export const Wibble$isWibble = (value) => value instanceof Wibble; 75 77 ----- 76 78
+1 -1
compiler-core/src/javascript/typescript.rs
··· 439 439 let definition = if constructors.is_empty() { 440 440 if let Some((module, external_name, _location)) = external_javascript { 441 441 let member = Member { 442 - name: external_name.to_doc(), 442 + name: external_name.clone(), 443 443 alias: Some(eco_format!("{name}$").to_doc()), 444 444 }; 445 445 imports.register_export(eco_format!("{name}$"));
+20
compiler-core/src/type_.rs
··· 355 355 } 356 356 } 357 357 358 + pub fn named_type_name_and_package(&self) -> Option<(EcoString, EcoString, EcoString)> { 359 + match self { 360 + Self::Named { 361 + package, 362 + module, 363 + name, 364 + .. 365 + } => Some((package.clone(), module.clone(), name.clone())), 366 + Self::Var { type_ } => type_.borrow().named_type_name_and_package(), 367 + Self::Fn { .. } | Self::Tuple { .. } => None, 368 + } 369 + } 370 + 358 371 pub fn set_custom_type_variant(&mut self, index: u16) { 359 372 match self { 360 373 Type::Named { ··· 1416 1429 pub fn named_type_name(&self) -> Option<(EcoString, EcoString)> { 1417 1430 match self { 1418 1431 Self::Link { type_ } => type_.named_type_name(), 1432 + Self::Unbound { .. } | Self::Generic { .. } => None, 1433 + } 1434 + } 1435 + 1436 + pub fn named_type_name_and_package(&self) -> Option<(EcoString, EcoString, EcoString)> { 1437 + match self { 1438 + Self::Link { type_ } => type_.named_type_name_and_package(), 1419 1439 Self::Unbound { .. } | Self::Generic { .. } => None, 1420 1440 } 1421 1441 }
+6 -5
compiler-core/templates/prelude.mjs
··· 73 73 } 74 74 } 75 75 76 - export class Empty extends List {} 77 - export const List$Empty = () => new Empty(); 76 + export class Empty extends List { } 77 + export const List$Empty$const = new Empty(); 78 + export const List$Empty = () => List$Empty$const; 78 79 export const List$isEmpty = (value) => value instanceof Empty; 79 80 80 81 export class NonEmpty extends List { ··· 575 576 return new BitArray(segment); 576 577 } 577 578 578 - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); 579 + return new BitArray(new Uint8Array(/** @type {number[]} */(segments))); 579 580 } 580 581 581 582 // Count the total number of bits and check if all segments are numbers, i.e. ··· 597 598 // If all segments are numbers then pass the segments array directly to the 598 599 // Uint8Array constructor 599 600 if (areAllSegmentsNumbers) { 600 - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); 601 + return new BitArray(new Uint8Array(/** @type {number[]} */(segments))); 601 602 } 602 603 603 604 // Pack the segments into a Uint8Array ··· 1458 1459 try { 1459 1460 if (a.equals(b)) continue; 1460 1461 else return false; 1461 - } catch {} 1462 + } catch { } 1462 1463 } 1463 1464 1464 1465 let [keys, get] = getters(a);
+3 -2
test-package-compiler/src/snapshots/test_package_compiler__generated_tests__javascript_d_ts.snap
··· 34 34 import { CustomType as $CustomType } from "./gleam.mjs"; 35 35 36 36 export class Woo extends $CustomType {} 37 - export const Wibble$Woo = () => new Woo(); 37 + export const Wibble$Woo$const = new Woo(); 38 + export const Wibble$Woo = () => Wibble$Woo$const; 38 39 export const Wibble$isWoo = (value) => value instanceof Woo; 39 40 40 41 export function wobble() { 41 - return new Woo(); 42 + return Wibble$Woo$const; 42 43 }
+2 -1
test-package-compiler/src/snapshots/test_package_compiler__generated_tests__javascript_import.snap
··· 38 38 import { CustomType as $CustomType } from "../gleam.mjs"; 39 39 40 40 export class A extends $CustomType {} 41 - export const A$A = () => new A(); 41 + export const A$A$const = new A(); 42 + export const A$A = () => A$A$const; 42 43 export const A$isA = (value) => value instanceof A; 43 44 44 45
+4 -3
test-package-compiler/src/snapshots/test_package_compiler__generated_tests__javascript_sourcemaps.snap
··· 27 27 import { CustomType as $CustomType } from "./gleam.mjs"; 28 28 29 29 export class Woo extends $CustomType {} 30 - export const Wibble$Woo = () => new Woo(); 30 + export const Wibble$Woo$const = new Woo(); 31 + export const Wibble$Woo = () => Wibble$Woo$const; 31 32 export const Wibble$isWoo = (value) => value instanceof Woo; 32 33 33 34 export function wobble() { 34 - return new Woo(); 35 + return Wibble$Woo$const; 35 36 } 36 37 37 38 38 39 //// /out/lib/the_package/hello.mjs.map 39 - {"version":3,"file":"hello.mjs","sources":["hello.gleam"],"names":[],"mappings":";;;AAAA,AACE;AAAA;AAAA,4DACD;;AAED;EACE;CACD"} 40 + {"version":3,"file":"hello.mjs","sources":["hello.gleam"],"names":[],"mappings":";;;AAAA,AACE;AAAA;;AAAA,4DACD;;AAED;EACE;CACD"}