refactor(transformer): move Semantic into Transformer (#1130)

This commit is contained in:
Boshen 2023-11-02 13:10:15 +08:00 committed by GitHub
parent fa4e0cae81
commit 69150d812c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 36 additions and 52 deletions

View file

@ -72,6 +72,10 @@ impl<'a> Semantic<'a> {
&self.scopes
}
pub fn scopes_mut(&mut self) -> &mut ScopeTree {
&mut self.scopes
}
pub fn trivias(&self) -> &TriviasMap {
&self.trivias
}

View file

@ -1,4 +1,4 @@
use std::{cell::RefCell, env, path::Path, rc::Rc};
use std::{env, path::Path};
use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
@ -36,9 +36,6 @@ fn main() {
println!("{printed}\n");
let semantic = SemanticBuilder::new(&source_text, source_type).build(&ret.program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let program = allocator.alloc(ret.program);
let transform_options = TransformOptions {
@ -49,7 +46,7 @@ fn main() {
}),
..TransformOptions::default()
};
Transformer::new(&allocator, source_type, &symbols, &scopes, transform_options).build(program);
Transformer::new(&allocator, source_type, semantic, transform_options).build(program);
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(program);
println!("Transformed:\n");
println!("{printed}");

View file

@ -1,30 +1,37 @@
use std::{
cell::{Ref, RefCell},
cell::{Ref, RefCell, RefMut},
rc::Rc,
};
use oxc_ast::AstBuilder;
use oxc_semantic::{ScopeId, ScopeTree, SymbolId, SymbolTable};
use oxc_semantic::{ScopeId, ScopeTree, Semantic, SymbolId, SymbolTable};
use oxc_span::Atom;
#[derive(Clone)]
pub struct TransformerCtx<'a> {
pub ast: Rc<AstBuilder<'a>>,
pub symbols: Rc<RefCell<SymbolTable>>,
pub scopes: Rc<RefCell<ScopeTree>>,
semantic: Rc<RefCell<Semantic<'a>>>,
}
impl<'a> TransformerCtx<'a> {
pub fn symbols(&self) -> Ref<SymbolTable> {
self.symbols.borrow()
pub fn new(ast: Rc<AstBuilder<'a>>, semantic: Rc<RefCell<Semantic<'a>>>) -> Self {
Self { ast, semantic }
}
pub fn scopes(&self) -> Ref<ScopeTree> {
self.scopes.borrow()
pub fn symbols(&self) -> Ref<'_, SymbolTable> {
Ref::map(self.semantic.borrow(), |semantic| semantic.symbols())
}
pub fn scopes(&self) -> Ref<'_, ScopeTree> {
Ref::map(self.semantic.borrow(), |semantic| semantic.scopes())
}
pub fn scopes_mut(&self) -> RefMut<'_, ScopeTree> {
RefMut::map(self.semantic.borrow_mut(), |semantic| semantic.scopes_mut())
}
pub fn add_binding(&self, name: Atom) {
// TODO: use the correct scope and symbol id
self.scopes.borrow_mut().add_binding(ScopeId::new(0), name, SymbolId::new(0));
self.scopes_mut().add_binding(ScopeId::new(0), name, SymbolId::new(0));
}
}

View file

