[rust] Assignment expressions

This commit is contained in:
Joe Savona
2023-07-06 09:24:51 +09:00
parent d99da01698
commit c59ac387ae
4 changed files with 68 additions and 26 deletions
+33 -16
View File
@@ -1,7 +1,7 @@
use bumpalo::collections::{CollectIn, String};
use estree::{
ExpressionLike, FunctionDeclaration, Literal, LiteralValue, Pattern, Statement,
VariableDeclarationKind,
AssignmentTarget, ExpressionLike, FunctionDeclaration, Literal, LiteralValue, Pattern,
Statement, VariableDeclarationKind,
};
use hir::{
ArrayElement, BlockKind, Environment, Function, GotoKind, Identifier, InstructionKind,
@@ -114,7 +114,13 @@ fn lower_statement<'a>(
for declaration in stmt.declarations {
if let Some(init) = declaration.init {
let value = lower_expression_to_temporary(env, builder, init);
lower_assignment(env, builder, kind, declaration.id, value);
lower_assignment(
env,
builder,
kind,
AssignmentTarget::Pattern(declaration.id.into()),
value,
);
} else {
if let Pattern::Identifier(id) = declaration.id {
// TODO: handle unbound variables
@@ -195,6 +201,14 @@ fn lower_expression<'a>(
.collect_in(env.allocator);
InstructionValue::Array(hir::Array { elements })
}
ExpressionLike::AssignmentExpression(expr) => match expr.operator {
estree::AssignmentOperator::Equals => {
let right = lower_expression_to_temporary(env, builder, expr.right);
lower_assignment(env, builder, InstructionKind::Reassign, expr.left, right)
}
_ => todo!("lower assignment expr {:#?}", expr),
},
// Cases that cannot appear in expression position but which are included in ExpressionLike
// to make serialization easier
ExpressionLike::SpreadElement(_) => {
@@ -208,22 +222,25 @@ fn lower_assignment<'a>(
env: &'a Environment<'a>,
builder: &mut Builder<'a>,
kind: InstructionKind,
lvalue: Pattern,
lvalue: AssignmentTarget,
value: Place<'a>,
) -> InstructionValue<'a> {
match lvalue {
Pattern::Identifier(lvalue) => {
let place = lower_identifier_for_assignment(env, builder, kind, *lvalue).unwrap();
let temporary = lower_value_to_temporary(
env,
builder,
InstructionValue::StoreLocal(hir::StoreLocal {
lvalue: LValue { place, kind },
value,
}),
);
InstructionValue::LoadLocal(LoadLocal { place: temporary })
}
AssignmentTarget::Pattern(lvalue) => match *lvalue {
Pattern::Identifier(lvalue) => {
let place = lower_identifier_for_assignment(env, builder, kind, *lvalue).unwrap();
let temporary = lower_value_to_temporary(
env,
builder,
InstructionValue::StoreLocal(hir::StoreLocal {
lvalue: LValue { place, kind },
value,
}),
);
InstructionValue::LoadLocal(LoadLocal { place: temporary })
}
_ => todo!("lower assignment pattern for {:#?}", lvalue),
},
_ => todo!("lower assignment for {:#?}", lvalue),
}
}
+26 -5
View File
@@ -6,8 +6,8 @@ use swc_core::common::errors::Handler;
use swc_core::common::source_map::Pos;
use swc_core::common::{FileName, FilePathMapping, Mark, SourceMap, Span, SyntaxContext, GLOBALS};
use swc_core::ecma::ast::{
AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Ident, Lit, ModuleItem, Pat, PatOrExpr,
Program, Stmt, UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
AssignOp, BinaryOp, BlockStmt, Decl, EsVersion, Expr, Ident, Lit, MemberExpr, ModuleItem, Pat,
PatOrExpr, Program, Stmt, UnaryOp, VarDecl, VarDeclKind, VarDeclOrExpr,
};
use swc_core::ecma::parser::Syntax;
use swc_core::ecma::transforms::base::resolver;
@@ -360,7 +360,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
Expr::Assign(expr) => {
estree::ExpressionLike::AssignmentExpression(Box::new(estree::AssignmentExpression {
operator: convert_assignment_operator(expr.op),
left: convert_assignment_target(&expr.left),
left: convert_assignment_target(cx, &expr.left),
right: convert_expression(cx, &expr.right),
loc: None,
range: convert_span(&expr.span),
@@ -370,8 +370,28 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
}
}
fn convert_assignment_target(_target: &PatOrExpr) -> estree::AssignmentTarget {
todo!("translate assignment target")
fn convert_assignment_target(cx: &Context, target: &PatOrExpr) -> estree::AssignmentTarget {
match target {
PatOrExpr::Pat(target) => {
estree::AssignmentTarget::Pattern(Box::new(convert_pattern(cx, target)))
}
PatOrExpr::Expr(target) => {
if let Expr::Member(target) = target.as_ref() {
estree::AssignmentTarget::MemberExpression(Box::new(convert_member_expression(
cx, target,
)))
} else {
panic!(
"Invalid input, expected either a pattern or member expression, got {:#?}",
target
)
}
}
}
}
fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberExpression {
todo!("convert member expression")
}
fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
@@ -388,6 +408,7 @@ fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
fn convert_assignment_operator(op: AssignOp) -> estree::AssignmentOperator {
match op {
AssignOp::Assign => estree::AssignmentOperator::Equals,
AssignOp::AddAssign => estree::AssignmentOperator::PlusEquals,
_ => todo!("translate assignment operator"),
}
@@ -8,6 +8,7 @@ function id(x) {
Math;
id;
let y = true;
y = false;
y;
let z;
z;
@@ -14,6 +14,7 @@ function id(x) {
Math;
id;
let y = true;
y = false;
y;
let z;
z;
@@ -28,9 +29,11 @@ bb0
[1] unknown $2 = LoadGlobal id
[2] unknown $3 = true
[3] unknown $5 = StoreLocal Let unknown y$4 = unknown $3
[4] unknown $6 = LoadLocal unknown y$4
[5] unknown $8 = DeclareLocal Let unknown z$7
[6] unknown $9 = LoadLocal unknown z$7
[7] unknown $11 = LoadLocal unknown x$10
[8] Return unknown $11
[4] unknown $6 = false
[5] unknown $7 = StoreLocal Reassign unknown y$4 = unknown $6
[6] unknown $8 = LoadLocal unknown y$4
[7] unknown $10 = DeclareLocal Let unknown z$9
[8] unknown $11 = LoadLocal unknown z$9
[9] unknown $13 = LoadLocal unknown x$12
[10] Return unknown $13