mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[rust] Update swc->estree->hir conversion for new estree
The previous PRs to make `estree` use codegen broke the swc->estree and estree->hir conversions. This PR updates those conversions so everything builds now.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use bumpalo::collections::{String, Vec};
|
||||
use estree::{
|
||||
AssignmentTarget, BinaryExpression, ExpressionLike, ForInit, ForStatement, FunctionDeclaration,
|
||||
IfStatement, Literal, LiteralValue, Pattern, Statement, VariableDeclarationKind,
|
||||
AssignmentTarget, BinaryExpression, BlockStatement, Expression, ForInit, ForStatement,
|
||||
FunctionDeclaration, IfStatement, JsValue, Literal, Pattern, Statement,
|
||||
VariableDeclarationKind,
|
||||
};
|
||||
use hir::{
|
||||
ArrayElement, BlockKind, BranchTerminal, Environment, ForTerminal, Function, GotoKind,
|
||||
@@ -27,7 +28,21 @@ pub fn build<'a>(
|
||||
) -> Result<Function<'a>, BuildDiagnostic> {
|
||||
let mut builder = Builder::new(environment);
|
||||
|
||||
lower_statement(environment, &mut builder, fun.body.unwrap(), None)?;
|
||||
match fun.function.body {
|
||||
Some(estree::FunctionBody::BlockStatement(body)) => {
|
||||
lower_block_statement(environment, &mut builder, *body, None)?
|
||||
}
|
||||
Some(estree::FunctionBody::Expression(body)) => {
|
||||
lower_expression_to_temporary(environment, &mut builder, body)?;
|
||||
}
|
||||
None => {
|
||||
return Err(BuildDiagnostic::new(
|
||||
DiagnosticError::EmptyFunction,
|
||||
ErrorSeverity::InvalidSyntax,
|
||||
fun.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// In case the function did not explicitly return, terminate the final
|
||||
// block with an explicit `return undefined`. If the function *did* return,
|
||||
@@ -49,11 +64,23 @@ pub fn build<'a>(
|
||||
let body = builder.build()?;
|
||||
Ok(Function {
|
||||
body,
|
||||
is_async: fun.is_async,
|
||||
is_generator: fun.is_generator,
|
||||
is_async: fun.function.is_async,
|
||||
is_generator: fun.function.is_generator,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_block_statement<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
stmt: BlockStatement,
|
||||
label: Option<String<'a>>,
|
||||
) -> Result<(), BuildDiagnostic> {
|
||||
for stmt in stmt.body {
|
||||
lower_statement(env, builder, stmt, None)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert a statement to HIR. This will often result in multiple instructions and blocks
|
||||
/// being created as statements often describe control flow.
|
||||
fn lower_statement<'a>(
|
||||
@@ -64,9 +91,7 @@ fn lower_statement<'a>(
|
||||
) -> Result<(), BuildDiagnostic> {
|
||||
match stmt {
|
||||
Statement::BlockStatement(stmt) => {
|
||||
for stmt in stmt.body {
|
||||
lower_statement(env, builder, stmt, None)?;
|
||||
}
|
||||
lower_block_statement(env, builder, *stmt, label)?;
|
||||
}
|
||||
Statement::BreakStatement(stmt) => {
|
||||
let block = builder.resolve_break(stmt.label.as_ref())?;
|
||||
@@ -292,7 +317,7 @@ fn lower_statement<'a>(
|
||||
fn lower_expression_to_temporary<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
expr: ExpressionLike,
|
||||
expr: Expression,
|
||||
) -> Result<Place<'a>, BuildDiagnostic> {
|
||||
let value = lower_expression(env, builder, expr)?;
|
||||
Ok(lower_value_to_temporary(env, builder, value))
|
||||
@@ -305,10 +330,10 @@ fn lower_expression_to_temporary<'a>(
|
||||
fn lower_expression<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
expr: ExpressionLike,
|
||||
expr: Expression,
|
||||
) -> Result<InstructionValue<'a>, BuildDiagnostic> {
|
||||
Ok(match expr {
|
||||
ExpressionLike::Identifier(expr) => {
|
||||
Expression::Identifier(expr) => {
|
||||
// TODO: handle unbound variables
|
||||
let binding = builder.resolve_binding(&expr)?;
|
||||
match binding {
|
||||
@@ -324,24 +349,31 @@ fn lower_expression<'a>(
|
||||
}),
|
||||
}
|
||||
}
|
||||
ExpressionLike::Literal(expr) => InstructionValue::Primitive(hir::Primitive {
|
||||
Expression::Literal(expr) => InstructionValue::Primitive(hir::Primitive {
|
||||
value: lower_primitive(env, builder, *expr),
|
||||
}),
|
||||
ExpressionLike::ArrayExpression(expr) => {
|
||||
Expression::ArrayExpression(expr) => {
|
||||
let mut elements = Vec::with_capacity_in(expr.elements.len(), &env.allocator);
|
||||
for expr in expr.elements {
|
||||
let element = match expr {
|
||||
ExpressionLike::SpreadElement(expr) => ArrayElement::Spread(
|
||||
lower_expression_to_temporary(env, builder, expr.argument)?,
|
||||
Some(estree::ExpressionOrSpread::SpreadElement(expr)) => {
|
||||
Some(ArrayElement::Spread(lower_expression_to_temporary(
|
||||
env,
|
||||
builder,
|
||||
expr.argument,
|
||||
)?))
|
||||
}
|
||||
Some(estree::ExpressionOrSpread::Expression(expr)) => Some(
|
||||
ArrayElement::Place(lower_expression_to_temporary(env, builder, expr)?),
|
||||
),
|
||||
_ => ArrayElement::Place(lower_expression_to_temporary(env, builder, expr)?),
|
||||
None => None,
|
||||
};
|
||||
elements.push(element);
|
||||
}
|
||||
InstructionValue::Array(hir::Array { elements })
|
||||
}
|
||||
|
||||
ExpressionLike::AssignmentExpression(expr) => match expr.operator {
|
||||
Expression::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)?
|
||||
@@ -349,7 +381,7 @@ fn lower_expression<'a>(
|
||||
_ => todo!("lower assignment expr {:#?}", expr),
|
||||
},
|
||||
|
||||
ExpressionLike::BinaryExpression(expr) => {
|
||||
Expression::BinaryExpression(expr) => {
|
||||
let BinaryExpression {
|
||||
left,
|
||||
operator,
|
||||
@@ -365,15 +397,6 @@ fn lower_expression<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
// Cases that cannot appear in expression position but which are included in ExpressionLike
|
||||
// to make serialization easier
|
||||
ExpressionLike::SpreadElement(expr) => {
|
||||
return Err(BuildDiagnostic::new(
|
||||
DiagnosticError::NonExpressionInExpressionPosition,
|
||||
ErrorSeverity::Invariant,
|
||||
expr.range,
|
||||
));
|
||||
}
|
||||
_ => todo!("Lower expr {expr:#?}"),
|
||||
})
|
||||
}
|
||||
@@ -386,7 +409,7 @@ fn lower_assignment<'a>(
|
||||
value: Place<'a>,
|
||||
) -> Result<InstructionValue<'a>, BuildDiagnostic> {
|
||||
Ok(match lvalue {
|
||||
AssignmentTarget::Pattern(lvalue) => match *lvalue {
|
||||
AssignmentTarget::Pattern(lvalue) => match lvalue {
|
||||
Pattern::Identifier(lvalue) => {
|
||||
let place = lower_identifier_for_assignment(env, builder, kind, *lvalue)?;
|
||||
let temporary = lower_value_to_temporary(
|
||||
@@ -466,10 +489,10 @@ fn lower_primitive<'a>(
|
||||
literal: Literal,
|
||||
) -> PrimitiveValue<'a> {
|
||||
match literal.value {
|
||||
LiteralValue::Boolean(bool) => PrimitiveValue::Boolean(bool),
|
||||
LiteralValue::Null => PrimitiveValue::Null,
|
||||
LiteralValue::Number(value) => PrimitiveValue::Number(f64::from(value).into()),
|
||||
LiteralValue::String(s) => PrimitiveValue::String(String::from_str_in(&s, &env.allocator)),
|
||||
JsValue::Bool(bool) => PrimitiveValue::Boolean(bool),
|
||||
JsValue::Null => PrimitiveValue::Null,
|
||||
JsValue::Number(value) => PrimitiveValue::Number(f64::from(value).into()),
|
||||
JsValue::String(s) => PrimitiveValue::String(String::from_str_in(&s, &env.allocator)),
|
||||
_ => todo!("Lower literal {literal:#?}"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@ pub enum DiagnosticError {
|
||||
/// ErrorSeverity::Invariant
|
||||
#[error("Invariant: Identifier was not resolved (did name resolution run successfully?)")]
|
||||
UnknownIdentifier,
|
||||
|
||||
/// ErrorSeverity::InvalidSyntax
|
||||
#[error("Expected function to have a body")]
|
||||
EmptyFunction,
|
||||
}
|
||||
|
||||
#[derive(Error, Diagnostic, Debug)]
|
||||
|
||||
@@ -91,7 +91,8 @@
|
||||
"type": "Vec<ModuleItem>"
|
||||
},
|
||||
"source_type": {
|
||||
"type": "Option<SourceType>",
|
||||
"type": "SourceType",
|
||||
"optional": true,
|
||||
"rename": "sourceType"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,7 @@ fn convert_program(cx: &Context, program: &Program) -> estree::Program {
|
||||
let body = &program.body;
|
||||
program_items = Vec::with_capacity(body.len());
|
||||
for item in body {
|
||||
program_items.push(estree::ModuleItem::Statement(Box::new(convert_statement(
|
||||
cx, item,
|
||||
))));
|
||||
program_items.push(estree::ModuleItem::Statement(convert_statement(cx, item)));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -84,7 +82,7 @@ fn convert_program(cx: &Context, program: &Program) -> estree::Program {
|
||||
estree::SourceType::Module
|
||||
},
|
||||
body: program_items,
|
||||
comments: None,
|
||||
// comments: None,
|
||||
loc: None,
|
||||
range: None,
|
||||
}
|
||||
@@ -92,9 +90,7 @@ fn convert_program(cx: &Context, program: &Program) -> estree::Program {
|
||||
|
||||
fn convert_module_item(cx: &Context, item: &ModuleItem) -> estree::ModuleItem {
|
||||
match item {
|
||||
ModuleItem::Stmt(item) => {
|
||||
estree::ModuleItem::Statement(Box::new(convert_statement(cx, item)))
|
||||
}
|
||||
ModuleItem::Stmt(item) => estree::ModuleItem::Statement(convert_statement(cx, item)),
|
||||
_ => todo!("translate module item {:#?}", item),
|
||||
}
|
||||
}
|
||||
@@ -131,23 +127,27 @@ fn convert_statement(cx: &Context, stmt: &Stmt) -> estree::Statement {
|
||||
Stmt::Decl(Decl::Fn(item)) => {
|
||||
let name = item.ident.sym.to_string();
|
||||
estree::Statement::FunctionDeclaration(Box::new(estree::FunctionDeclaration {
|
||||
id: Some(estree::Identifier {
|
||||
name,
|
||||
binding: convert_binding(cx, item.ident.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&item.ident.span),
|
||||
}),
|
||||
params: item
|
||||
.function
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| convert_pattern(cx, ¶m.pat))
|
||||
.collect(),
|
||||
body: item.function.body.as_ref().map(|body| {
|
||||
estree::Statement::BlockStatement(Box::new(convert_block_statement(cx, body)))
|
||||
}),
|
||||
is_async: item.function.is_async,
|
||||
is_generator: item.function.is_generator,
|
||||
function: estree::Function {
|
||||
id: Some(estree::Identifier {
|
||||
name,
|
||||
binding: convert_binding(cx, item.ident.span.ctxt),
|
||||
loc: None,
|
||||
range: convert_span(&item.ident.span),
|
||||
}),
|
||||
params: item
|
||||
.function
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| convert_pattern(cx, ¶m.pat))
|
||||
.collect(),
|
||||
body: item.function.body.as_ref().map(|body| {
|
||||
estree::FunctionBody::BlockStatement(Box::new(convert_block_statement(
|
||||
cx, body,
|
||||
)))
|
||||
}),
|
||||
is_async: item.function.is_async,
|
||||
is_generator: item.function.is_generator,
|
||||
},
|
||||
loc: None,
|
||||
range: convert_span(&item.function.span),
|
||||
}))
|
||||
@@ -206,7 +206,7 @@ fn convert_statement(cx: &Context, stmt: &Stmt) -> estree::Statement {
|
||||
Stmt::For(item) => estree::Statement::ForStatement(Box::new(estree::ForStatement {
|
||||
init: item.init.as_ref().map(|init| match init {
|
||||
VarDeclOrExpr::Expr(init) => {
|
||||
estree::ForInit::Expression(Box::new(convert_expression(cx, init)))
|
||||
estree::ForInit::Expression(convert_expression(cx, init))
|
||||
}
|
||||
VarDeclOrExpr::VarDecl(init) => {
|
||||
assert_eq!(init.decls.len(), 1);
|
||||
@@ -268,28 +268,28 @@ fn convert_variable_declaration(cx: &Context, decl: &VarDecl) -> estree::Variabl
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
fn convert_expression(cx: &Context, expr: &Expr) -> estree::Expression {
|
||||
match expr {
|
||||
Expr::Ident(expr) => {
|
||||
estree::ExpressionLike::Identifier(Box::new(convert_identifier(cx, expr)))
|
||||
}
|
||||
Expr::Ident(expr) => estree::Expression::Identifier(Box::new(convert_identifier(cx, expr))),
|
||||
Expr::Array(expr) => {
|
||||
estree::ExpressionLike::ArrayExpression(Box::new(estree::ArrayExpression {
|
||||
estree::Expression::ArrayExpression(Box::new(estree::ArrayExpression {
|
||||
elements: expr
|
||||
.elems
|
||||
.iter()
|
||||
.map(|item| {
|
||||
// TODO: represent holes in array expressions
|
||||
let value = item.as_ref().unwrap();
|
||||
let value = item.as_ref()?;
|
||||
match value.spread {
|
||||
Some(spread) => estree::ExpressionLike::SpreadElement(Box::new(
|
||||
estree::SpreadElement {
|
||||
Some(spread) => Some(estree::ExpressionOrSpread::SpreadElement(
|
||||
Box::new(estree::SpreadElement {
|
||||
argument: convert_expression(cx, &value.expr),
|
||||
loc: None,
|
||||
range: convert_span(&spread),
|
||||
},
|
||||
}),
|
||||
)),
|
||||
None => Some(estree::ExpressionOrSpread::Expression(
|
||||
convert_expression(cx, &value.expr),
|
||||
)),
|
||||
None => convert_expression(cx, &value.expr),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
@@ -297,17 +297,18 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
}
|
||||
Expr::Await(expr) => {
|
||||
estree::ExpressionLike::AwaitExpression(Box::new(estree::AwaitExpression {
|
||||
argument: convert_expression(cx, &expr.arg),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}))
|
||||
Expr::Await(_expr) => {
|
||||
// estree::Expression::AwaitExpression(Box::new(estree::AwaitExpression {
|
||||
// argument: convert_expression(cx, &expr.arg),
|
||||
// loc: None,
|
||||
// range: convert_span(&expr.span),
|
||||
// }))
|
||||
todo!("await expression")
|
||||
}
|
||||
Expr::Unary(expr) => {
|
||||
estree::ExpressionLike::UnaryExpression(Box::new(estree::UnaryExpression {
|
||||
estree::Expression::UnaryExpression(Box::new(estree::UnaryExpression {
|
||||
operator: convert_unary_operator(expr.op),
|
||||
is_prefix: false,
|
||||
prefix: false,
|
||||
argument: convert_expression(cx, &expr.arg),
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
@@ -315,7 +316,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
}
|
||||
Expr::Bin(expr) => match convert_binary_operator(expr.op) {
|
||||
Operator::Binary(op) => {
|
||||
estree::ExpressionLike::BinaryExpression(Box::new(estree::BinaryExpression {
|
||||
estree::Expression::BinaryExpression(Box::new(estree::BinaryExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
@@ -324,7 +325,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
}))
|
||||
}
|
||||
Operator::Logical(op) => {
|
||||
estree::ExpressionLike::LogicalExpression(Box::new(estree::LogicalExpression {
|
||||
estree::Expression::LogicalExpression(Box::new(estree::LogicalExpression {
|
||||
operator: op,
|
||||
left: convert_expression(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
@@ -335,30 +336,28 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
},
|
||||
Expr::Lit(expr) => {
|
||||
let (value, range) = match expr {
|
||||
Lit::Bool(expr) => (
|
||||
estree::LiteralValue::Boolean(expr.value),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Bool(expr) => (estree::JsValue::Bool(expr.value), convert_span(&expr.span)),
|
||||
Lit::Num(expr) => (
|
||||
estree::LiteralValue::Number(expr.value.into()),
|
||||
estree::JsValue::Number(expr.value.into()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Str(expr) => (
|
||||
estree::LiteralValue::String(expr.value.to_string()),
|
||||
estree::JsValue::String(expr.value.to_string()),
|
||||
convert_span(&expr.span),
|
||||
),
|
||||
Lit::Null(expr) => (estree::LiteralValue::Null, convert_span(&expr.span)),
|
||||
Lit::Null(expr) => (estree::JsValue::Null, convert_span(&expr.span)),
|
||||
_ => todo!(),
|
||||
};
|
||||
estree::ExpressionLike::Literal(Box::new(estree::Literal {
|
||||
estree::Expression::Literal(Box::new(estree::Literal {
|
||||
value,
|
||||
raw: None,
|
||||
loc: None,
|
||||
regex: None,
|
||||
range,
|
||||
}))
|
||||
}
|
||||
Expr::Assign(expr) => {
|
||||
estree::ExpressionLike::AssignmentExpression(Box::new(estree::AssignmentExpression {
|
||||
estree::Expression::AssignmentExpression(Box::new(estree::AssignmentExpression {
|
||||
operator: convert_assignment_operator(expr.op),
|
||||
left: convert_assignment_target(cx, &expr.left),
|
||||
right: convert_expression(cx, &expr.right),
|
||||
@@ -367,7 +366,7 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
}))
|
||||
}
|
||||
Expr::Member(expr) => {
|
||||
estree::ExpressionLike::MemberExpression(Box::new(convert_member_expression(cx, expr)))
|
||||
estree::Expression::MemberExpression(Box::new(convert_member_expression(cx, expr)))
|
||||
}
|
||||
_ => todo!("translate expression {:#?}", expr),
|
||||
}
|
||||
@@ -375,17 +374,17 @@ fn convert_expression(cx: &Context, expr: &Expr) -> estree::ExpressionLike {
|
||||
|
||||
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::Pat(target) => estree::AssignmentTarget::Pattern(convert_pattern(cx, target)),
|
||||
PatOrExpr::Expr(target) => {
|
||||
match target.as_ref() {
|
||||
Expr::Member(target) => estree::AssignmentTarget::MemberExpression(Box::new(
|
||||
convert_member_expression(cx, target),
|
||||
)),
|
||||
Expr::Ident(target) => estree::AssignmentTarget::Pattern(Box::new(
|
||||
Expr::Member(target) => {
|
||||
estree::AssignmentTarget::Expression(estree::Expression::MemberExpression(
|
||||
Box::new(convert_member_expression(cx, target)),
|
||||
))
|
||||
}
|
||||
Expr::Ident(target) => estree::AssignmentTarget::Pattern(
|
||||
estree::Pattern::Identifier(Box::new(convert_identifier(cx, target))),
|
||||
)),
|
||||
),
|
||||
_ => {
|
||||
panic!("Expected assignment target to be member expression or identifier, got {:#?}", target)
|
||||
}
|
||||
@@ -398,7 +397,7 @@ fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberE
|
||||
let (is_computed, property) = match &expr.prop {
|
||||
MemberProp::Ident(prop) => (
|
||||
false,
|
||||
estree::ExpressionLike::Identifier(Box::new(convert_identifier(cx, prop))),
|
||||
estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
|
||||
),
|
||||
MemberProp::Computed(prop) => (true, convert_expression(cx, &prop.expr)),
|
||||
_ => {
|
||||
@@ -406,10 +405,10 @@ fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberE
|
||||
}
|
||||
};
|
||||
estree::MemberExpression {
|
||||
object: convert_expression(cx, &expr.obj),
|
||||
object: estree::ExpressionOrSuper::Expression(convert_expression(cx, &expr.obj)),
|
||||
property,
|
||||
is_computed,
|
||||
is_optional: false,
|
||||
computed: false, // TODO
|
||||
// optional: false, // TODO
|
||||
loc: None,
|
||||
range: convert_span(&expr.span),
|
||||
}
|
||||
@@ -417,7 +416,7 @@ fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> estree::MemberE
|
||||
|
||||
fn convert_unary_operator(op: UnaryOp) -> estree::UnaryOperator {
|
||||
match op {
|
||||
UnaryOp::Bang => estree::UnaryOperator::Exclamation,
|
||||
UnaryOp::Bang => estree::UnaryOperator::Negation,
|
||||
UnaryOp::Delete => estree::UnaryOperator::Delete,
|
||||
UnaryOp::Minus => estree::UnaryOperator::Minus,
|
||||
UnaryOp::Plus => estree::UnaryOperator::Plus,
|
||||
@@ -442,32 +441,34 @@ enum Operator {
|
||||
|
||||
fn convert_binary_operator(op: BinaryOp) -> Operator {
|
||||
match op {
|
||||
BinaryOp::Add => Operator::Binary(estree::BinaryOperator::Plus),
|
||||
BinaryOp::BitAnd => Operator::Binary(estree::BinaryOperator::Ampersand),
|
||||
BinaryOp::BitOr => Operator::Binary(estree::BinaryOperator::Pipe),
|
||||
BinaryOp::BitXor => Operator::Binary(estree::BinaryOperator::Caret),
|
||||
BinaryOp::Div => Operator::Binary(estree::BinaryOperator::Slash),
|
||||
BinaryOp::EqEq => Operator::Binary(estree::BinaryOperator::EqualsEquals),
|
||||
BinaryOp::EqEqEq => Operator::Binary(estree::BinaryOperator::TripleEquals),
|
||||
BinaryOp::Exp => Operator::Binary(estree::BinaryOperator::AsteriskAsterisk),
|
||||
BinaryOp::Add => Operator::Binary(estree::BinaryOperator::Add),
|
||||
BinaryOp::BitAnd => Operator::Binary(estree::BinaryOperator::BinaryAnd),
|
||||
BinaryOp::BitOr => Operator::Binary(estree::BinaryOperator::BinaryOr),
|
||||
BinaryOp::BitXor => Operator::Binary(estree::BinaryOperator::BinaryXor),
|
||||
BinaryOp::Div => Operator::Binary(estree::BinaryOperator::Divide),
|
||||
BinaryOp::EqEq => Operator::Binary(estree::BinaryOperator::Equals),
|
||||
BinaryOp::EqEqEq => Operator::Binary(estree::BinaryOperator::StrictEquals),
|
||||
// BinaryOp::Exp => Operator::Binary(estree::BinaryOperator::AsteriskAsterisk),
|
||||
BinaryOp::Gt => Operator::Binary(estree::BinaryOperator::GreaterThan),
|
||||
BinaryOp::GtEq => Operator::Binary(estree::BinaryOperator::GreaterThanEquals),
|
||||
BinaryOp::GtEq => Operator::Binary(estree::BinaryOperator::GreaterThanOrEqual),
|
||||
BinaryOp::In => Operator::Binary(estree::BinaryOperator::In),
|
||||
BinaryOp::InstanceOf => Operator::Binary(estree::BinaryOperator::Instanceof),
|
||||
BinaryOp::LShift => Operator::Binary(estree::BinaryOperator::LtLt),
|
||||
BinaryOp::LShift => Operator::Binary(estree::BinaryOperator::ShiftLeft),
|
||||
BinaryOp::Lt => Operator::Binary(estree::BinaryOperator::LessThan),
|
||||
BinaryOp::LtEq => Operator::Binary(estree::BinaryOperator::LessThanEquals),
|
||||
BinaryOp::Mod => Operator::Binary(estree::BinaryOperator::Percent),
|
||||
BinaryOp::Mul => Operator::Binary(estree::BinaryOperator::Asterisk),
|
||||
BinaryOp::LtEq => Operator::Binary(estree::BinaryOperator::LessThanOrEqual),
|
||||
BinaryOp::Mod => Operator::Binary(estree::BinaryOperator::Modulo),
|
||||
// BinaryOp::Mul => Operator::Binary(estree::BinaryOperator::Asterisk),
|
||||
BinaryOp::NotEq => Operator::Binary(estree::BinaryOperator::NotEquals),
|
||||
BinaryOp::NotEqEq => Operator::Binary(estree::BinaryOperator::NotTripleEquals),
|
||||
BinaryOp::RShift => Operator::Binary(estree::BinaryOperator::GtGt),
|
||||
BinaryOp::Sub => Operator::Binary(estree::BinaryOperator::Minus),
|
||||
BinaryOp::ZeroFillRShift => Operator::Binary(estree::BinaryOperator::GtGtGt),
|
||||
BinaryOp::NotEqEq => Operator::Binary(estree::BinaryOperator::NotStrictEquals),
|
||||
BinaryOp::RShift => Operator::Binary(estree::BinaryOperator::ShiftRight),
|
||||
BinaryOp::Sub => Operator::Binary(estree::BinaryOperator::Subtract),
|
||||
BinaryOp::ZeroFillRShift => Operator::Binary(estree::BinaryOperator::UnsignedShiftRight),
|
||||
|
||||
BinaryOp::LogicalAnd => Operator::Logical(estree::LogicalOperator::AmpersandAmpersand),
|
||||
BinaryOp::LogicalOr => Operator::Logical(estree::LogicalOperator::PipePipe),
|
||||
BinaryOp::NullishCoalescing => Operator::Logical(estree::LogicalOperator::QuestionQuestion),
|
||||
BinaryOp::LogicalAnd => Operator::Logical(estree::LogicalOperator::And),
|
||||
BinaryOp::LogicalOr => Operator::Logical(estree::LogicalOperator::Or),
|
||||
BinaryOp::NullishCoalescing => Operator::Logical(estree::LogicalOperator::NullCoalescing),
|
||||
|
||||
_ => panic!("Unsupported binary operator `{}`", op),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +485,7 @@ fn convert_pattern(cx: &Context, pat: &Pat) -> estree::Pattern {
|
||||
}
|
||||
|
||||
fn convert_binding(context: &Context, binding_cx: SyntaxContext) -> Option<Binding> {
|
||||
let id = BindingId::new(NonZeroU32::new(binding_cx.as_u32()).unwrap());
|
||||
let id = BindingId::new(binding_cx.as_u32());
|
||||
if binding_cx.as_u32() == context.top_level_mark.as_u32() {
|
||||
Some(Binding::Global)
|
||||
} else if binding_cx.as_u32() == context.unresolved_mark.as_u32() {
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Binding;
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Binding {
|
||||
Global,
|
||||
Module(BindingId),
|
||||
Local(BindingId),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct BindingId(u32);
|
||||
|
||||
impl BindingId {
|
||||
pub fn new(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BindingId> for u32 {
|
||||
fn from(value: BindingId) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ pub struct Literal {
|
||||
pub struct Program {
|
||||
pub body: Vec<ModuleItem>,
|
||||
#[serde(rename = "sourceType")]
|
||||
pub source_type: Option<SourceType>,
|
||||
#[serde(default)]
|
||||
pub source_type: SourceType,
|
||||
#[serde(default)]
|
||||
pub loc: Option<SourceLocation>,
|
||||
#[serde(default)]
|
||||
|
||||
@@ -4,7 +4,7 @@ mod generated_extensions;
|
||||
mod js_value;
|
||||
mod range;
|
||||
|
||||
pub use binding::Binding;
|
||||
pub use binding::{Binding, BindingId};
|
||||
pub use generated::*;
|
||||
pub use js_value::JsValue;
|
||||
pub use range::SourceRange;
|
||||
|
||||
+1
-1
@@ -351,7 +351,7 @@ Output:
|
||||
}
|
||||
}
|
||||
],
|
||||
"sourceType": null,
|
||||
"sourceType": "script",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
|
||||
@@ -18,7 +18,7 @@ fn fixtures() {
|
||||
|
||||
for (ix, item) in ast.body.into_iter().enumerate() {
|
||||
if let ModuleItem::Statement(stmt) = item {
|
||||
if let Statement::FunctionDeclaration(fun) = *stmt {
|
||||
if let Statement::FunctionDeclaration(fun) = stmt {
|
||||
let allocator = Bump::new();
|
||||
let environment = allocator.alloc(Environment::new(
|
||||
&allocator,
|
||||
|
||||
@@ -51,7 +51,7 @@ pub enum InstructionValue<'a> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Array<'a> {
|
||||
pub elements: Vec<'a, ArrayElement<'a>>,
|
||||
pub elements: Vec<'a, Option<ArrayElement<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -55,7 +55,11 @@ impl<'a> Print for InstructionValue<'a> {
|
||||
if ix != 0 {
|
||||
write!(out, ", ")?;
|
||||
}
|
||||
item.print(out)?;
|
||||
if let Some(item) = item {
|
||||
item.print(out)?;
|
||||
} else {
|
||||
write!(out, "<elision>")?;
|
||||
}
|
||||
}
|
||||
write!(out, "]")?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user