···
471
471
result
472
472
}
473
473
474
474
+
fn wrap_block<CompileFn>(&mut self, compile: CompileFn) -> Output<'a>
475
475
+
where
476
476
+
CompileFn: Fn(&mut Self) -> Output<'a>,
477
477
+
{
478
478
+
let block_variable = self.next_local_var(&BLOCK_VARIABLE.into());
479
479
+
480
480
+
// Save initial state
481
481
+
let scope_position = std::mem::replace(
482
482
+
&mut self.scope_position,
483
483
+
Position::Assign(block_variable.clone()),
484
484
+
);
485
485
+
let function_position = std::mem::replace(&mut self.function_position, Position::NotTail);
486
486
+
487
487
+
// Generate the expression
488
488
+
let statement_doc = compile(self)?;
489
489
+
self.statement_level
490
490
+
.push(docvec!["let ", block_variable.clone(), ";"]);
491
491
+
self.statement_level.push(statement_doc);
492
492
+
493
493
+
// Reset
494
494
+
self.scope_position = scope_position;
495
495
+
self.function_position = function_position;
496
496
+
497
497
+
Ok(self.wrap_return(block_variable.to_doc()))
498
498
+
}
499
499
+
474
500
/// Use the `_block` variable if the expression is JS statement.
475
501
pub fn wrap_expression(&mut self, expression: &'a TypedExpr) -> Output<'a> {
476
502
match expression {
···
478
504
| TypedExpr::Todo { .. }
479
505
| TypedExpr::Case { .. }
480
506
| TypedExpr::Pipeline { .. }
481
481
-
| TypedExpr::RecordUpdate { .. } => {
482
482
-
let block_variable = self.next_local_var(&BLOCK_VARIABLE.into());
483
483
-
let statement_doc = self.not_in_tail_position(|this| {
484
484
-
this.scope_position = Position::Assign(block_variable.clone());
485
485
-
this.expression(expression)
486
486
-
})?;
487
487
-
self.statement_level
488
488
-
.push(docvec!["let ", block_variable.clone(), ";"]);
489
489
-
self.statement_level.push(statement_doc);
490
490
-
Ok(self.wrap_return(block_variable.to_doc()))
491
491
-
}
507
507
+
| TypedExpr::RecordUpdate { .. } => self.wrap_block(|this| this.expression(expression)),
492
508
_ => self.expression(expression),
493
509
}
494
510
}
···
604
620
}
605
621
} else {
606
622
match &self.scope_position {
607
607
-
Position::Tail | Position::Assign(_) => return self.block_document(statements),
608
608
-
Position::NotTail => {}
609
609
-
}
623
623
+
Position::Tail | Position::Assign(_) => self.block_document(statements),
624
624
+
Position::NotTail => self.wrap_block(|this| {
625
625
+
// Save previous scope
626
626
+
let current_scope_vars = this.current_scope_vars.clone();
610
627
611
611
-
let block_variable = self.next_local_var(&BLOCK_VARIABLE.into());
612
612
-
let statements = self.not_in_tail_position(|this| {
613
613
-
this.scope_position = Position::Assign(block_variable.clone());
614
614
-
this.block_document(statements)
615
615
-
})?;
616
616
-
self.statement_level
617
617
-
.push(docvec!["let ", block_variable.clone(), ";"]);
618
618
-
self.statement_level.push(statements);
619
619
-
Ok(self.wrap_return(block_variable.to_doc()))
628
628
+
let document = this.block_document(statements)?;
629
629
+
630
630
+
// Restore previous state
631
631
+
this.current_scope_vars = current_scope_vars;
632
632
+
633
633
+
Ok(document)
634
634
+
}),
635
635
+
}
620
636
}
621
637
}
622
638
···
51
51
_block = [a$3, b];
52
52
}
53
53
let c = _block;
54
54
-
wibble(a$3);
54
54
+
wibble(a$2);
55
55
let x$1 = c;
56
56
return x$1;
57
57
}
···
34
34
let _pipe = 3;
35
35
_block$1 = add1(_pipe);
36
36
}
37
37
-
let _pipe$1 = _block$1;
38
38
-
_block = add1(_pipe$1);
37
37
+
let _pipe = _block$1;
38
38
+
_block = add1(_pipe);
39
39
}
40
40
let x = _block;
41
41
return x;
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/blocks.rs
3
3
+
expression: "\npub fn main() {\n {\n let x = 1\n let _ = {\n let x = 2\n x\n }\n x\n }\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
7
7
+
pub fn main() {
8
8
+
{
9
9
+
let x = 1
10
10
+
let _ = {
11
11
+
let x = 2
12
12
+
x
13
13
+
}
14
14
+
x
15
15
+
}
16
16
+
}
17
17
+
18
18
+
19
19
+
----- COMPILED JAVASCRIPT
20
20
+
export function main() {
21
21
+
{
22
22
+
let x = 1;
23
23
+
let _block;
24
24
+
{
25
25
+
let x$1 = 2;
26
26
+
_block = x$1;
27
27
+
}
28
28
+
let $ = _block;
29
29
+
30
30
+
return x;
31
31
+
}
32
32
+
}