lib/minjs/compressor.rb in minjs-0.2.1 vs lib/minjs/compressor.rb in minjs-0.2.2
- old
+ new
@@ -6,19 +6,21 @@
require 'minjs/statement'
require 'minjs/expression'
require 'minjs/func'
require 'minjs/program'
require 'minjs/exceptions'
+require 'minjs/version'
require 'logger'
module Minjs
class Compressor
include Literal
include Statement
include Exp
include Func
include Program
+ include Ctype
attr_reader :prog
def initialize(options = {})
@logger = options[:logger]
@@ -61,22 +63,22 @@
:reorder_function_decl,
:simple_replacement,
:reorder_var,
:assignment_after_var,
:grouping_statement,
- :reduce_if,
:block_to_statement,
+ :reduce_if,
:if_to_cond,
:optimize_if_return,
:compress_var,
:reduce_exp,
:grouping_statement,
:block_to_statement,
:if_to_cond,
:optimize_if_return2,
- :optimize_if_return3,
- :remove_paren,
+ :block_to_statement,
+ :add_remove_paren,
]
algo.each do |a|
if (options.empty? || options[:all] || options[a]) && !options[("no_" + a.to_s).to_sym]
@logger.info "* #{a}"
__send__(a, @prog)
@@ -165,11 +167,11 @@
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StatementList
st.grouping
end
}
- remove_paren
+ add_remove_paren
self
end
def reorder_function_decl(node = @prog)
flist = []
@@ -272,65 +274,81 @@
self
}
self
end
- def remove_paren(node = @prog)
+ def add_remove_paren(node = @prog)
node.traverse(nil) {|st, parent|
if st.respond_to? :remove_paren
st.remove_paren
st.add_paren
end
}
self
end
- def remove_block_in_block(node = @prog)
- while true
- _retry = false
- node.traverse(nil) {|st, parent|
- if parent.kind_of? ECMA262::StatementList and st.kind_of? ECMA262::StBlock
- idx = parent.index(st)
- parent.statement_list[idx..idx] = st.statement_list.statement_list
- _retry = true
- break
- elsif st.kind_of? ECMA262::StBlock
- ;
- end
- }
- break if !_retry
- end
- self
+ def remove_paren(node = @prog)
+ add_remove_paren(node)
end
- def block_to_statement(node = @prog)
- node.traverse(nil) {|st, parent|
- if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
- if st.to_statement?
- parent.replace(st, st.to_statement)
- end
- end
- }
- if_block_to_statement
- end
-
#
- # To determine removing "if block" is available or not is difficult.
- # For example, next codes block must not be removed, because
+ # To determine removing "block" is available or not is difficult.
+ # For example, next code's if-block must not be removed, because
# "else" cluase combined to second "if" statement.
#
- #
# if(a){ //<= this block must not be removed
# while(true)
# if(b){
# ;
# }
# }
# else{
# ;
# }
+ #
+ # The next code's while-block must not be removed, because
+ # "else" cluase combined to second "if" statement.
+ #
+ # if(a)
+ # while(true){ //<= this block must not be removed
+ # if(b){
+ # ;
+ # }
+ # }
+ # else{
+ # ;
+ # }
+ #
+ # To solve this problem, first, every then-clause without block
+ # converts to block statement. After converted, all blocks
+ # except then-clause can be removed safety.
+ #
+ def then_to_block(node = @prog)
+ node.traverse(nil) {|st, parent|
+ if st.kind_of? ECMA262::StIf
+ if !st.then_st.kind_of?(ECMA262::StBlock)
+ st.replace(st.then_st, ECMA262::StBlock.new([st.then_st]))
+ end
+ end
+ }
+ end
+
+ def block_to_statement(node = @prog)
+ remove_empty_statement
+ then_to_block
+ node.traverse(nil) {|st, parent|
+ if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
+ if st.to_statement?
+ parent.replace(st, st.to_statement)
+ end
+ end
+ }
+ if_block_to_statement
+ end
+
def if_block_to_statement(node = @prog)
+ remove_empty_statement
# The "else" cluase's block can be removed always
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StIf
if st.else_st and st.else_st.kind_of? ECMA262::StBlock
st.else_st.remove_empty_statement
@@ -339,10 +357,51 @@
if st.else_st and st.else_st.kind_of? ECMA262::StBlock and st.else_st.to_statement?
st.replace(st.else_st, st.else_st.to_statement)
end
end
}
+ node.traverse(nil) {|st, parent|
+ if st.kind_of? ECMA262::StIf
+ if st.then_st and st.then_st.kind_of? ECMA262::StBlock
+ st.then_st.remove_empty_statement
+ end
+ if !st.else_st and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
+ st.replace(st.then_st, st.then_st.to_statement)
+ elsif st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
+ _st = st.then_st
+ st2 = st.then_st.to_statement
+ while true
+ if st2.kind_of? ECMA262::StVar or st2.kind_of? ECMA262::StEmpty or
+ st2.kind_of? ECMA262::StExp or st2.kind_of? ECMA262::StBlock or
+ st2.kind_of? ECMA262::StDoWhile or st2.kind_of? ECMA262::StSwitch or
+ st2.kind_of? ECMA262::StContinue or st2.kind_of? ECMA262::StBreak or
+ st2.kind_of? ECMA262::StReturn or st2.kind_of? ECMA262::StThrow or
+ st2.kind_of? ECMA262::StTry or st2.kind_of? ECMA262::StDebugger
+ st.replace(st.then_st, st.then_st.to_statement)
+ break;
+ elsif st2.kind_of? ECMA262::StWhile or
+ st2.kind_of? ECMA262::StFor or
+ st2.kind_of? ECMA262::StForIn or
+ st2.kind_of? ECMA262::StForVar or
+ st2.kind_of? ECMA262::StForInVar or
+ st2.kind_of? ECMA262::StWith or
+ st2.kind_of? ECMA262::StLabelled
+ st2 = st2.statement
+ elsif st2.kind_of? ECMA262::StIf
+ if st2.else_st
+ st2 = st2.else_st
+ else
+ break
+ end
+ else #?
+ break
+ end
+ end
+ end
+ end
+ }
+=begin
node.traverse(nil) {|st0, parent|
st = st0.deep_dup
if st.kind_of? ECMA262::StIf
if st.then_st and st.then_st.kind_of? ECMA262::StBlock
st.then_st.remove_empty_statement
@@ -353,33 +412,55 @@
end
_lex = Minjs::Lex.new(st.to_js)
_context = ECMA262::Context.new
_if = if_statement(_lex, _context)
+ reduce_exp(_if)
if _if == st #
- parent.replace(st0, st)
+ if st0.then_st and st0.then_st.kind_of? ECMA262::StBlock
+ st0.then_st.remove_empty_statement
+ end
+ if st0.then_st and st0.then_st.kind_of? ECMA262::StBlock and st0.then_st.to_statement?
+ st0.replace(st0.then_st, st0.then_st.to_statement)
+ end
+ else
+ p '!='
+ puts st.to_js
+ puts _if.to_js
end
end
}
+=end
self
end
#
# if(a)b;else c;
# =>
# a?b:c
#
# if(a)b
# =>
- # a&&b;
+ # a&&b; or a?b:0;
#
+ # NOTE:
+ # Sometimes, "conditional operator" will be shorter than
+ # "logical and operator", because "conditional operator"'s
+ # priority is lower than almost all other expressions.
+ #
def if_to_cond(node = @prog)
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StIf
if st.to_exp?
t = ECMA262::StExp.new(st.to_exp({}))
- remove_paren(t)
+ t2 = ECMA262::StExp.new(st.to_exp({cond: true}))
+ if t2.to_js.length < t.to_js.length
+ t = t2
+ end
+ add_remove_paren(t)
+ simple_replacement(t)
+
if t.to_js.length <= st.to_js.length
parent.replace(st, t)
end
end
end
@@ -394,11 +475,12 @@
def if_to_return(node = @prog)
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StIf
if st.to_return?
t = st.to_return
- remove_paren(t)
+ add_remove_paren(t)
+ simple_replacement(t)
if t.to_js.length <= st.to_js.length
parent.replace(st, t)
end
end
end
@@ -408,53 +490,59 @@
#
# if(a)return b;
# return c;
#
- # => if(a)return b;else return c;
# => return a?b:c;
#
def optimize_if_return(node = @prog)
- retry_flag = true
- while retry_flag
- retry_flag = false
- node.traverse(nil) {|st0, parent0|
- if st0.kind_of? ECMA262::StIf and parent0.kind_of? ECMA262::StatementList
- i = parent0.index(st0)
- break if i.nil?
- parent = parent0.deep_dup
- st = parent[i]
- #
- if parent[i+1].nil? and !parent.kind_of?(ECMA262::SourceElements)
- next
+ node.traverse(nil) {|st0, parent0|
+ if st0.kind_of? ECMA262::StatementList
+ st0.remove_empty_statement
+ st = st0.deep_dup
+ while true
+ #check last statement
+ ls = st.statement_list[-1]
+ ls2 = st.statement_list[-2]
+ if st.kind_of? ECMA262::SourceElements and !(ls.kind_of? ECMA262::StReturn)
+ ls2 = ls
+ ls = ECMA262::StReturn.new(ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)))
end
- if parent[i+1].nil? or parent[i+1].to_return?
- s = st
- while s.kind_of? ECMA262::StIf and s.else_st and s.then_st.to_return?
- s = s.else_st
- end
- if s and s.kind_of? ECMA262::StIf and s.then_st.to_return?
- if parent[i+1]
- s.replace(s.else_st, parent[i+1])
- parent.replace(parent[i+1], ECMA262::StEmpty.new)
- else
- s.replace(s.else_st, ECMA262::StReturn.new(ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0))))
- end
- if_to_cond(parent)
- if parent.to_js(:no_debug => true).length <= parent0.to_js(:no_debug => true).length
- parent0.replace(st0, st)
- if parent[i+1]
- parent0.replace(parent0[i+1], ECMA262::StEmpty.new)
- end
- retry_flag = true
- node = parent0
- end
- end
+ break if ls.nil?
+ break if ls2.nil?
+ break if !ls.to_return?
+ break if !ls2.kind_of?(ECMA262::StIf)
+ break if ls2.else_st
+ break if !ls2.then_st.to_return?
+
+# if !ls2.then_st.kind_of? ECMA262::StIf and !ls2.then_st.to_return?
+# break
+# end
+# if ls2.then_st.kind_of? ECMA262::StIf and !ls2.then_to_return?
+# break
+# end
+
+ then_exp = ls2.then_st.to_return.exp
+ else_exp = ls.to_return.exp
+ then_exp = ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)) if then_exp.nil?
+ else_exp = ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)) if else_exp.nil?
+ if ls2.cond.kind_of? ECMA262::ExpLogicalNot
+ cond = ECMA262::ExpCond.new(ls2.cond.val, else_exp, then_exp)
+ else
+ cond = ECMA262::ExpCond.new(ls2.cond, then_exp, else_exp)
end
+ ret = ECMA262::StReturn.new(cond)
+ #puts ret.to_js
+ #puts ls2.to_js
+ st.replace(ls2, ret)
+ st.remove(ls)
end
- }
- end
+ if st0.to_js.length > st.to_js.length
+ parent0.replace(st0, st)
+ end
+ end
+ }
self
end
#
# if(a)return b;else c;
@@ -468,27 +556,11 @@
if (st.then_st.kind_of? ECMA262::StBlock and st.then_st[-1].kind_of? ECMA262::StReturn) or
st.then_st.kind_of? ECMA262::StReturn
idx = parent.index(st)
parent[idx+1..0] = st.else_st
st.replace(st.else_st, nil)
- end
- end
- }
- self
- end
- #
- # feature
- #
- # if(a)b;else return c;
- # =>
- # if(!a)return c;b;
- #
- def optimize_if_return3(node = @prog)
- node.traverse(nil) {|st, parent|
- if st.kind_of? ECMA262::StIf and st.else_st and parent.kind_of? ECMA262::StatementList
- st.remove_empty_statement
- if (st.else_st.kind_of? ECMA262::StBlock and st.else_st[-1].kind_of? ECMA262::StReturn) or
+ elsif (st.else_st.kind_of? ECMA262::StBlock and st.else_st[-1].kind_of? ECMA262::StReturn) or
st.else_st.kind_of? ECMA262::StReturn
idx = parent.index(st)
parent[idx+1..0] = st.then_st
st.instance_eval{
@then_st = @else_st
@@ -502,40 +574,96 @@
end
def compress_var(node = @prog, options = {})
func_scopes = []
catch_scopes = []
+ with_scopes = []
+ #
+ # ECMA262 10.2:
+ #
+ # Usually a Lexical Environment is associated with some
+ # specific syntactic structure of ECMAScript code such as a
+ # FunctionDeclaration, a WithStatement, or a Catch clause of a
+ # TryStatement and a new Lexical Environment is created each
+ # time such code is evaluated.
+ #
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StFunc
func_scopes.push([st, parent])
elsif st.kind_of? ECMA262::StTry
catch_scopes.push([st, parent])
elsif st.kind_of? ECMA262::StWith
- #TODO
+ with_scopes.push([st, parent])
end
}
- #10.2
#
- # Catch clause of a TryStatement and a new Lexical Environment is
- # created each time such code is evaluated.
+ # 10.2, 12.14
#
+ #eee = 'global';
+ #function test()
+ #{
+ # /*
+ # "eee" is local variable(belongs to this function)
+ # because var declaration is exist in this function.
+ # (see also catch's scope comment)
+ # So, global variable 'eee' is not changed.
+ # */
+ # eee = 'function';
+ # try{
+ # console.log(eee); //=>function
+ # throw "exception";
+ # }
+ # catch(eee){
+ # /*
+ # The catch's variable scope will be created at execution time.
+ # so next var declaration should belong to "test" function.
+ # */
+ # var eee;
+ # /*
+ # In execution time, "eee" belongs to this
+ # catch-clause's scope.
+ # */
+ # console.log(eee); //=>exception
+ # /*
+ # Next function has its own scope and 'eee' belongs to its.
+ # */
+ # (function(){
+ # var eee;
+ # console.log(eee); //=>undefined
+ # })();
+ # }
+ #}
+ #console.log(eee); //=>global
+ #test();
+ #
catch_scopes.each{|st, parent|
catch_context = ECMA262::Context.new
catch_context.lex_env = st.context.lex_env.new_declarative_env()
catch_context.var_env = st.context.var_env
catch_context.lex_env.record.create_mutable_binding(st.catch[0], nil)
catch_context.lex_env.record.set_mutable_binding(st.catch[0], :undefined, nil)
st.catch[0].context = catch_context
st.catch[1].traverse(parent){|st2|
- if st2.kind_of? ECMA262::IdentifierName and st2 == st.catch[0] and
- st2.binding_env == st.catch[0].binding_env
+ if st2.kind_of? ECMA262::IdentifierName and st2 == st.catch[0] and st2.binding_env == st.catch[0].binding_env
st2.context = catch_context
end
}
func_scopes.unshift([st, parent])
}
+# with_scopes.each{|st, parent|
+# with_context = ECMA262::Context.new
+# with_context.lex_env = st.context.lex_env.new_declarative_env()
+# with_context.var_env = st.context.var_env
+# st.statement.traverse(st) {|st2|
+# if st2.kind_of? ECMA262::IdentifierName and st2.binding_env == st.context.var_env
+# st2.context = with_context
+# with_context.lex_env.record.create_mutable_binding(st2, nil)
+# with_context.lex_env.record.set_mutable_binding(st2, :undefined, nil)
+# end
+# }
+# }
func_scopes.reverse!
func_scopes.each {|st, parent|
if st.kind_of? ECMA262::StFunc
context = st.context
elsif st.kind_of? ECMA262::StTry
@@ -584,14 +712,10 @@
outer_vars[var_name] ||= 0
outer_vars[var_name] += 1
elsif st2_lex_env == @global_context.lex_env #global
outer_vars[var_name] ||= 0
outer_vars[var_name] += 1
-# elsif st2_lex_env == context.lex_env and st2_lex_env != context.lex_env
-# nesting_vars[var_name] ||= 0
-# nesting_vars[var_name] += 1
-# nesting_vars_list.push(st2)
elsif st2_lex_env == context.lex_env
var_vars[var_name] ||= 0
var_vars[var_name] += 1
var_vars_list.push(st2)
else
@@ -618,10 +742,14 @@
st.traverse(parent) {|st2|
if st2.kind_of? ECMA262::ExpCall and st2.name.to_js({}) == "eval"
eval_flag = true
break
end
+ if st2.kind_of? ECMA262::StWith
+ eval_flag = true
+ break
+ end
}
if eval_flag
next
end
end
@@ -635,18 +763,22 @@
rename_table = {}
var_vars_array.each {|name, count|
if name.nil?
next #bug?
end
- #STDERR.puts "trying to rename #{name}"
+ if name.length == 1
+ #STDERR.puts "#{name}=>#{count}"
+ next
+ end
+ #STDERR.puts "trying to rename #{name}(#{count})"
while true
#condition b
- if var_vars[var_sym]
- #STDERR.puts "var_vars has #{var_sym}"
- #condigion c
- elsif outer_vars[var_sym]
+ if outer_vars[var_sym]
#STDERR.puts "outer_vars has #{var_sym}"
+ elsif var_vars[var_sym]
+ #STDERR.puts "var_vars has #{var_sym}(#{var_vars[var_sym]})"
+ #condigion c
else #condition a&d
#STDERR.puts "->#{var_sym}"
break
end
var_sym = next_sym(var_sym)
@@ -685,11 +817,11 @@
x.instance_eval{
@val = var_sym2
}
end
#raise 'error' if x.binding_env(:var).nil?
- raise 'error' if x.binding_env(:lex).nil?
+ raise x.to_js if x.binding_env(:lex).nil?
end
end
rename_table[name] = var_sym
var_sym = next_sym(var_sym)
}
@@ -709,15 +841,17 @@
end
end
end
var_vars_list.each {|st2|
- st2.instance_eval{
- @val = rename_table[@val]
- }
- #raise 'error' if st2.binding_env(:var).nil?
- raise 'error' if st2.binding_env(:lex).nil?
+ st2.instance_eval{
+ if rename_table[@val]
+ @val = rename_table[@val]
+ #raise 'error' if st2.binding_env(:var).nil?
+ raise st2.to_js if st2.binding_env(:lex).nil?
+ end
+ }
}
}
self
end
@@ -729,11 +863,10 @@
}
self
end
def simple_replacement(node = @prog)
- retry_flag = false
node.traverse(nil) {|st, parent|
#
#true => !0
#false => !1
#
@@ -775,21 +908,55 @@
# new A() => (new A)
#
elsif st.kind_of? ECMA262::ExpNew and st.args and st.args.length == 0
st.replace(st.args, nil)
parent.add_paren.remove_paren
+ #
+ # !c?a:b => c?b:a
+ # true?a:b => a
+ # false?a:b => b
+ #
+ elsif st.kind_of? ECMA262::ExpCond
+ if st.val.kind_of? ECMA262::ExpLogicalNot
+ st.instance_eval{
+ @val = @val.val
+ t = @val2
+ @val2 = @val3
+ @val3 = t
+ }
+ simple_replacement(st)
+ end
+
+ if st.val.respond_to? :to_ecma262_boolean
+ if st.val.to_ecma262_boolean.nil?
+ ;
+ elsif st.val.to_ecma262_boolean
+ parent.replace(st, st.val2)
+ else
+ parent.replace(st, st.val3)
+ end
+ end
+ #
+ # A["B"] => A.N
+ #
+ elsif st.kind_of? ECMA262::ExpPropBrac and st.val2.kind_of? ECMA262::ECMA262String
+ if idname?(st.val2.val)
+ parent.replace(st, ECMA262::ExpProp.new(st.val, st.val2))
+ elsif !st.val2.to_ecma262_number.nil? and (v=ECMA262::ECMA262Numeric.new(st.val2.to_ecma262_number)).to_ecma262_string == st.val2.to_ecma262_string
+ st.replace(st.val2, v)
+ end
end
}
self
end
#
# reduce_if
#
def reduce_if(node = @prog)
retry_flag = true
- while(retry_flag)
+ while retry_flag
retry_flag = false
node.traverse(nil) {|st, parent|
if st.kind_of? ECMA262::StIf
# if(a)
# if(b) ...;
@@ -798,72 +965,77 @@
if st.else_st.nil? and
st.then_st.kind_of? ECMA262::StIf and st.then_st.else_st.nil?
st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
st.replace(st.then_st, st.then_st.then_st)
end
- #if(a);
- # => a
- #if(a){}
- # => a
- if st.then_st.empty? and st.else_st.nil?
- parent.replace(st, ECMA262::StExp.new(st.cond))
- retry_flag = true
- end
#if(a)z;else;
#if(a)z;else{}
# => {if(a)z;}
if st.else_st and st.else_st.empty?
st.replace(st.else_st, nil)
parent.replace(st, ECMA262::StBlock.new([st]))
retry_flag = true
+ break
end
-
#if(a);else z;
- #=>if(!a)z;
+ #=>{if(!a)z};
#if(a){}else z;
- #=>if(!a)z;
+ #=>{if(!a)z};
if st.then_st.empty? and st.else_st
st.replace(st.cond, ECMA262::ExpLogicalNot.new(st.cond));
else_st = st.else_st
st.replace(st.else_st, nil)
st.replace(st.then_st, else_st)
parent.replace(st, ECMA262::StBlock.new([st]))
retry_flag = true
+ break
end
+ #if(a);
+ # => a
+ #if(a){}
+ # => a
+ if st.then_st.empty? and st.else_st.nil?
+ parent.replace(st, ECMA262::StExp.new(st.cond))
+ end
=begin
-#feature
- #
#if(!(a&&b))
#=>
#if(!a||!b)
- #
- #if(!(a||b))
- #=>
- #if(!a&&!b)
- #
if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
st.cond.val.val.kind_of? ECMA262::ExpLogicalAnd
a = ECMA262::ExpLogicalNot.new(st.cond.val.val.val)
b = ECMA262::ExpLogicalNot.new(st.cond.val.val.val2)
- r = ECMA262::ExpLogicalOr.new(a,b).add_paren.remove_paren
- if r.to_js.length < st.cond.to_js.length
+ r = ECMA262::ExpLogicalOr.new(a,b).add_remove_paren
+ if r.to_js.length <= st.cond.to_js.length
st.replace(st.cond, r)
end
- elsif st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
+ end
+ #if(!(a||b))
+ #=>
+ #if(!a&&!b)
+ if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
st.cond.val.val.kind_of? ECMA262::ExpLogicalOr
a = ECMA262::ExpLogicalNot.new(st.cond.val.val.val)
b = ECMA262::ExpLogicalNot.new(st.cond.val.val.val2)
- r = ECMA262::ExpLogicalAnd.new(a,b).add_paren.remove_paren
- if r.to_js.length < st.cond.to_js.length
+ r = ECMA262::ExpLogicalAnd.new(a,b).add_remove_paren
+ if r.to_js.length <= st.cond.to_js.length
st.replace(st.cond, r)
end
end
=end
+ #if((a))
+ if st.cond.kind_of? ECMA262::ExpParen
+ st.replace(st.cond, st.cond.val)
+ end
+ #if(!!a)
+ if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpLogicalNot
+ st.replace(st.cond, st.cond.val.val)
+ end
end
}
- block_to_statement if retry_flag
end
+ block_to_statement
self
end
def assignment_after_var(node = @prog)
def rewrite_var(var_st, name, initializer)
@@ -944,16 +1116,26 @@
if $0 == __FILE__
argv = ARGV.dup
f = []
options = {}
argv.each do |x|
- if x.match(/^--?/)
+ if x.match(/^--?version/)
+ puts Minjs::VERSION
+ exit(0)
+ elsif x.match(/^--?/)
opt = $'.gsub(/-/, '_').to_sym
options[opt] = true
else
f.push(open(x.to_s).read())
end
end
+
+ js = f.join("\n")
+
comp = Minjs::Compressor.new(:debug => false)
- comp.compress(f.join("\n"), options)
- puts comp.to_js(options)
+ comp.compress(js, options)
+ comp_js = comp.to_js(options)
+ #p comp_js.length
+ js = comp_js
+ puts js
+
end