[rust] Assignment expressions
Joe Savona committed
Jul 6, 2023 at 09:24 UTC
c59ac387aed46c90199f1bc9e057c1a09b4a0a6d
4 files changed
+68
-26
compiler/forget/crates/build-hir/src/build.rs
+33
-16
@@ -1,7 +1,7 @@
1
use bumpalo::collections::{CollectIn, String};
2
use estree::{
3
- ExpressionLike, FunctionDeclaration, Literal, LiteralValue, Pattern, Statement,
4
- VariableDeclarationKind,
3
+ AssignmentTarget, ExpressionLike, FunctionDeclaration, Literal, LiteralValue, Pattern,
4
+ Statement, VariableDeclarationKind,
5
};
6
use hir::{
7
ArrayElement, BlockKind, Environment, Function, GotoKind, Identifier, InstructionKind,
@@ -114,7 +114,13 @@ fn lower_statement<'a>(
114
for declaration in stmt.declarations {
115
if let Some(init) = declaration.init {
116
let value = lower_expression_to_temporary(env, builder, init);
117
- lower_assignment(env, builder, kind, declaration.id, value);
117
+ lower_assignment(
118
+ env,
119
+ builder,
120
+ kind,
121
+ AssignmentTarget::Pattern(declaration.id.into()),
122
+ value,
123
+ );
124
} else {
125
if let Pattern::Identifier(id) = declaration.id {
126
// TODO: handle unbound variables
@@ -195,6 +201,14 @@ fn lower_expression<'a>(
201
.collect_in(env.allocator);
202
InstructionValue::Array(hir::Array { elements })
203
}
204
+ ExpressionLike::AssignmentExpression(expr) => match expr.operator {
205
+ estree::AssignmentOperator::Equals => {
206
+ let right = lower_expression_to_temporary(env, builder, expr.right);
207
+ lower_assignment(env, builder, InstructionKind::Reassign, expr.left, right)
208
+ }
209
+ _ => todo!("lower assignment expr {:#?}", expr),
210
+ },
211
+
212
// Cases that cannot appear in expression position but which are included in ExpressionLike
213
// to make serialization easier
214
ExpressionLike::SpreadElement(_) => {
@@ -208,22 +222,25 @@ fn lower_assignment<'a>(
222
env: &'a Environment<'a>,
223
builder: &mut Builder<'a>,
224
kind: InstructionKind,
211
- lvalue: Pattern,
225
+ lvalue: AssignmentTarget,
226
value: Place<'a>,
227
) -> InstructionValue<'a> {
228
match lvalue {
215
- Pattern::Identifier(lvalue) => {
216
- let place = lower_identifier_for_assignment(env, builder, kind, *lvalue).unwrap();
217
- let temporary = lower_value_to_temporary(
218
- env,
219
- builder,
220
- InstructionValue::StoreLocal(hir::StoreLocal {
221
- lvalue: LValue { place, kind },
222
- value,
223
- }),
224
- );
225
- InstructionValue::LoadLocal(LoadLocal { place: temporary })
226
- }
229
+ AssignmentTarget::Pattern(lvalue) => match *lvalue {
230
+ Pattern::Identifier(lvalue) => {
231
+ let place = lower_identifier_for_assignment(env, builder, kind, *lvalue).unwrap();
232
+ let temporary = lower_value_to_temporary(
233
+ env,
234
+ builder,
235
+ InstructionValue::StoreLocal(hir::StoreLocal {
236
+ lvalue: LValue { place, kind },
237
+ value,
238
+ }),
239
+ );
240
+ InstructionValue::LoadLocal(LoadLocal { place: temporary })
241
+ }
242
+ _ => todo!("lower assignment pattern for {:#?}", lvalue),
243
+ },
244
_ => todo!("lower assignment for {:#?}", lvalue),
245
}
246
}
compiler/forget/crates/estree-swc/src/lib.rs
+26
-5
@@ -6,8 +6,8 @@ use swc_core::common::errors::Handler;
6
use swc_core::common::source_map::Pos;
7
use swc_core::common::{FileName, FilePathMapping, Mark, SourceMap, Span, SyntaxContext, GLOBALS};
8
use swc_core::ecma::ast::{
9
- AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Ident, Lit, ModuleItem, Pat, PatOrExpr,
10
- Program, Stmt, UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
9
+ AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Ident, Lit, MemberExpr, ModuleItem, Pat,
10
+ PatOrExpr, Program, Stmt, UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
11
};
12
use swc_core::ecma::parser::Syntax;
13
use swc_core::ecma::transforms::base::resolver;
@@ -360,7 +360,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
360
Expr::Assign(expr) => {
361
estree::ExpressionLike::AssignmentExpression(Box::new(estree::AssignmentExpression {
362
operator: convert_assignment_operator(expr.op),
363
- left: convert_assignment_target(&expr.left),
363
+ left: convert_assignment_target(cx, &expr.left),
364
right: convert_expression(cx, &expr.right),
365
loc: None,
366
range: convert_span(&expr.span),
@@ -370,8 +370,28 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
370
}
371
}
372
373
-fn convert_assignment_target(_target: &PatOrExpr) -> estree::AssignmentTarget {
374
- todo!("translate assignment target")
373
+fn convert_assignment_target(cx: &Context, target: &PatOrExpr) -> estree::AssignmentTarget {
374
+ match target {
375
+ PatOrExpr::Pat(target) => {
376
+ estree::AssignmentTarget::Pattern(Box::new(convert_pattern(cx, target)))
377
+ }
378
+ PatOrExpr::Expr(target) => {
379
+ if let Expr::Member(target) = target.as_ref() {
380
+ estree::AssignmentTarget::MemberExpression(Box::new(convert_member_expression(
381
+ cx, target,
382
+ )))
383
+ } else {
384
+ panic!(
385
+ "Invalid input, expected either a pattern or member expression, got {:#?}",
386
+ target
387
+ )
388
+ }
389
+ }
390
+ }
391
+}
392
+
393
+fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberExpression {
394
+ todo!("convert member expression")
395
}
396
397
fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
@@ -388,6 +408,7 @@ fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
408
409
fn convert_assignment_operator(op: AssignOp) -> estree::AssignmentOperator {
410
match op {
411
+ AssignOp::Assign => estree::AssignmentOperator::Equals,
412
AssignOp::AddAssign => estree::AssignmentOperator::PlusEquals,
413
_ => todo!("translate assignment operator"),
414
}
compiler/forget/crates/fixtures/tests/fixtures/identifiers.js
+1
@@ -8,6 +8,7 @@ function id(x) {
8
Math;
9
id;
10
let y = true;
11
+ y = false;
12
y;
13
let z;
14
z;
compiler/forget/crates/fixtures/tests/snapshots/fixtures_test__fixtures@identifiers.js.snap
+8
-5
@@ -14,6 +14,7 @@ function id(x) {
14
Math;
15
id;
16
let y = true;
17
+ y = false;
18
y;
19
let z;
20
z;
@@ -28,9 +29,11 @@ bb0
29
[1] unknown $2 = LoadGlobal id
30
[2] unknown $3 = true
31
[3] unknown $5 = StoreLocal Let unknown y$4 = unknown $3
31
- [4] unknown $6 = LoadLocal unknown y$4
32
- [5] unknown $8 = DeclareLocal Let unknown z$7
33
- [6] unknown $9 = LoadLocal unknown z$7
34
- [7] unknown $11 = LoadLocal unknown x$10
35
- [8] Return unknown $11
32
+ [4] unknown $6 = false
33
+ [5] unknown $7 = StoreLocal Reassign unknown y$4 = unknown $6
34
+ [6] unknown $8 = LoadLocal unknown y$4
35
+ [7] unknown $10 = DeclareLocal Let unknown z$9
36
+ [8] unknown $11 = LoadLocal unknown z$9
37
+ [9] unknown $13 = LoadLocal unknown x$12
38
+ [10] Return unknown $13
39