lib/minjs/compressor.rb in minjs-0.1.2 vs lib/minjs/compressor.rb in minjs-0.1.3

- old
+ new

@@ -36,19 +36,21 @@ def compress(data, options = {}) parse(data) reorder_function_decl - return_after simple_replacement reorder_var assignment_after_var grouping_statement block_to_exp - if_to_cond #buggy + if_to_cond compress_var reduce_exp + remove_paren + #feature + #return_to_exp @heading_comments.reverse.each do |c| @prog.source_elements.unshift(c) end to_js(options) @@ -139,11 +141,11 @@ } end def reorder_function_decl self.traverse {|st, parent| - if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::Prog and st.decl + if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::Prog and st.decl? if parent.index(st) parent.remove(st) parent.source_elements.unshift(st) end end @@ -191,10 +193,32 @@ end } remove_block_in_block end + #feature + def remove_paren + self.traverse {|st, parent| + if st.kind_of? ECMA262::ExpParen + # + # ECMA262 say: + # expression statement cannot start with "function" + # + if parent.priority(st) > st.val.priority(nil) + if st.val.to_js.match(/^function/) + ; + elsif st.val.to_js.match(/^{/) + ; + else + parent.replace(st, st.val) + end + end + end + } + self + end + def remove_block_in_block while true _retry = false self.traverse {|st, parent| if parent.kind_of? ECMA262::Prog and st.kind_of? ECMA262::StBlock @@ -225,17 +249,51 @@ end end } end + def block_to_statement + self.traverse {|st, parent| + if st.kind_of? ECMA262::StBlock and st.to_statement? + if parent.kind_of? ECMA262::StTry + else + parent.replace(st, st.to_statement) + end + end + } + end + def if_to_cond - #traverse all statemtns and expression self.traverse {|st, parent| if st.kind_of? ECMA262::StIf and st.to_exp? if t = ECMA262::StExp.new(st.to_exp({})) parent.replace(st, t) end + # feature... +=begin + elsif st.kind_of? ECMA262::StIf and st.to_return? + # + # if(...) + # return a; + # return b; + # + # => if(...)return a;else return b; + # + if parent.kind_of? ECMA262::StList and st.else_st.nil? and (nxt = parent[parent.index(st) + 1]).kind_of? ECMA262::StReturn + st.replace(st.else_st, nxt) + parent.replace(nxt, ECMA262::StEmpty.new()) + parent.replace(st, st.to_return) + # + # if(...) + # return a; + # else + # return b; + # + else + parent.replace(st, st.to_return) + end +=end end } end def compress_var @@ -309,10 +367,11 @@ var_sym = next_sym(var_sym) } end } end + def reduce_exp self.traverse {|st, parent| if st.kind_of? ECMA262::Exp st.reduce(parent) end @@ -323,13 +382,13 @@ self.traverse {|st, parent| #true => !0 #false => !1 if st.kind_of? ECMA262::Boolean if st.true? - parent.replace(st, ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new('0', 0))) + parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(0)))) else - parent.replace(st, ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new('1', 1))) + parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(1)))) end #if(true){<then>}else{<else>} => then elsif st.kind_of? ECMA262::StIf if st.cond.kind_of? ECMA262::Boolean if st.cond.true? @@ -342,32 +401,38 @@ end end } end - def return_after + def return_to_exp self.traverse {|st, parent| if st.kind_of? ECMA262::StReturn - if parent.kind_of? ECMA262::StList - idx = parent.index(st) - idx += 1 - while parent.statement_list[idx] - parent.statement_list[idx] = ECMA262::StEmpty.new; - idx += 1 + if parent.kind_of? ECMA262::Prog + parent.remove_empty_statement + # + # a=1;return b; => return a=1,b; + # + # check statement: + # last one is return and its previous is expression or not + if parent.source_elements[-1] == st and (prev=parent.source_elements[-2]).class == ECMA262::StExp + if st.exp + st.replace(st.exp, ECMA262::ExpComma.new(prev.exp, st.exp)) + parent.replace(prev, ECMA262::StEmpty.new()) + end end - elsif parent.kind_of? ECMA262::Prog - idx = parent.index(st) - idx += 1 - while parent.source_elements[idx] - parent.source_elements[idx] = ECMA262::StEmpty.new; - idx += 1 + elsif parent.kind_of? ECMA262::StList + parent.remove_empty_statement + if parent.statement_list[-1] == st and (prev=parent.statement_list[-2]).class == ECMA262::StExp + if st.exp + st.replace(st.exp, ECMA262::ExpComma.new(prev.exp, st.exp)) + parent.replace(prev, ECMA262::StEmpty.new()) + end end - if st.exp.nil? - parent.replace(st, ECMA262::StEmpty.new) - end end end } + block_to_statement + if_to_cond end # # var a; a=1 # => var a=1 #