@@ -15,8 +15,15 @@ use std::sync::Arc;
15
15
16
16
#[ derive( Debug , Clone ) ]
17
17
pub enum Position {
18
+ /// We are compiling the last expression in a function, meaning that it should
19
+ /// use `return` to return the value it produces from the function.
18
20
Tail ,
19
- NotTail ( Ordering ) ,
21
+ /// We are inside a function, but the value of this expression isn't being
22
+ /// used, so we don't need to do anything with the returned value.
23
+ Statement ,
24
+ /// The value of this expression needs to be used inside another expression,
25
+ /// so we need to use the value that is returned by this expression.
26
+ Expression ( Ordering ) ,
20
27
/// We are compiling an expression inside a block, meaning we must assign
21
28
/// to the `_block` variable at the end of the scope, because blocks are not
22
29
/// expressions in JS.
@@ -38,8 +45,8 @@ impl Position {
38
45
#[ must_use]
39
46
pub fn ordering ( & self ) -> Ordering {
40
47
match self {
41
- Self :: NotTail ( ordering) => * ordering,
42
- Self :: Tail | Self :: Assign ( _) => Ordering :: Loose ,
48
+ Self :: Expression ( ordering) => * ordering,
49
+ Self :: Tail | Self :: Assign ( _) | Self :: Statement => Ordering :: Loose ,
43
50
}
44
51
}
45
52
}
@@ -518,7 +525,7 @@ impl<'module, 'a> Generator<'module, 'a> {
518
525
pub fn wrap_return ( & mut self , document : Document < ' a > ) -> Document < ' a > {
519
526
match & self . scope_position {
520
527
Position :: Tail => docvec ! [ "return " , document, ";" ] ,
521
- Position :: NotTail ( _) => document,
528
+ Position :: Expression ( _) | Position :: Statement => document,
522
529
Position :: Assign ( name) => docvec ! [ name. clone( ) , " = " , document, ";" ] ,
523
530
}
524
531
}
@@ -536,10 +543,12 @@ impl<'module, 'a> Generator<'module, 'a> {
536
543
{
537
544
let new_ordering = ordering. unwrap_or ( self . scope_position . ordering ( ) ) ;
538
545
539
- let function_position =
540
- std:: mem:: replace ( & mut self . function_position , Position :: NotTail ( new_ordering) ) ;
546
+ let function_position = std:: mem:: replace (
547
+ & mut self . function_position ,
548
+ Position :: Expression ( new_ordering) ,
549
+ ) ;
541
550
let scope_position =
542
- std:: mem:: replace ( & mut self . scope_position , Position :: NotTail ( new_ordering) ) ;
551
+ std:: mem:: replace ( & mut self . scope_position , Position :: Expression ( new_ordering) ) ;
543
552
544
553
let result = compile ( self ) ;
545
554
@@ -562,7 +571,7 @@ impl<'module, 'a> Generator<'module, 'a> {
562
571
record_assignment : Some ( _) ,
563
572
..
564
573
} ,
565
- Position :: NotTail ( Ordering :: Loose ) ,
574
+ Position :: Expression ( Ordering :: Loose ) ,
566
575
) => self . wrap_block ( |this| this. expression ( expression) ) ,
567
576
(
568
577
TypedExpr :: Panic { .. }
@@ -574,7 +583,7 @@ impl<'module, 'a> Generator<'module, 'a> {
574
583
record_assignment : Some ( _) ,
575
584
..
576
585
} ,
577
- Position :: NotTail ( Ordering :: Strict ) ,
586
+ Position :: Expression ( Ordering :: Strict ) ,
578
587
) => self . immediately_invoked_function_expression ( expression, |this, expr| {
579
588
this. expression ( expr)
580
589
} ) ,
@@ -597,8 +606,8 @@ impl<'module, 'a> Generator<'module, 'a> {
597
606
match & self . scope_position {
598
607
// Here the document is a return statement: `return <expr>;`
599
608
// or an assignment: `_block = <expr>;`
600
- Position :: Tail | Position :: Assign ( _) => document,
601
- Position :: NotTail ( _) => docvec ! [ "(" , document, ")" ] ,
609
+ Position :: Tail | Position :: Assign ( _) | Position :: Statement => document,
610
+ Position :: Expression ( _) => docvec ! [ "(" , document, ")" ] ,
602
611
}
603
612
}
604
613
@@ -644,7 +653,7 @@ impl<'module, 'a> Generator<'module, 'a> {
644
653
) ;
645
654
let function_position = std:: mem:: replace (
646
655
& mut self . function_position ,
647
- Position :: NotTail ( Ordering :: Strict ) ,
656
+ Position :: Expression ( Ordering :: Strict ) ,
648
657
) ;
649
658
650
659
// Generate the expression
@@ -774,12 +783,14 @@ impl<'module, 'a> Generator<'module, 'a> {
774
783
}
775
784
}
776
785
match & self . scope_position {
777
- Position :: Tail | Position :: Assign ( _) => self . block_document ( statements) ,
778
- Position :: NotTail ( Ordering :: Strict ) => self
786
+ Position :: Tail | Position :: Assign ( _) | Position :: Statement => {
787
+ self . block_document ( statements)
788
+ }
789
+ Position :: Expression ( Ordering :: Strict ) => self
779
790
. immediately_invoked_function_expression ( statements, |this, statements| {
780
791
this. statements ( statements)
781
792
} ) ,
782
- Position :: NotTail ( Ordering :: Loose ) => self . wrap_block ( |this| {
793
+ Position :: Expression ( Ordering :: Loose ) => self . wrap_block ( |this| {
783
794
// Save previous scope
784
795
let current_scope_vars = this. current_scope_vars . clone ( ) ;
785
796
@@ -806,11 +817,16 @@ impl<'module, 'a> Generator<'module, 'a> {
806
817
let mut documents = Vec :: with_capacity ( count * 3 ) ;
807
818
for ( i, statement) in statements. iter ( ) . enumerate ( ) {
808
819
if i + 1 < count {
809
- documents. push (
810
- self . not_in_tail_position ( Some ( Ordering :: Loose ) , |this| {
811
- this. statement ( statement)
812
- } ) ,
813
- ) ;
820
+ let function_position =
821
+ std:: mem:: replace ( & mut self . function_position , Position :: Statement ) ;
822
+ let scope_position =
823
+ std:: mem:: replace ( & mut self . scope_position , Position :: Statement ) ;
824
+
825
+ documents. push ( self . statement ( statement) ) ;
826
+
827
+ self . function_position = function_position;
828
+ self . scope_position = scope_position;
829
+
814
830
if requires_semicolon ( statement) {
815
831
documents. push ( ";" . to_doc ( ) ) ;
816
832
}
@@ -845,7 +861,7 @@ impl<'module, 'a> Generator<'module, 'a> {
845
861
let js_name = self . next_local_var ( name) ;
846
862
let assignment = docvec ! [ "let " , js_name. clone( ) , " = " , subject, ";" ] ;
847
863
let assignment = match & self . scope_position {
848
- Position :: NotTail ( _) => assignment,
864
+ Position :: Expression ( _) | Position :: Statement => assignment,
849
865
Position :: Tail => docvec ! [ assignment, line( ) , "return " , js_name, ";" ] ,
850
866
Position :: Assign ( block_variable) => docvec ! [
851
867
assignment,
@@ -900,7 +916,7 @@ impl<'module, 'a> Generator<'module, 'a> {
900
916
} ) ;
901
917
902
918
match & self . scope_position {
903
- Position :: NotTail ( _) => check,
919
+ Position :: Expression ( _) | Position :: Statement => check,
904
920
Position :: Tail | Position :: Assign ( _) => {
905
921
docvec ! [ check, line( ) , self . wrap_return( "undefined" . to_doc( ) ) ]
906
922
}
0 commit comments