Skip to content

Commit

Permalink
rework super() desugaring
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Nov 11, 2024
1 parent da13686 commit 5ca0c2f
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 82 deletions.
1 change: 1 addition & 0 deletions crates/dash_compiler/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl<'cx, 'interner> InstructionBuilder<'cx, 'interner> {
build_typeof Instruction::TypeOf,
build_bitnot Instruction::BitNot,
build_not Instruction::Not,
build_bind_this Instruction::BindThis,
build_this Instruction::This,
build_strict_eq Instruction::StrictEq,
build_strict_ne Instruction::StrictNe,
Expand Down
43 changes: 31 additions & 12 deletions crates/dash_compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,7 +1345,7 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
kind: ExprKind::assignment_local_space(super_id, superclass_constructor_call, TokenType::Assignment),
})?;

// __super.__proto__ = this.__proto__
// __super.constructor = this.constructor
ib.visit_expression_statement(Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::assignment(
Expand All @@ -1359,7 +1359,7 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
},
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::identifier(sym::__proto__),
kind: ExprKind::identifier(sym::constructor),
},
),
},
Expand All @@ -1369,29 +1369,29 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
false,
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::Literal(LiteralExpr::Identifier(sym::this)),
kind: ExprKind::identifier(sym::this),
},
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::identifier(sym::__proto__),
kind: ExprKind::identifier(sym::constructor),
},
),
},
TokenType::Assignment,
),
})?;

// this.__proto__ = __super
ib.visit_assignment_expression(
Span::COMPILER_GENERATED,
AssignmentExpr::new_expr_place(
// __super.__proto__ = this.__proto__
ib.visit_expression_statement(Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::assignment(
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::property_access(
false,
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::Literal(LiteralExpr::Identifier(sym::this)),
kind: ExprKind::compiled(compile_local_load(super_id, false)),
},
Expr {
span: Span::COMPILER_GENERATED,
Expand All @@ -1401,12 +1401,28 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
},
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::compiled(compile_local_load(super_id, false)),
kind: ExprKind::property_access(
false,
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::identifier(sym::this),
},
Expr {
span: Span::COMPILER_GENERATED,
kind: ExprKind::identifier(sym::__proto__),
},
),
},
TokenType::Assignment,
),
)?;
// Assignment expression leaves `super` on the stack, as it is needed by expressions
})?;

// this = __super
ib.build_local_load(super_id, false);
ib.build_bind_this();

// Leave the instance on the stack as required by expressions
ib.build_this();

return Ok(());
}
Expand Down Expand Up @@ -1674,6 +1690,7 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
ty,
ty_segment: _,
constructor_initializers,
has_extends_clause,
}: FunctionDeclaration,
) -> Result<(), Error> {
let mut ib = InstructionBuilder::new(self);
Expand Down Expand Up @@ -1754,6 +1771,7 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
debug_symbols: cmp.debug_symbols,
source: Rc::clone(&ib.source),
references_arguments: cmp.references_arguments.is_some(),
has_extends_clause,
};
ib.build_function_constant(function)
.map_err(|_| Error::ConstantPoolLimitExceeded(span))?;
Expand Down Expand Up @@ -2182,6 +2200,7 @@ impl<'interner> Visitor<Result<(), Error>> for FunctionCompiler<'interner> {
ty: FunctionKind::Function(Asyncness::No),
ty_segment: None,
constructor_initializers: Some(fields.clone().filter(|member| !member.static_).cloned().collect()),
has_extends_clause: class.extends.is_some(),
};

