Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(transformer): finish exponentiation operator
Browse files Browse the repository at this point in the history
Boshen committed Oct 15, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 6c18b3e commit 61a11de
Showing 17 changed files with 376 additions and 82 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 22 additions & 22 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
@@ -92,29 +92,18 @@ pub enum Expression<'a> {
impl<'a> Expression<'a> {
/// `PrimaryExpression`
/// [tc39/ecma262#prod-PrimaryExpression](https://tc39.es/ecma262/#prod-PrimaryExpression)
#[rustfmt::skip]
pub fn is_primary_expression(&self) -> bool {
self.is_literal_expression()
|| matches!(
self,
Self::Identifier(_)
| Self::ThisExpression(_)
| Self::FunctionExpression(_)
| Self::ClassExpression(_)
| Self::ParenthesizedExpression(_)
| Self::ArrayExpression(_)
| Self::ObjectExpression(_)
)
}

pub fn is_literal_expression(&self) -> bool {
matches!(
self,
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumberLiteral(_)
| Self::BigintLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_) // TemplateLiteral is not `Literal` type per oxc_ast
self.is_literal() || matches!(self, Self::Identifier(_) | Self::ThisExpression(_) | Self::FunctionExpression(_)
| Self::ClassExpression(_) | Self::ParenthesizedExpression(_)
| Self::ArrayExpression(_) | Self::ObjectExpression(_))
}

#[rustfmt::skip]
pub fn is_literal(&self) -> bool {
// Note: TemplateLiteral is not `Literal`
matches!(self, Self::BooleanLiteral(_) | Self::NullLiteral(_) | Self::NumberLiteral(_)
| Self::BigintLiteral(_) | Self::RegExpLiteral(_) | Self::StringLiteral(_)
)
}

@@ -540,6 +529,10 @@ pub enum MemberExpression<'a> {
}

