Skip to content

Commit

Permalink
implement opt_ast::merge_vars
Browse files Browse the repository at this point in the history
  • Loading branch information
erikdesjardins committed Aug 8, 2020
1 parent 5d34cfa commit 2df4850
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fn main() -> Result<(), NiceError> {
log::info!("Done ir2ast @ {}", Time(start.elapsed()));

let ast = if opt_ast {
let ast = opt_ast::run(g, ast);
let ast = opt_ast::run(g, ast, opt_ast::Opt { minify });
log::info!("Done ast optimization @ {}", Time(start.elapsed()));
ast
} else {
Expand Down
13 changes: 12 additions & 1 deletion src/opt_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,27 @@ use swc_ecma_visit::FoldWith;
use crate::swc_globals;

mod if2cond;
mod merge_vars;
mod swc;

#[cfg(test)]
mod tests;

pub struct Opt {
pub minify: bool,
}

#[inline(never)] // for better profiling
pub fn run(g: &swc_globals::Initialized, ast: ast::Program) -> ast::Program {
pub fn run(g: &swc_globals::Initialized, ast: ast::Program, options: Opt) -> ast::Program {
let ast = swc::run_passes(g, ast);

let ast = ast.fold_with(&mut if2cond::If2Cond);

let ast = if options.minify {
ast.fold_with(&mut merge_vars::MergeVars)
} else {
ast
};

swc::run_passes(g, ast)
}
48 changes: 48 additions & 0 deletions src/opt_ast/merge_vars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::mem;

use swc_ecma_ast as ast;
use swc_ecma_visit::{Fold, FoldWith};

/// Merges adjacent variable declarations.
pub struct MergeVars;

impl Fold for MergeVars {
fn fold_stmts(&mut self, stmts: Vec<ast::Stmt>) -> Vec<ast::Stmt> {
let stmts = stmts.fold_children_with(self);

let var_to_stmt = |var| ast::Stmt::Decl(ast::Decl::Var(var));

let mut out = Vec::with_capacity(stmts.len());
let mut buffered_var = None;
for stmt in stmts {
match (stmt, &mut buffered_var) {
(ast::Stmt::Decl(ast::Decl::Var(cur)), buf @ None) => {
// no buffer yet, buffer this decl
*buf = Some(cur);
}
(ast::Stmt::Decl(ast::Decl::Var(cur)), Some(buf)) if cur.kind == buf.kind => {
// same kind, add to buffer
buf.decls.extend(cur.decls);
}
(ast::Stmt::Decl(ast::Decl::Var(cur)), Some(_)) => {
// different kinds, swap into buffer
let buffered_var = mem::replace(&mut buffered_var, Some(cur));
if let Some(buf) = buffered_var {
out.push(var_to_stmt(buf));
}
}
(stmt, _) => {
// not a var decl, flush buffer
if let Some(buf) = buffered_var.take() {
out.push(var_to_stmt(buf));
}
out.push(stmt);
}
}
}
if let Some(buf) = buffered_var {
out.push(var_to_stmt(buf));
}
out
}
}
77 changes: 77 additions & 0 deletions src/opt_ast/tests/merge_vars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::opt_ast::merge_vars;

case!(basic, || merge_vars::MergeVars, r#"
var x;
var y;
var z;
let a;
let b;
let c;
const d;
const e;
const f;
"#, @r###"
var x, y, z;
let a, b, c;
const d, e, f;
"###);

case!(basic_values, || merge_vars::MergeVars, r#"
var x;
var y = 1;
var z;
let a;
let b = 2;
let c;
const d;
const e = 3;
const f;
"#, @r###"
var x, y = 1, z;
let a, b = 2, c;
const d, e = 3, f;
"###);

case!(inner_scopes, || merge_vars::MergeVars, r#"
if (foo) {
var a;
var b = 1;
}
"#, @r###"
if (foo) {
var a, b = 1;
}
"###);

case!(inner_fn_scopes, || merge_vars::MergeVars, r#"
function foo() {
var a;
var b = 1;
}
"#, @r###"
function foo() {
var a, b = 1;
}
"###);

case!(bail_nondecl, || merge_vars::MergeVars, r#"
var a;
foo();
var b = 1;
"#, @r###"
var a;
foo();
var b = 1;
"###);

case!(bail_different_types, || merge_vars::MergeVars, r#"
var x;
let y;
const z;
var a;
"#, @r###"
var x;
let y;
const z;
var a;
"###);
3 changes: 2 additions & 1 deletion src/opt_ast/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ macro_rules! case {
use crate::{emit, opt_ast, parse, swc_globals};
swc_globals::with(|g| {
let (ast, files) = parse::parse(g, $string)?;
let ast = opt_ast::run(g, ast);
let ast = opt_ast::run(g, ast, opt_ast::Opt { minify: false });
let js = emit::emit(g, ast, files, emit::Opt { minify: false })?;
insta::assert_snapshot!(js, @ $expected);
Ok(())
Expand All @@ -29,4 +29,5 @@ macro_rules! case {
}

mod if2cond;
mod merge_vars;
mod swc;
4 changes: 2 additions & 2 deletions src/tests/all_phases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ macro_rules! case {
minify: false,
},
);
let ast = opt_ast::run(g, ast);
let ast = opt_ast::run(g, ast, opt_ast::Opt { minify: false });
let js = emit::emit(g, ast, files, emit::Opt { minify: false })?;
insta::assert_snapshot!(js, @ $expected);
Ok(())
Expand All @@ -48,7 +48,7 @@ macro_rules! extern_case {
minify: false,
},
);
let ast = opt_ast::run(g, ast);
let ast = opt_ast::run(g, ast, opt_ast::Opt { minify: false });
let js = emit::emit(g, ast, files, emit::Opt { minify: false })?;
insta::assert_snapshot!(stringify!($name), js);
Ok(())
Expand Down

0 comments on commit 2df4850

Please sign in to comment.