[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:
Joe Savona
2023-07-11 11:52:32 +09:00
parent 17ed6cc9a9
commit bdd50d522d
11 changed files with 183 additions and 130 deletions
+55 -32
View File
@@ -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"
}
}
+90 -89
View File
@@ -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, &param.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, &param.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() {
+21 -2
View File
@@ -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)]
+1 -1
View File
@@ -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;
@@ -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)]
+5 -1
View File
@@ -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, "]")?;
}