diff --git a/compiler/forget/crates/build-hir/src/build.rs b/compiler/forget/crates/build-hir/src/build.rs index a4241d7ee2..10150c543f 100644 --- a/compiler/forget/crates/build-hir/src/build.rs +++ b/compiler/forget/crates/build-hir/src/build.rs @@ -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, 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>, +) -> 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, 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, 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, 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:#?}"), } } diff --git a/compiler/forget/crates/build-hir/src/error.rs b/compiler/forget/crates/build-hir/src/error.rs index 7bd64ef61c..4a784ebc0d 100644 --- a/compiler/forget/crates/build-hir/src/error.rs +++ b/compiler/forget/crates/build-hir/src/error.rs @@ -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)] diff --git a/compiler/forget/crates/estree-codegen/src/ecmascript.json b/compiler/forget/crates/estree-codegen/src/ecmascript.json index ea8d5284e2..d3384b67ac 100644 --- a/compiler/forget/crates/estree-codegen/src/ecmascript.json +++ b/compiler/forget/crates/estree-codegen/src/ecmascript.json @@ -91,7 +91,8 @@ "type": "Vec" }, "source_type": { - "type": "Option", + "type": "SourceType", + "optional": true, "rename": "sourceType" } } diff --git a/compiler/forget/crates/estree-swc/src/lib.rs b/compiler/forget/crates/estree-swc/src/lib.rs index 4cb6adc517..d6e4221a29 100644 --- a/compiler/forget/crates/estree-swc/src/lib.rs +++ b/compiler/forget/crates/estree-swc/src/lib.rs @@ -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 { - 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() { diff --git a/compiler/forget/crates/estree/src/binding.rs b/compiler/forget/crates/estree/src/binding.rs index a5fa32814c..4882bb97f6 100644 --- a/compiler/forget/crates/estree/src/binding.rs +++ b/compiler/forget/crates/estree/src/binding.rs @@ -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 for u32 { + fn from(value: BindingId) -> Self { + value.0 + } +} diff --git a/compiler/forget/crates/estree/src/generated.rs b/compiler/forget/crates/estree/src/generated.rs index eb74c114f8..3f269fc132 100644 --- a/compiler/forget/crates/estree/src/generated.rs +++ b/compiler/forget/crates/estree/src/generated.rs @@ -56,7 +56,8 @@ pub struct Literal { pub struct Program { pub body: Vec, #[serde(rename = "sourceType")] - pub source_type: Option, + #[serde(default)] + pub source_type: SourceType, #[serde(default)] pub loc: Option, #[serde(default)] diff --git a/compiler/forget/crates/estree/src/lib.rs b/compiler/forget/crates/estree/src/lib.rs index 202fb72755..4f5319f910 100644 --- a/compiler/forget/crates/estree/src/lib.rs +++ b/compiler/forget/crates/estree/src/lib.rs @@ -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; diff --git a/compiler/forget/crates/estree/src/snapshots/estree__tests__fixtures@simple.json.snap b/compiler/forget/crates/estree/src/snapshots/estree__tests__fixtures@simple.json.snap index 85cb9a74bb..013848ff28 100644 --- a/compiler/forget/crates/estree/src/snapshots/estree__tests__fixtures@simple.json.snap +++ b/compiler/forget/crates/estree/src/snapshots/estree__tests__fixtures@simple.json.snap @@ -351,7 +351,7 @@ Output: } } ], - "sourceType": null, + "sourceType": "script", "loc": { "source": null, "start": { diff --git a/compiler/forget/crates/fixtures/tests/fixtures_test.rs b/compiler/forget/crates/fixtures/tests/fixtures_test.rs index 2b532a66e0..94a0f6ac38 100644 --- a/compiler/forget/crates/fixtures/tests/fixtures_test.rs +++ b/compiler/forget/crates/fixtures/tests/fixtures_test.rs @@ -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, diff --git a/compiler/forget/crates/hir/src/instruction.rs b/compiler/forget/crates/hir/src/instruction.rs index 75dddb5ea6..7c60607bd8 100644 --- a/compiler/forget/crates/hir/src/instruction.rs +++ b/compiler/forget/crates/hir/src/instruction.rs @@ -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>>, } #[derive(Debug)] diff --git a/compiler/forget/crates/hir/src/print.rs b/compiler/forget/crates/hir/src/print.rs index 3bd83493fa..8b1086c104 100644 --- a/compiler/forget/crates/hir/src/print.rs +++ b/compiler/forget/crates/hir/src/print.rs @@ -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, "")?; + } } write!(out, "]")?; }