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

Configure Feed

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

Be more strict with block lifting

+377 -260
+171 -73
compiler-core/src/javascript/expression.rs
··· 19 19 #[derive(Debug, Clone)] 20 20 pub enum Position { 21 21 Tail, 22 - NotTail, 22 + NotTail(Ordering), 23 23 /// We are compiling an expression inside a block, meaning we must assign 24 24 /// to the `_block` variable at the end of the scope, because blocks are not 25 25 /// expressions in JS. ··· 37 37 pub fn is_tail(&self) -> bool { 38 38 matches!(self, Self::Tail) 39 39 } 40 + } 41 + 42 + #[derive(Debug, Clone, Copy)] 43 + pub enum Ordering { 44 + Strict, 45 + Loose, 40 46 } 41 47 42 48 #[derive(Debug)] ··· 168 174 TypedExpr::Float { value, .. } => Ok(float(value)), 169 175 170 176 TypedExpr::List { elements, tail, .. } => { 171 - self.not_in_tail_position(|r#gen| match tail { 177 + self.not_in_tail_position(Ordering::Strict, |r#gen| match tail { 172 178 Some(tail) => { 173 179 r#gen.tracker.prepend_used = true; 174 180 let tail = r#gen.wrap_expression(tail)?; ··· 245 251 let expression = expression 246 252 .as_ref() 247 253 .expect("echo with no expression outside of pipe"); 248 - let expresion_doc = 249 - self.not_in_tail_position(|this| this.wrap_expression(expression))?; 254 + let expresion_doc = self.not_in_tail_position(Ordering::Strict, |this| { 255 + this.wrap_expression(expression) 256 + })?; 250 257 self.echo(expresion_doc, location) 251 258 } 252 259 ··· 262 269 } 263 270 264 271 fn negate_with(&mut self, with: &'static str, value: &'a TypedExpr) -> Output<'a> { 265 - self.not_in_tail_position(|r#gen| Ok(docvec![with, r#gen.wrap_expression(value)?])) 272 + self.not_in_tail_position(Ordering::Strict, |r#gen| { 273 + Ok(docvec![with, r#gen.wrap_expression(value)?]) 274 + }) 266 275 } 267 276 268 277 fn bit_array(&mut self, segments: &'a [TypedExprBitArraySegment]) -> Output<'a> { ··· 272 281 273 282 // Collect all the values used in segments. 274 283 let segments_array = array(segments.iter().map(|segment| { 275 - let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(&segment.value))?; 284 + let value = self.not_in_tail_position(Ordering::Strict, |r#gen| { 285 + r#gen.wrap_expression(&segment.value) 286 + })?; 276 287 277 288 if segment.type_ == crate::type_::int() || segment.type_ == crate::type_::float() { 278 289 let details = self.sized_bit_array_segment_details(segment)?; ··· 421 432 (Some(size_value), size) 422 433 } 423 434 _ => { 424 - let mut size = 425 - self.not_in_tail_position(|r#gen| r#gen.wrap_expression(size))?; 435 + let mut size = self.not_in_tail_position(Ordering::Strict, |r#gen| { 436 + r#gen.wrap_expression(size) 437 + })?; 426 438 427 439 if unit != 1 { 428 440 size = size.group().append(" * ".to_doc().append(unit.to_doc())); ··· 452 464 pub fn wrap_return(&mut self, document: Document<'a>) -> Document<'a> { 453 465 match &self.scope_position { 454 466 Position::Tail => docvec!["return ", document, ";"], 455 - Position::NotTail => document, 467 + Position::NotTail(_) => document, 456 468 Position::Assign(name) => docvec![name.clone(), " = ", document, ";"], 457 469 } 458 470 } 459 471 460 - pub fn not_in_tail_position<CompileFn>(&mut self, compile: CompileFn) -> Output<'a> 472 + pub fn not_in_tail_position<CompileFn>( 473 + &mut self, 474 + ordering: Ordering, 475 + compile: CompileFn, 476 + ) -> Output<'a> 461 477 where 462 478 CompileFn: Fn(&mut Self) -> Output<'a>, 463 479 { 464 - let function_position = std::mem::replace(&mut self.function_position, Position::NotTail); 465 - let scope_position = std::mem::replace(&mut self.scope_position, Position::NotTail); 480 + let function_position = 481 + std::mem::replace(&mut self.function_position, Position::NotTail(ordering)); 482 + let scope_position = 483 + std::mem::replace(&mut self.scope_position, Position::NotTail(ordering)); 466 484 467 485 let result = compile(self); 468 486 ··· 471 489 result 472 490 } 473 491 474 - fn wrap_block<CompileFn>(&mut self, compile: CompileFn) -> Output<'a> 475 - where 476 - CompileFn: Fn(&mut Self) -> Output<'a>, 477 - { 478 - let block_variable = self.next_local_var(&BLOCK_VARIABLE.into()); 479 - 480 - // Save initial state 481 - let scope_position = std::mem::replace( 482 - &mut self.scope_position, 483 - Position::Assign(block_variable.clone()), 484 - ); 485 - let function_position = std::mem::replace(&mut self.function_position, Position::NotTail); 486 - 487 - // Generate the expression 488 - let statement_doc = compile(self)?; 489 - self.statement_level 490 - .push(docvec!["let ", block_variable.clone(), ";"]); 491 - self.statement_level.push(statement_doc); 492 - 493 - // Reset 494 - self.scope_position = scope_position; 495 - self.function_position = function_position; 496 - 497 - Ok(self.wrap_return(block_variable.to_doc())) 498 - } 499 - 500 492 /// Use the `_block` variable if the expression is JS statement. 501 493 pub fn wrap_expression(&mut self, expression: &'a TypedExpr) -> Output<'a> { 502 - match expression { 503 - TypedExpr::Panic { .. } 504 - | TypedExpr::Todo { .. } 505 - | TypedExpr::Case { .. } 506 - | TypedExpr::Pipeline { .. } 507 - | TypedExpr::RecordUpdate { .. } => self.wrap_block(|this| this.expression(expression)), 494 + match (expression, &self.scope_position) { 495 + (_, Position::Tail | Position::Assign(_)) => self.expression(expression), 496 + ( 497 + TypedExpr::Panic { .. } 498 + | TypedExpr::Todo { .. } 499 + | TypedExpr::Case { .. } 500 + | TypedExpr::Pipeline { .. } 501 + | TypedExpr::RecordUpdate { .. }, 502 + Position::NotTail(Ordering::Loose), 503 + ) => self.wrap_block(|this| this.expression(expression)), 504 + ( 505 + TypedExpr::Panic { .. } 506 + | TypedExpr::Todo { .. } 507 + | TypedExpr::Case { .. } 508 + | TypedExpr::Pipeline { .. } 509 + | TypedExpr::RecordUpdate { .. }, 510 + Position::NotTail(Ordering::Strict), 511 + ) => self.immediately_invoked_function_expression(expression, |r#gen, expr| { 512 + r#gen.expression(expr) 513 + }), 508 514 _ => self.expression(expression), 509 515 } 510 516 } ··· 525 531 // Here the document is a return statement: `return <expr>;` 526 532 // or an assignment: `_block = <expr>;` 527 533 Position::Tail | Position::Assign(_) => document, 528 - Position::NotTail => docvec!["(", document, ")"], 534 + Position::NotTail(_) => docvec!["(", document, ")"], 529 535 }) 530 536 } 531 537 538 + /// Wrap an expression in an immediately invoked function expression 539 + fn immediately_invoked_function_expression<T, ToDoc>( 540 + &mut self, 541 + statements: &'a T, 542 + to_doc: ToDoc, 543 + ) -> Output<'a> 544 + where 545 + ToDoc: FnOnce(&mut Self, &'a T) -> Output<'a>, 546 + { 547 + // Save initial state 548 + let scope_position = std::mem::replace(&mut self.scope_position, Position::Tail); 549 + 550 + // Set state for in this iife 551 + let current_scope_vars = self.current_scope_vars.clone(); 552 + 553 + // Generate the expression 554 + let result = to_doc(self, statements); 555 + 556 + // Reset 557 + self.current_scope_vars = current_scope_vars; 558 + self.scope_position = scope_position; 559 + 560 + // Wrap in iife document 561 + let doc = immediately_invoked_function_expression_document(result?); 562 + Ok(self.wrap_return(doc)) 563 + } 564 + 565 + fn wrap_block<CompileFn>(&mut self, compile: CompileFn) -> Output<'a> 566 + where 567 + CompileFn: Fn(&mut Self) -> Output<'a>, 568 + { 569 + let block_variable = self.next_local_var(&BLOCK_VARIABLE.into()); 570 + 571 + // Save initial state 572 + let scope_position = std::mem::replace( 573 + &mut self.scope_position, 574 + Position::Assign(block_variable.clone()), 575 + ); 576 + let function_position = std::mem::replace( 577 + &mut self.function_position, 578 + Position::NotTail(Ordering::Strict), 579 + ); 580 + 581 + // Generate the expression 582 + let statement_doc = compile(self); 583 + 584 + // Reset 585 + self.scope_position = scope_position; 586 + self.function_position = function_position; 587 + 588 + self.statement_level 589 + .push(docvec!["let ", block_variable.clone(), ";"]); 590 + self.statement_level.push(statement_doc?); 591 + 592 + Ok(self.wrap_return(block_variable.to_doc())) 593 + } 594 + 532 595 fn variable(&mut self, name: &'a EcoString, constructor: &'a ValueConstructor) -> Output<'a> { 533 596 match &constructor.variant { 534 597 ValueConstructorVariant::LocalConstant { literal } => { ··· 566 629 expression: None, 567 630 location, 568 631 .. 569 - } => documents.push(self.not_in_tail_position(|this| { 632 + } => documents.push(self.not_in_tail_position(Ordering::Strict, |this| { 570 633 let var = latest_local_var 571 634 .as_ref() 572 635 .expect("echo with no previous step in a pipe"); ··· 575 638 576 639 // Otherwise we assign the intermediate pipe value to a variable. 577 640 _ => { 578 - documents.push(self.not_in_tail_position(|this| { 641 + documents.push(self.not_in_tail_position(Ordering::Strict, |this| { 579 642 this.simple_variable_assignment(&assignment.name, &assignment.value) 580 643 })?); 581 644 latest_local_var = Some(self.local_var(&assignment.name)); ··· 621 684 } else { 622 685 match &self.scope_position { 623 686 Position::Tail | Position::Assign(_) => self.block_document(statements), 624 - Position::NotTail => self.wrap_block(|this| { 687 + Position::NotTail(Ordering::Strict) => self 688 + .immediately_invoked_function_expression(statements, |r#gen, statements| { 689 + r#gen.statements(statements) 690 + }), 691 + Position::NotTail(Ordering::Loose) => self.wrap_block(|this| { 625 692 // Save previous scope 626 693 let current_scope_vars = this.current_scope_vars.clone(); 627 694 ··· 654 721 let mut documents = Vec::with_capacity(count * 3); 655 722 for (i, statement) in statements.iter().enumerate() { 656 723 if i + 1 < count { 657 - documents.push(self.not_in_tail_position(|r#gen| r#gen.statement(statement))?); 724 + documents.push( 725 + self.not_in_tail_position(Ordering::Loose, |r#gen| r#gen.statement(statement))?, 726 + ); 658 727 if requires_semicolon(statement) { 659 728 documents.push(";".to_doc()); 660 729 } ··· 677 746 value: &'a TypedExpr, 678 747 ) -> Output<'a> { 679 748 // Subject must be rendered before the variable for variable numbering 680 - let subject = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 749 + let subject = 750 + self.not_in_tail_position(Ordering::Loose, |r#gen| r#gen.wrap_expression(value))?; 681 751 let js_name = self.next_local_var(name); 682 752 let assignment = docvec!["let ", js_name.clone(), " = ", subject, ";"]; 683 753 let assignment = if self.scope_position.is_tail() { ··· 707 777 // Otherwise we need to compile the patterns 708 778 let (subject, subject_assignment) = pattern::assign_subject(self, value); 709 779 // Value needs to be rendered before traversing pattern to have correctly incremented variables. 710 - let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 780 + let value = 781 + self.not_in_tail_position(Ordering::Loose, |r#gen| r#gen.wrap_expression(value))?; 711 782 let mut pattern_generator = pattern::Generator::new(self); 712 783 pattern_generator.traverse_pattern(&subject, pattern)?; 713 784 let compiled = pattern_generator.take_compiled(); ··· 831 902 .zip(subject_values) 832 903 .flat_map(|(assignment_name, value)| assignment_name.map(|name| (name, value))) 833 904 .map(|(name, value)| { 834 - let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 905 + let value = self 906 + .not_in_tail_position(Ordering::Strict, |r#gen| r#gen.wrap_expression(value))?; 835 907 Ok(docvec!["let ", name, " = ", value, ";", line()]) 836 908 }) 837 909 .try_collect()?; ··· 846 918 message: Option<&'a TypedExpr>, 847 919 ) -> Output<'a> { 848 920 let message = match message { 849 - Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 921 + Some(m) => self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.expression(m))?, 850 922 None => string("Pattern match failed, no pattern matched the value."), 851 923 }; 852 924 ··· 854 926 } 855 927 856 928 fn tuple(&mut self, elements: &'a [TypedExpr]) -> Output<'a> { 857 - self.not_in_tail_position(|r#gen| { 929 + self.not_in_tail_position(Ordering::Strict, |r#gen| { 858 930 array( 859 931 elements 860 932 .iter() ··· 866 938 fn call(&mut self, fun: &'a TypedExpr, arguments: &'a [TypedCallArg]) -> Output<'a> { 867 939 let arguments = arguments 868 940 .iter() 869 - .map(|element| self.not_in_tail_position(|r#gen| r#gen.wrap_expression(&element.value))) 941 + .map(|element| { 942 + self.not_in_tail_position(Ordering::Strict, |r#gen| { 943 + r#gen.wrap_expression(&element.value) 944 + }) 945 + }) 870 946 .try_collect()?; 871 947 872 948 self.call_with_doc_args(fun, arguments) ··· 943 1019 } 944 1020 945 1021 _ => { 946 - let fun = self.not_in_tail_position(|r#gen| { 1022 + let fun = self.not_in_tail_position(Ordering::Strict, |r#gen| { 947 1023 let is_fn_literal = matches!(fun, TypedExpr::Fn { .. }); 948 1024 let fun = r#gen.wrap_expression(fun)?; 949 1025 if is_fn_literal { ··· 998 1074 } 999 1075 1000 1076 fn record_access(&mut self, record: &'a TypedExpr, label: &'a str) -> Output<'a> { 1001 - self.not_in_tail_position(|r#gen| { 1077 + self.not_in_tail_position(Ordering::Strict, |r#gen| { 1002 1078 let record = r#gen.wrap_expression(record)?; 1003 1079 Ok(docvec![record, ".", maybe_escape_property_doc(label)]) 1004 1080 }) ··· 1011 1087 args: &'a [TypedCallArg], 1012 1088 ) -> Output<'a> { 1013 1089 Ok(docvec![ 1014 - self.not_in_tail_position(|r#gen| r#gen.assignment(record))?, 1090 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.assignment(record))?, 1015 1091 line(), 1016 1092 self.call(constructor, args)?, 1017 1093 ]) 1018 1094 } 1019 1095 1020 1096 fn tuple_index(&mut self, tuple: &'a TypedExpr, index: u64) -> Output<'a> { 1021 - self.not_in_tail_position(|r#gen| { 1097 + self.not_in_tail_position(Ordering::Strict, |r#gen| { 1022 1098 let tuple = r#gen.wrap_expression(tuple)?; 1023 1099 Ok(docvec![tuple, eco_format!("[{index}]")]) 1024 1100 }) ··· 1046 1122 } 1047 1123 1048 1124 fn div_int(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 1049 - let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1050 - let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1125 + let left = 1126 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(left))?; 1127 + let right = 1128 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(right))?; 1051 1129 self.tracker.int_division_used = true; 1052 1130 Ok(docvec!["divideInt", wrap_args([left, right])]) 1053 1131 } 1054 1132 1055 1133 fn remainder_int(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 1056 - let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1057 - let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1134 + let left = 1135 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(left))?; 1136 + let right = 1137 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(right))?; 1058 1138 self.tracker.int_remainder_used = true; 1059 1139 Ok(docvec!["remainderInt", wrap_args([left, right])]) 1060 1140 } 1061 1141 1062 1142 fn div_float(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 1063 - let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1064 - let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1143 + let left = 1144 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(left))?; 1145 + let right = 1146 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(right))?; 1065 1147 self.tracker.float_division_used = true; 1066 1148 Ok(docvec!["divideFloat", wrap_args([left, right])]) 1067 1149 } ··· 1074 1156 ) -> Output<'a> { 1075 1157 // If it is a simple scalar type then we can use JS' reference identity 1076 1158 if is_js_scalar(left.type_()) { 1077 - let left_doc = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1078 - let right_doc = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1159 + let left_doc = 1160 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(left))?; 1161 + let right_doc = 1162 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(right))?; 1079 1163 let operator = if should_be_equal { " === " } else { " !== " }; 1080 1164 return Ok(docvec![left_doc, operator, right_doc]); 1081 1165 } 1082 1166 1083 1167 // Other types must be compared using structural equality 1084 - let left = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(left))?; 1085 - let right = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(right))?; 1168 + let left = 1169 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.wrap_expression(left))?; 1170 + let right = 1171 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.wrap_expression(right))?; 1086 1172 Ok(self.prelude_equal_call(should_be_equal, left, right)) 1087 1173 } 1088 1174 ··· 1110 1196 right: &'a TypedExpr, 1111 1197 op: &'a str, 1112 1198 ) -> Output<'a> { 1113 - let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1114 - let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1199 + let left = 1200 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(left))?; 1201 + let right = 1202 + self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.child_expression(right))?; 1115 1203 Ok(docvec![left, " ", op, " ", right]) 1116 1204 } 1117 1205 1118 1206 fn todo(&mut self, message: Option<&'a TypedExpr>, location: &'a SrcSpan) -> Output<'a> { 1119 1207 let message = match message { 1120 - Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 1208 + Some(m) => self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.expression(m))?, 1121 1209 None => string("`todo` expression evaluated. This code has not yet been implemented."), 1122 1210 }; 1123 1211 let doc = self.throw_error("todo", &message, *location, vec![]); ··· 1127 1215 1128 1216 fn panic(&mut self, location: &'a SrcSpan, message: Option<&'a TypedExpr>) -> Output<'a> { 1129 1217 let message = match message { 1130 - Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 1218 + Some(m) => self.not_in_tail_position(Ordering::Strict, |r#gen| r#gen.expression(m))?, 1131 1219 None => string("`panic` expression evaluated."), 1132 1220 }; 1133 1221 let doc = self.throw_error("panic", &message, *location, vec![]); ··· 1954 2042 Statement::Assignment(_) => false, 1955 2043 Statement::Use(_) => false, 1956 2044 } 2045 + } 2046 + 2047 + /// Wrap a document in an immediately invoked function expression 2048 + fn immediately_invoked_function_expression_document(document: Document<'_>) -> Document<'_> { 2049 + docvec![ 2050 + docvec!["(() => {", break_("", " "), document].nest(INDENT), 2051 + break_("", " "), 2052 + "})()", 2053 + ] 2054 + .group() 1957 2055 } 1958 2056 1959 2057 fn record_constructor<'a>(
+7 -7
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__blocks__concat_blocks.snap
··· 17 17 18 18 ----- COMPILED JAVASCRIPT 19 19 function main(f, a, b) { 20 - let _block; 21 - let _pipe = a; 22 - _block = f(_pipe); 23 - let _block$1; 24 - let _pipe$1 = b; 25 - _block$1 = f(_pipe$1); 26 - return _block + _block$1; 20 + return (() => { 21 + let _pipe = a; 22 + return f(_pipe); 23 + })() + (() => { 24 + let _pipe = b; 25 + return f(_pipe); 26 + })(); 27 27 }
+3 -5
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__blocks__left_operator_sequence.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 function go() { 17 - let _block; 18 - { 17 + return 1 === (() => { 19 18 1; 20 - _block = 2; 21 - } 22 - return 1 === _block; 19 + return 2; 20 + })(); 23 21 }
+3 -5
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__blocks__right_operator_sequence.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 function go() { 17 - let _block; 18 - { 17 + return (() => { 19 18 1; 20 - _block = 2; 21 - } 22 - return _block === 1; 19 + return 2; 20 + })() === 1; 23 21 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__binop_panic_left.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "panic", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`panic` expression evaluated.", 21 - {} 22 - ) 23 - return _block && x; 14 + return (() => { 15 + throw makeError( 16 + "panic", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`panic` expression evaluated.", 21 + {} 22 + ) 23 + })() && x; 24 24 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__binop_panic_right.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "panic", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`panic` expression evaluated.", 21 - {} 22 - ) 23 - return x && _block; 14 + return x && (() => { 15 + throw makeError( 16 + "panic", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`panic` expression evaluated.", 21 + {} 22 + ) 23 + })(); 24 24 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__binop_todo_left.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "todo", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`todo` expression evaluated. This code has not yet been implemented.", 21 - {} 22 - ) 23 - return _block && x; 14 + return (() => { 15 + throw makeError( 16 + "todo", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`todo` expression evaluated. This code has not yet been implemented.", 21 + {} 22 + ) 23 + })() && x; 24 24 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__binop_todo_right.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "todo", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`todo` expression evaluated. This code has not yet been implemented.", 21 - {} 22 - ) 23 - return x && _block; 14 + return x && (() => { 15 + throw makeError( 16 + "todo", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`todo` expression evaluated. This code has not yet been implemented.", 21 + {} 22 + ) 23 + })(); 24 24 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__negate_panic.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "panic", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`panic` expression evaluated.", 21 - {} 22 - ) 23 - return !_block; 14 + return !(() => { 15 + throw makeError( 16 + "panic", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`panic` expression evaluated.", 21 + {} 22 + ) 23 + })(); 24 24 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__negate_todo.snap
··· 11 11 import { makeError } from "../gleam.mjs"; 12 12 13 13 export function negate(x) { 14 - let _block; 15 - throw makeError( 16 - "todo", 17 - "my/mod", 18 - 2, 19 - "negate", 20 - "`todo` expression evaluated. This code has not yet been implemented.", 21 - {} 22 - ) 23 - return !_block; 14 + return !(() => { 15 + throw makeError( 16 + "todo", 17 + "my/mod", 18 + 2, 19 + "negate", 20 + "`todo` expression evaluated. This code has not yet been implemented.", 21 + {} 22 + ) 23 + })(); 24 24 }
+3 -5
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bools__negation_block.snap
··· 12 12 13 13 ----- COMPILED JAVASCRIPT 14 14 export function negate(x) { 15 - let _block; 16 - { 15 + return !(() => { 17 16 123; 18 - _block = x; 19 - } 20 - return !_block; 17 + return x; 18 + })(); 21 19 }
+7 -7
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__called_case.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 function go(x, y) { 17 - let _block; 18 - if (x === 0) { 19 - _block = y; 20 - } else { 21 - _block = y; 22 - } 23 - return _block(); 17 + return (() => { 18 + if (x === 0) { 19 + return y; 20 + } else { 21 + return y; 22 + } 23 + })()(); 24 24 }
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__pipe.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 function go(x, f) { 17 - let _block; 18 - let _pipe = x; 19 - _block = f(_pipe); 20 - let $ = _block; 17 + let $ = (() => { 18 + let _pipe = x; 19 + return f(_pipe); 20 + })(); 21 21 if ($ === 0) { 22 22 return 1; 23 23 } else {
+8 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__echo__echo_with_a_block.snap
··· 24 24 } from "../gleam.mjs"; 25 25 26 26 export function main() { 27 - let _block; 28 - { 29 - undefined; 30 - _block = 1; 31 - } 32 - return echo(_block, "src/module.gleam", 3); 27 + return echo( 28 + (() => { 29 + undefined; 30 + return 1; 31 + })(), 32 + "src/module.gleam", 33 + 3, 34 + ); 33 35 } 34 36 35 37 // ...omitted code from `templates/echo.mjs`...
+10 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__echo__echo_with_a_case_expression.snap
··· 23 23 } from "../gleam.mjs"; 24 24 25 25 export function main() { 26 - let _block; 27 - let $ = 1; 28 - { 29 - _block = 2; 30 - } 31 - return echo(_block, "src/module.gleam", 3); 26 + return echo( 27 + (() => { 28 + let $ = 1; 29 + { 30 + return 2; 31 + } 32 + })(), 33 + "src/module.gleam", 34 + 3, 35 + ); 32 36 } 33 37 34 38 // ...omitted code from `templates/echo.mjs`...
+13 -9
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__echo__echo_with_a_panic.snap
··· 22 22 } from "../gleam.mjs"; 23 23 24 24 export function main() { 25 - let _block; 26 - throw makeError( 27 - "panic", 28 - "my/mod", 25 + return echo( 26 + (() => { 27 + throw makeError( 28 + "panic", 29 + "my/mod", 30 + 3, 31 + "main", 32 + "`panic` expression evaluated.", 33 + {} 34 + ) 35 + })(), 36 + "src/module.gleam", 29 37 3, 30 - "main", 31 - "`panic` expression evaluated.", 32 - {} 33 - ) 34 - return echo(_block, "src/module.gleam", 3); 38 + ); 35 39 } 36 40 37 41 // ...omitted code from `templates/echo.mjs`...
+9 -7
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__functions__case_in_call.snap
··· 13 13 14 14 ----- COMPILED JAVASCRIPT 15 15 export function main(f, x) { 16 - let _block; 17 - if (x === 1) { 18 - _block = 2; 19 - } else { 20 - _block = 0; 21 - } 22 - return f(_block); 16 + return f( 17 + (() => { 18 + if (x === 1) { 19 + return 2; 20 + } else { 21 + return 0; 22 + } 23 + })(), 24 + ); 23 25 }
+10 -7
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__functions__two_pipes_in_a_row.snap
··· 24 24 } 25 25 26 26 export function main() { 27 - let _block; 28 - let _pipe = () => { return 1; }; 29 - _block = new Function(_pipe); 30 - let _block$1; 31 - let _pipe$1 = () => { return 2; }; 32 - _block$1 = new Function(_pipe$1); 33 - return toList([_block, _block$1]); 27 + return toList([ 28 + (() => { 29 + let _pipe = () => { return 1; }; 30 + return new Function(_pipe); 31 + })(), 32 + (() => { 33 + let _pipe = () => { return 2; }; 34 + return new Function(_pipe); 35 + })(), 36 + ]); 34 37 }
+6 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__lists__multi_line_list_literals.snap
··· 13 13 import { toList } from "../gleam.mjs"; 14 14 15 15 function go(x) { 16 - let _block; 17 - { 18 - true; 19 - _block = 1; 20 - } 21 - return toList([_block]); 16 + return toList([ 17 + (() => { 18 + true; 19 + return 1; 20 + })(), 21 + ]); 22 22 }
+11 -8
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__numbers__float_divide_complex_expr.snap
··· 16 16 import { divideFloat } from "../gleam.mjs"; 17 17 18 18 function go() { 19 - let _block; 20 - let $ = 1.0 >= 0.0; 21 - if ($) { 22 - _block = 2.0; 23 - } else { 24 - _block = 4.0; 25 - } 26 - return divideFloat(_block, 2.0); 19 + return divideFloat( 20 + (() => { 21 + let $ = 1.0 >= 0.0; 22 + if ($) { 23 + return 2.0; 24 + } else { 25 + return 4.0; 26 + } 27 + })(), 28 + 2.0 29 + ); 27 30 }
+11 -8
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__numbers__int_divide_complex_expr.snap
··· 16 16 import { divideInt } from "../gleam.mjs"; 17 17 18 18 function go() { 19 - let _block; 20 - let $ = 1 >= 0; 21 - if ($) { 22 - _block = 2; 23 - } else { 24 - _block = 4; 25 - } 26 - return divideInt(_block, 2); 19 + return divideInt( 20 + (() => { 21 + let $ = 1 >= 0; 22 + if ($) { 23 + return 2; 24 + } else { 25 + return 4; 26 + } 27 + })(), 28 + 2 29 + ); 27 30 }
+11 -8
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__numbers__int_mod_complex_expr.snap
··· 16 16 import { remainderInt } from "../gleam.mjs"; 17 17 18 18 function go() { 19 - let _block; 20 - let $ = 1 >= 0; 21 - if ($) { 22 - _block = 2; 23 - } else { 24 - _block = 4; 25 - } 26 - return remainderInt(_block, 2); 19 + return remainderInt( 20 + (() => { 21 + let $ = 1 >= 0; 22 + if ($) { 23 + return 2; 24 + } else { 25 + return 4; 26 + } 27 + })(), 28 + 2 29 + ); 27 30 }
+12 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__panic__as_expression.snap
··· 24 24 {} 25 25 ) 26 26 let boop = _block; 27 - let _block$1; 28 - throw makeError( 29 - "panic", 30 - "my/mod", 31 - 4, 32 - "go", 33 - "`panic` expression evaluated.", 34 - {} 35 - ) 36 - return f(_block$1); 27 + return f( 28 + (() => { 29 + throw makeError( 30 + "panic", 31 + "my/mod", 32 + 4, 33 + "go", 34 + "`panic` expression evaluated.", 35 + {} 36 + ) 37 + })(), 38 + ); 37 39 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__panic__pipe.snap
··· 13 13 import { makeError } from "../gleam.mjs"; 14 14 15 15 function go(f) { 16 - let _block; 17 - throw makeError( 18 - "panic", 19 - "my/mod", 20 - 3, 21 - "go", 22 - "`panic` expression evaluated.", 23 - {} 24 - ) 25 16 let _pipe = f; 26 - return _block(_pipe); 17 + return (() => { 18 + throw makeError( 19 + "panic", 20 + "my/mod", 21 + 3, 22 + "go", 23 + "`panic` expression evaluated.", 24 + {} 25 + ) 26 + })()(_pipe); 27 27 }
+1 -3
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__todo__as_expression.snap
··· 17 17 let _block; 18 18 throw makeError("todo", "my/mod", 3, "go", "I should do this", {}) 19 19 let boop = _block; 20 - let _block$1; 21 - throw makeError("todo", "my/mod", 4, "go", "Boom", {}) 22 - return f(_block$1); 20 + return f((() => { throw makeError("todo", "my/mod", 4, "go", "Boom", {}) })()); 23 21 }
+7 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__tuples__tuple_with_block_element.snap
··· 17 17 18 18 ----- COMPILED JAVASCRIPT 19 19 function go() { 20 - let _block; 21 - { 22 - "2"; 23 - _block = "3"; 24 - } 25 - return ["1", _block]; 20 + return [ 21 + "1", 22 + (() => { 23 + "2"; 24 + return "3"; 25 + })(), 26 + ]; 26 27 }