ib.visit_expression_statement(Expr {
Expand Down
1 change: 1 addition & 0 deletions crates/dash_decompiler/src/decompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ impl<'interner, 'buf> FunctionDecompiler<'interner, 'buf> {
self.handle_op_instr("objlit", &props);
}
Instruction::This => self.handle_opless_instr("this"),
Instruction::BindThis => self.handle_opless_instr("bindthis"),
Instruction::StaticPropAssign => {
let _k = self.read()?;
let b = self.read_u16()?;
Expand Down
1 change: 1 addition & 0 deletions crates/dash_middle/src/compiler/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct Function {
pub source: Rc<str>,
pub debug_symbols: DebugSymbols,
pub references_arguments: bool,
pub has_extends_clause: bool,
}

impl Function {
Expand Down
1 change: 1 addition & 0 deletions crates/dash_middle/src/compiler/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub enum Instruction {
DynamicPropAccess,
ArrayLit,
ObjLit,
BindThis,
This,
StaticPropAssign,
DynamicPropAssign,
Expand Down
25 changes: 2 additions & 23 deletions crates/dash_middle/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ pub struct FunctionDeclaration {
/// If this function is a desugared class constructor,
/// then this contains all the instance members that need to be initialized.
pub constructor_initializers: Option<Vec<ClassMember>>,
/// Whether this function is a desugared class constructor and the class has an `extends` clause
pub has_extends_clause: bool,
}

impl fmt::Display for FunctionDeclaration {
Expand Down Expand Up @@ -553,29 +555,6 @@ where
Ok(())
}

impl FunctionDeclaration {
/// Creates a new function declaration
pub fn new(
name: Option<Binding>,
id: ScopeId,
parameters: Vec<(Parameter, Option<Expr>, Option<TypeSegment>)>,
statements: Vec<Statement>,
ty: FunctionKind,
ty_segment: Option<TypeSegment>,
constructor_initializers: Option<Vec<ClassMember>>,
) -> Self {
Self {
id,
name,
parameters,
statements,
ty,
ty_segment,
constructor_initializers,
}
}
}

/// A block statement, primarily used to enter a new scope
#[derive(Debug, Clone)]
pub struct BlockStatement(pub Vec<Statement>, pub ScopeId);
Expand Down
83 changes: 48 additions & 35 deletions crates/dash_parser/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,15 +557,16 @@ impl<'a, 'interner> Parser<'a, 'interner> {
key,
Expr {
span: current.span.to(self.previous()?.span),
kind: ExprKind::function(FunctionDeclaration::new(
None,
kind: ExprKind::function(FunctionDeclaration {
id,
name: None,
parameters,
body.0,
FunctionKind::Function(Asyncness::No),
None,
None,
)),
statements: body.0,
ty: FunctionKind::Function(Asyncness::No),
ty_segment: None,
constructor_initializers: None,
has_extends_clause: false,
}),
},
));
} else {
Expand Down Expand Up @@ -617,15 +618,16 @@ impl<'a, 'interner> Parser<'a, 'interner> {
self.eat(TokenType::LeftBrace, true)?;
let BlockStatement(stmts, scope_id) = self.parse_block()?;

let fun = FunctionDeclaration::new(
None,
scope_id,
params,
stmts,
FunctionKind::Function(Asyncness::No),
None,
None,
);
let fun = FunctionDeclaration {
name: None,
id: scope_id,
parameters: params,
statements: stmts,
ty: FunctionKind::Function(Asyncness::No),
ty_segment: None,
constructor_initializers: None,
has_extends_clause: false,
};
items.push((
key,
Expr {
Expand Down Expand Up @@ -725,17 +727,18 @@ impl<'a, 'interner> Parser<'a, 'interner> {

Expr {
span: current.span.to(statement.span),
kind: ExprKind::function(FunctionDeclaration::new(
None,
self.scope_count.inc(),
params,
vec![statement],
kind: ExprKind::function(FunctionDeclaration {
name: None,
id: self.scope_count.inc(),
parameters: params,
statements: vec![statement],
// FIXME: this isn't correct -- we're currently desugaring async closures
// as if they're simply async functions
FunctionKind::Function(Asyncness::Yes),
None,
None,
)),
ty: FunctionKind::Function(Asyncness::Yes),
ty_segment: None,
constructor_initializers: None,
has_extends_clause: false,
}),
}
} else {
return None;
Expand Down Expand Up @@ -845,7 +848,16 @@ impl<'a, 'interner> Parser<'a, 'interner> {
self.new_level_stack.pop_level().unwrap();

Some((
FunctionDeclaration::new(name, scope_id, arguments, statements, ty, ty_seg, None),
FunctionDeclaration {
name,
id: scope_id,
parameters: arguments,
statements,
ty,
ty_segment: ty_seg,
constructor_initializers: None,
has_extends_clause: false,
},
self.previous()?.span,
))
}
Expand Down Expand Up @@ -917,15 +929,16 @@ impl<'a, 'interner> Parser<'a, 'interner> {
let func_id = self.scope_count.inc();
Some(Expr {
span: pre_span.to(body.span),
kind: ExprKind::function(FunctionDeclaration::new(
None,
func_id,
list,
vec![body],
FunctionKind::Arrow,
None,
None,
)),
kind: ExprKind::function(FunctionDeclaration {
name: None,
id: func_id,
parameters: list,
statements: vec![body],
ty: FunctionKind::Arrow,
ty_segment: None,
constructor_initializers: None,
has_extends_clause: false,
}),
})
}
}
19 changes: 10 additions & 9 deletions crates/dash_parser/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,22 +166,23 @@ impl<'a, 'interner> Parser<'a, 'interner> {
let body = self.parse_statement()?;

let func_id = self.scope_count.inc();
let func = FunctionDeclaration::new(
match key {
let func = FunctionDeclaration {
name: match key {
ClassMemberKey::Named(name) => Some(self.create_binding(name)),
// TODO: not correct, `class V { ['a']() {} }` should have its name set to 'a'
ClassMemberKey::Computed(_) => None,
},
func_id,
arguments,
vec![body],
match is_generator {
id: func_id,
parameters: arguments,
statements: vec![body],
ty: match is_generator {
true => FunctionKind::Generator,
false => FunctionKind::Function(asyncness),
},
ty_seg,
None,
);
ty_segment: ty_seg,
constructor_initializers: None,
has_extends_clause: false,
};

members.push(ClassMember {
private: is_private,
Expand Down
7 changes: 7 additions & 0 deletions crates/dash_vm/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1997,6 +1997,12 @@ mod handlers {
Ok(None)
}

pub fn bindthis(mut cx: DispatchContext<'_>) -> Result<Option<HandleResult>, Unrooted> {
let value = cx.pop_stack_rooted();
cx.active_frame_mut().this = This::Bound(value);
Ok(None)
}

pub fn global_this(mut cx: DispatchContext<'_>) -> Result<Option<HandleResult>, Unrooted> {
let global = cx.global;
cx.stack.push(Value::object(global));
Expand Down Expand Up @@ -2393,6 +2399,7 @@ pub fn handle(vm: &mut Vm, instruction: Instruction) -> Result<Option<HandleResu
Instruction::DynamicPropAccess => handlers::dynamicpropertyaccess(cx),
Instruction::ArrayLit => handlers::arraylit(cx),
Instruction::ObjLit => handlers::objlit(cx),
Instruction::BindThis => handlers::bindthis(cx),
Instruction::This => handlers::this(cx),
Instruction::StaticPropAssign => handlers::staticpropertyassign(cx),
Instruction::DynamicPropAssign => handlers::dynamicpropertyassign(cx),
Expand Down
3 changes: 2 additions & 1 deletion crates/dash_vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl This {

unsafe impl Trace for This {
fn trace(&self, cx: &mut TraceCtxt<'_>) {
match self {
match *self {
This::Default => {}
This::BeforeSuper => {}
This::Bound(value) => value.trace(cx),
Expand Down Expand Up @@ -213,6 +213,7 @@ impl Frame {
source: cr.source,
debug_symbols: cr.debug_symbols,
references_arguments: false,
has_extends_clause: false,
};

Self {
Expand Down
1 change: 1 addition & 0 deletions crates/dash_vm/src/gc/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ unsafe impl Trace for dash_middle::compiler::constant::Function {
source: Rc { .. },
debug_symbols: _,
references_arguments: _,
has_extends_clause: _,
} = self;
name.trace(cx);
numbers.as_slice().trace(cx);
Expand Down
Loading

0 comments on commit 5ca0c2f

Please sign in to comment.