impl<'a> MemberExpression<'a> {
pub fn is_computed(&self) -> bool {
matches!(self, MemberExpression::ComputedMemberExpression(_))
}

pub fn optional(&self) -> bool {
match self {
MemberExpression::ComputedMemberExpression(expr) => expr.optional,
@@ -814,6 +807,13 @@ impl<'a> AssignmentTarget<'a> {
pub fn is_destructuring_pattern(&self) -> bool {
matches!(self, Self::AssignmentTargetPattern(_))
}

pub fn is_identifier(&self) -> bool {
matches!(
self,
Self::SimpleAssignmentTarget(SimpleAssignmentTarget::AssignmentTargetIdentifier(_))
)
}
}

#[derive(Debug, Hash)]
4 changes: 4 additions & 0 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
@@ -211,6 +211,10 @@ pub struct StringLiteral {
}

impl StringLiteral {
pub fn new(span: Span, value: Atom) -> Self {
Self { span, value }
}

/// Static Semantics: `IsStringWellFormedUnicode`
/// test for \uD800-\uDFFF
pub fn is_string_well_formed_unicode(&self) -> bool {
58 changes: 47 additions & 11 deletions crates/oxc_ast/src/ast_builder.rs
Original file line number Diff line number Diff line change
@@ -77,6 +77,16 @@ impl<'a> AstBuilder<'a> {
mem::replace(stmts, self.new_vec())
}

pub fn move_assignment_target(
&self,
target: &mut AssignmentTarget<'a>,
) -> AssignmentTarget<'a> {
let ident = IdentifierReference::new(Span::default(), "".into());
let dummy = self.simple_assignment_target_identifier(ident);
let dummy = AssignmentTarget::SimpleAssignmentTarget(dummy);
mem::replace(target, dummy)
}

pub fn program(
&self,
span: Span,
@@ -90,10 +100,6 @@ impl<'a> AstBuilder<'a> {

/* ---------- Literals ---------- */

pub fn string_literal(&self, span: Span, value: Atom) -> StringLiteral {
StringLiteral { span, value }
}

pub fn number_literal(
&self,
span: Span,
@@ -415,6 +421,13 @@ impl<'a> AstBuilder<'a> {
SimpleAssignmentTarget::AssignmentTargetIdentifier(self.alloc(ident))
}

pub fn simple_assignment_target_member_expression(
&self,
expr: MemberExpression<'a>,
) -> SimpleAssignmentTarget<'a> {
SimpleAssignmentTarget::MemberAssignmentTarget(self.alloc(expr))
}

pub fn await_expression(&self, span: Span, argument: Expression<'a>) -> Expression<'a> {
Expression::AwaitExpression(self.alloc(AwaitExpression { span, argument }))
}
@@ -496,31 +509,54 @@ impl<'a> AstBuilder<'a> {
Expression::MemberExpression(self.alloc(expr))
}

pub fn computed_member(
&self,
span: Span,
object: Expression<'a>,
expression: Expression<'a>,
optional: bool, // for optional chaining
) -> MemberExpression<'a> {
MemberExpression::ComputedMemberExpression(ComputedMemberExpression {
span,
object,
expression,
optional,
})
}

pub fn computed_member_expression(
&self,
span: Span,
object: Expression<'a>,
expression: Expression<'a>,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(MemberExpression::ComputedMemberExpression(
ComputedMemberExpression { span, object, expression, optional },
))
self.member_expression(self.computed_member(span, object, expression, optional))
}

pub fn static_member_expression(
pub fn static_member(
&self,
span: Span,
object: Expression<'a>,
property: IdentifierName,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(MemberExpression::StaticMemberExpression(StaticMemberExpression {
) -> MemberExpression<'a> {
MemberExpression::StaticMemberExpression(StaticMemberExpression {
span,
object,
property,
optional,
}))
})
}

pub fn static_member_expression(
&self,
span: Span,
object: Expression<'a>,
property: IdentifierName,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(self.static_member(span, object, property, optional))
}

pub fn private_field_expression(
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/ast_util.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ pub fn is_static_boolean<'a>(expr: &Expression<'a>, ctx: &LintContext<'a>) -> bo
/// Checks if a branch node of `LogicalExpression` short circuits the whole condition
fn is_logical_identity(op: LogicalOperator, expr: &Expression) -> bool {
match expr {
expr if expr.is_literal_expression() => {
expr if expr.is_literal() => {
let boolean_value = expr.get_boolean_value();
(op == LogicalOperator::Or && boolean_value == Some(true))
|| (op == LogicalOperator::And && boolean_value == Some(false))
@@ -142,7 +142,7 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> {
Self::Identifier(ident) => {
ident.name == "undefined" && ctx.semantic().is_reference_to_global_variable(ident)
}
_ if self.is_literal_expression() => true,
_ if self.is_literal() => true,
_ => false,
}
}
Original file line number Diff line number Diff line change
@@ -167,7 +167,7 @@ impl NoConstantBinaryExpression {
| Expression::UpdateExpression(_)
| Expression::BinaryExpression(_)
| Expression::UnaryExpression(_) => true,
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
Expression::CallExpression(call_expr) => {
if let Expression::Identifier(ident) = &call_expr.callee {
return ["Boolean", "String", "Number"].contains(&ident.name.as_str())
@@ -267,7 +267,7 @@ impl NoConstantBinaryExpression {
Expression::ParenthesizedExpression(paren_expr) => {
Self::has_constant_loose_boolean_comparison(&paren_expr.expression, ctx)
}
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
expr if expr.evaluate_to_undefined() => true,
_ => false,
}
@@ -288,7 +288,7 @@ impl NoConstantBinaryExpression {
| Expression::NewExpression(_)
| Expression::TemplateLiteral(_)
| Expression::UpdateExpression(_) => true,
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
Expression::BinaryExpression(binary_expr) => {
binary_expr.operator.is_numeric_or_string_binary_operator()
}
4 changes: 2 additions & 2 deletions crates/oxc_minifier/src/compressor/fold.rs
Original file line number Diff line number Diff line change
@@ -264,7 +264,7 @@ impl<'a> Compressor<'a> {
let right_string = get_string_value(right)?;
// let value = left_string.to_owned().
let value = left_string + right_string;
let string_literal = self.ast.string_literal(span, Atom::from(value));
let string_literal = StringLiteral::new(span, Atom::from(value));
Some(self.ast.literal_string_expression(string_literal))
},

@@ -587,7 +587,7 @@ impl<'a> Compressor<'a> {
};

if let Some(type_name) = type_name {
let string_literal = self.ast.string_literal(span, Atom::from(type_name));
let string_literal = StringLiteral::new(span, Atom::from(type_name));
return Some(self.ast.literal_string_expression(string_literal));
}
}
4 changes: 4 additions & 0 deletions crates/oxc_semantic/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -92,6 +92,10 @@ impl SymbolTable {
&self.references[reference_id]
}

pub fn has_binding(&self, reference_id: ReferenceId) -> bool {
self.references[reference_id].symbol_id().is_some()
}

pub fn is_global_reference(&self, reference_id: ReferenceId) -> bool {
self.references[reference_id].symbol_id().is_none()
}
10 changes: 7 additions & 3 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{env, path::Path};
use std::{cell::RefCell, env, path::Path, rc::Rc};

use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
@@ -34,12 +34,16 @@ fn main() {
println!("{printed}");

let program = allocator.alloc(ret.program);
let _ = SemanticBuilder::new(&source_text, source_type).build(program);

let semantic = SemanticBuilder::new(&source_text, source_type).build(program).semantic;
let (symbols, _scope_tree) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));

let transform_options = TransformOptions {
target: TransformTarget::ES2015,
react: Some(TransformReactOptions::default()),
};
Transformer::new(&allocator, source_type, transform_options).build(program);
Transformer::new(&allocator, source_type, &symbols, transform_options).build(program);
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(program);
println!("Transformed:\n");
println!("{printed}");
Loading

0 comments on commit 61a11de

Please sign in to comment.