This commit is contained in:
Andrew Morris
2023-07-27 16:35:58 +10:00
parent 9c21f0ee9c
commit cd81f79e4b
3 changed files with 104 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ mod ident;
mod import_pattern;
mod instruction;
mod link_module;
mod minify;
mod module_compiler;
mod name_allocator;
mod optimization;

View File

@@ -0,0 +1,94 @@
use std::{
iter::{Peekable, Skip, Take},
str::Chars,
};
use swc_common::BytePos;
pub fn minify(source: &str, span: swc_common::Span) -> String {
let mut minifier = Minifier::new(source, span);
minifier.run();
minifier.res
}
struct Minifier<'a> {
chars: Peekable<Take<Skip<Chars<'a>>>>,
res: String,
}
impl<'a> Minifier<'a> {
fn new(source: &'a str, span: swc_common::Span) -> Self {
let BytePos(start) = span.lo;
let BytePos(end) = span.hi;
let chars = source
.chars()
.skip(start as usize)
.take((end - start) as usize)
.peekable();
Minifier {
chars,
res: String::new(),
}
}
fn run(&mut self) {
let mut punctuation_last = true;
while let Some(c) = self.chars.peek().cloned() {
if c.is_ascii_whitespace() {
self.skip_ws(punctuation_last);
continue;
}
self.res.push(c);
self.chars.next();
punctuation_last = is_js_punctuation(c);
match c {
'\'' | '"' => self.simple_string(c),
'`' => self.template_string(),
_ => {}
}
}
}
fn skip_ws(&mut self, punctuation_last: bool) {
while let Some(c) = self.chars.peek().cloned() {
if !c.is_ascii_whitespace() {
if !punctuation_last && !is_js_punctuation(c) {
self.res.push(' ');
}
break;
}
self.chars.next();
}
}
fn simple_string(&mut self, quote_c: char) {
let mut escaping = false;
for c in &mut self.chars {
self.res.push(c);
if !escaping && c == quote_c {
break;
}
escaping = c == '\\';
}
}
fn template_string(&mut self) {
todo!()
}
}
fn is_js_punctuation(c: char) -> bool {
c.is_ascii_punctuation() && !matches!(c, '$' | '_')
}

View File

@@ -15,6 +15,7 @@ use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticReporter};
use crate::expression_compiler::{CompiledExpression, ExpressionCompiler};
use crate::function_compiler::{FunctionCompiler, Functionish};
use crate::ident::Ident;
use crate::minify::minify;
use crate::name_allocator::{ident_from_str, NameAllocator};
use crate::scope::OwnerId;
use crate::scope_analysis::{class_to_owner_id, ScopeAnalysis};
@@ -70,8 +71,8 @@ pub struct CompilerOutput {
pub module: Module,
}
pub fn compile_program(program: &swc_ecma_ast::Program) -> CompilerOutput {
let compiler = ModuleCompiler::compile_program(program);
pub fn compile_program(source: &str, program: &swc_ecma_ast::Program) -> CompilerOutput {
let compiler = ModuleCompiler::compile_program(source, program);
CompilerOutput {
diagnostics: compiler.diagnostics.take(),
@@ -83,7 +84,7 @@ pub fn compile_module(source: &str) -> CompilerOutput {
let (program_optional, mut diagnostics) = parse(source);
let mut compiler_output = match program_optional {
Some(program) => compile_program(&program),
Some(program) => compile_program(source, &program),
None => CompilerOutput::default(),
};
@@ -99,6 +100,7 @@ pub struct ModuleCompiler {
pub definition_allocator: NameAllocator,
pub scope_analysis: ScopeAnalysis,
pub constants_map: HashMap<Pointer, Value>,
pub source: String,
pub module: Module,
}
@@ -125,7 +127,7 @@ impl ModuleCompiler {
}
}
fn compile_program(program: &swc_ecma_ast::Program) -> Self {
fn compile_program(source: &str, program: &swc_ecma_ast::Program) -> Self {
use swc_ecma_ast::Program::*;
let module = match program {
@@ -144,6 +146,7 @@ impl ModuleCompiler {
let mut self_ = Self {
scope_analysis,
diagnostics: RefCell::new(diagnostics),
source: source.to_string(),
..Default::default()
};
@@ -153,6 +156,8 @@ impl ModuleCompiler {
}
fn compile_module(&mut self, module: &swc_ecma_ast::Module) {
println!("Min: {}", minify(&self.source, module.span));
for module_item in &module.body {
self.compile_module_item(module_item);
}