@ -163,7 +163,7 @@ impl<'a> ExponentiationOperator<'a> {
if ident
.reference_id
.get()
.is_some_and(|reference_id| self.ctx.symbols.borrow().has_binding(reference_id))
.is_some_and(|reference_id| self.ctx.symbols().has_binding(reference_id))
{
// this variable is declared in scope so we can be 100% sure
// that evaluating it multiple times won't trigger a getter
@ -185,7 +185,7 @@ impl<'a> ExponentiationOperator<'a> {
// Super cannot be directly assigned so lets return it also
if matches!(expr, Expression::Super(_))
|| matches!(&expr, Expression::Identifier(ident) if
ident.reference_id.get().is_some_and(|reference_id| self.ctx.symbols.borrow().has_binding(reference_id)))
ident.reference_id.get().is_some_and(|reference_id| self.ctx.symbols().has_binding(reference_id)))
{
return Some(expr);
}

View file

@ -26,7 +26,7 @@ use std::{cell::RefCell, rc::Rc};
use oxc_allocator::{Allocator, Vec};
use oxc_ast::{ast::*, AstBuilder, VisitMut};
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_semantic::Semantic;
use oxc_span::SourceType;
use crate::{
@ -66,16 +66,14 @@ impl<'a> Transformer<'a> {
pub fn new(
allocator: &'a Allocator,
source_type: SourceType,
symbols: &Rc<RefCell<SymbolTable>>,
scopes: &Rc<RefCell<ScopeTree>>,
semantic: Semantic<'a>,
options: TransformOptions,
) -> Self {
let ast = Rc::new(AstBuilder::new(allocator));
let ctx = TransformerCtx {
ast: Rc::clone(&ast),
symbols: Rc::clone(symbols),
scopes: Rc::clone(scopes),
};
let ctx = TransformerCtx::new(
Rc::clone(&ast),
Rc::new(RefCell::new(semantic)),
);
Self {
// TODO: pass verbatim_module_syntax from user config
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false)),

View file

@ -1,5 +1,3 @@
use std::{cell::RefCell, rc::Rc};
use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
use oxc_parser::Parser;
@ -32,15 +30,9 @@ impl Tester {
fn transform(&self, source_text: &str) -> String {
let program = Parser::new(&self.allocator, source_text, self.source_type).parse().program;
let semantic = SemanticBuilder::new(source_text, self.source_type).build(&program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let program = self.allocator.alloc(program);
Transformer::new(&self.allocator, self.source_type, &symbols, &scopes, self.options)
.build(program);
Transformer::new(&self.allocator, self.source_type, semantic, self.options).build(program);
Codegen::<false>::new(source_text.len(), CodegenOptions).build(program)
}

View file

@ -213,12 +213,9 @@ impl Oxc {
// FIXME: this should not be duplicated with the linter semantic,
// we need to fix the API so symbols and scopes can be shared.
let semantic = SemanticBuilder::new(source_text, source_type).build(program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let options =
TransformOptions { target: TransformTarget::ES2015, ..TransformOptions::default() };
Transformer::new(&allocator, source_type, &symbols, &scopes, options).build(program);
Transformer::new(&allocator, source_type, semantic, options).build(program);
}
let program = allocator.alloc(program);

View file

@ -6,7 +6,7 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
use std::{cell::RefCell, fs, hint::black_box, rc::Rc};
use std::{fs, hint::black_box};
use oxc_allocator::Allocator;
use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion};
@ -35,12 +35,9 @@ fn bench_transformer(criterion: &mut Criterion) {
let program = Parser::new(&allocator, source_text, source_type).parse().program;
let semantic =
SemanticBuilder::new(source_text, source_type).build(&program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let program = allocator.alloc(program);
let transform_options = TransformOptions::default();
Transformer::new(&allocator, source_type, &symbols, &scopes, transform_options)
Transformer::new(&allocator, source_type, semantic, transform_options)
.build(black_box(program));
allocator
});

View file

@ -1,8 +1,6 @@
use std::{
cell::RefCell,
fs,
path::{Path, PathBuf},
rc::Rc,
};
use oxc_allocator::Allocator;
@ -144,12 +142,9 @@ pub trait TestCase {
let semantic =
SemanticBuilder::new(&source_text, source_type).build(&transformed_program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let transformed_program = allocator.alloc(transformed_program);
Transformer::new(&allocator, source_type, &symbols, &scopes, self.transform_options())
Transformer::new(&allocator, source_type, semantic, self.transform_options())
.build(transformed_program);
Codegen::<false>::new(source_text.len(), CodegenOptions).build(transformed_program)
}
@ -197,11 +192,8 @@ impl TestCase for ConformanceTestCase {
// Transform input.js
let program = Parser::new(&allocator, &input, source_type).parse().program;
let semantic = SemanticBuilder::new(&input, source_type).build(&program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));
let scopes = Rc::new(RefCell::new(scopes));
let program = allocator.alloc(program);
Transformer::new(&allocator, source_type, &symbols, &scopes, self.transform_options())
Transformer::new(&allocator, source_type, semantic, self.transform_options())
.build(program);
let transformed_code = Codegen::<false>::new(input.len(), CodegenOptions).build(program);