lib/minjs/ecma262/st.rb in minjs-0.1.3 vs lib/minjs/ecma262/st.rb in minjs-0.1.5
- old
+ new
@@ -7,117 +7,19 @@
def to_return?
false
end
- def priority(exp)
+ def priority
999
end
- end
- #statement_list
- class StList < St
- attr_reader :statement_list
- #
- # statement_list: [statement, statement, ...]
- #
- def initialize(statement_list)
- @statement_list = statement_list
+ def last_statement
+ puts "warning: #{self.class}: last_statement not implement"
end
-
- def grouping
- sl = @statement_list
- i = 0
- while i < sl.length
- st = sl[i]
- i0 = i
- prev = nil
- t = nil
- while st and st.to_exp?
- if prev and prev.to_exp?
- t = ECMA262::ExpComma.new(t, st.to_exp({}))
- elsif prev.nil?
- t = st.to_exp({})
- else
- break
- end
- prev = st
- i += 1
- st = sl[i]
- end
- if i0 != i and i - i0 >= 2
- sl[i0...i] = StExp.new(t)
- i = (i - i0 + 1)
- else
- i += 1
- end
- end
- end
-
- def replace(from, to)
- idx = @statement_list.index(from)
- if idx
- @statement_list[idx] = to
- end
- end
-
- def remove(st)
- @statement_list.delete(st)
- end
-
- def remove_empty_statement
- @statement_list.reject!{|x|
- x.class == StEmpty
- }
- end
-
- def traverse(parent, &block)
- @statement_list.each do|st|
- st.traverse(self, &block)
- end
- yield self, parent
- end
-
- def to_js(options = {})
- concat options, @statement_list
- end
-
- def length
- @statement_list.length
- end
-
- def to_exp?
- @statement_list.each do |s|
- return false if s.to_exp? == false
- end
- return true
- end
-
- def to_exp(options)
- return nil if to_exp? == false
- t = @statement_list[0].to_exp(options)
- return t.to_exp(options) if @statement_list.length <= 1
- i = 1
- while(i < @statement_list.length)
- t = ExpComma.new(t, @statement_list[i])
- i += 1
- end
- t
- end
-
- def each(&block)
- @statement_list.each(&block)
- end
-
- def [](i)
- @statement_list[i]
- end
-
- def index(st)
- @statement_list.index(st)
- end
end
+
#
# 12.1
#
class StBlock < St
attr_reader :statement_list
@@ -125,37 +27,72 @@
#statement_list:StList
def initialize(statement_list)
@statement_list = statement_list
end
+ def deep_dup
+ self.class.new(@statement_list.deep_dup)
+ end
+
def traverse(parent, &block)
@statement_list.traverse(self, &block)
yield self, parent
end
def to_js(options = {})
concat(options, "{", @statement_list, "}")
end
def to_exp?
- @statement_list.length == 1 and @statement_list[0].to_exp?
+ t = @statement_list.statement_list.select{|s|
+ s.class != StEmpty
+ }
+ t.length == 1 and t[0].to_exp?
end
- def to_exp(options)
+ def to_exp(options = {})
+ statement_list.remove_empty_statement
@statement_list[0].to_exp({})
end
def to_statement?
- @statement_list.statement_list.select{|s|
+ t = @statement_list.statement_list.select{|s|
s.class != StEmpty
- }.length == 1
+ }
+ return false if t.length != 1
+ #
+ # if(a){ //<= this block must not be removed
+ # while(true)
+ # if(b){
+ # ;
+ # }
+ # }
+ # else{
+ # ;
+ # }
+ #
+ last_st = t[0].last_statement[-2]
+ if last_st.kind_of?(StIf) and last_st.else_st.nil?
+ return false
+ else
+ return true
+ end
end
def to_statement
statement_list.remove_empty_statement
@statement_list[0]
end
+
+ def last_statement
+ list = [self]
+ t = @statement_list.statement_list.select{|s|
+ s.class != StEmpty
+ }
+ return [nil] if t[-1].nil?
+ list.concat(t[-1].last_statement)
+ end
end
#
# 12.2
#
class StVar < St
@@ -168,10 +105,17 @@
def initialize(context, vars)
@vars = vars
@context = context
end
+ def deep_dup
+ self.class.new(@context,
+ @vars.collect{|x,y|
+ [x.deep_dup, y ? y.deep_dup : nil]
+ })
+ end
+
def replace(from, to)
@vars.each do |x|
if x[0] == from
x[0] = to
break
@@ -218,32 +162,56 @@
v1.push(x)
end
end
@vars = v1.concat(v2)
end
+
+ def remove_paren
+ @vars.each do |x|
+ if x[1] and x[1].kind_of? ExpParen and x[1].val.priority <= 130
+ x[1] = x[1].val
+ end
+ end
+ end
+ def last_statement
+ [self]
+ end
end
#12.3 empty
class StEmpty < St
def initialize()
end
+
+ def deep_dup
+ self.class.new()
+ end
+
def traverse(parent, &block)
yield self, parent
end
+
def to_js(options = {})
";"
end
+ def last_statement
+ [nil]
+ end
end
#12.4
class StExp < St
attr_reader :exp
def initialize(exp)
@exp = exp
end
+ def deep_dup
+ self.class.new(@exp.deep_dup)
+ end
+
def replace(from, to)
if @exp == from
@exp = to
end
end
@@ -255,17 +223,26 @@
def to_js(options = {})
concat(options, @exp, ";")
end
- def to_exp(options)
+ def to_exp(options = {})
@exp
end
def to_exp?
true
end
+
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val if @exp.remove_paren?
+ end
+ end
+ def last_statement
+ [self]
+ end
end
#12.5
class StIf < St
attr_reader :then_st, :else_st, :cond
@@ -274,10 +251,14 @@
@cond = cond
@then_st = then_st
@else_st = else_st
end
+ def deep_dup
+ self.class.new(@cond.deep_dup, @then_st.deep_dup, @else_st.deep_dup)
+ end
+
def replace(from, to)
if from == @then_st
@then_st = to
elsif from == @else_st
@else_st = to
@@ -291,38 +272,35 @@
@else_st.traverse(self, &block)
end
yield self, parent
end
+ def deep_dup
+ self.class.new(@cond.deep_dup, @then_st.deep_dup, @else_st ? @else_st.deep_dup : nil)
+ end
+
def to_js(options = {})
if @else_st
concat options, :if, "(", @cond, ")", @then_st, :else, @else_st
else
concat options, :if, "(", @cond, ")", @then_st
end
end
def to_return?
if !@else_st
- return true if @then_st.class == StReturn
+ return false
else
return true if @then_st.class == StReturn and @else_st.class == StReturn
end
end
def to_return
- if !@else_st
- cond = ExpParen.new(@cond)
- then_exp = ExpParen.new(then_st.exp)
- else_exp = ExpVoid.new(ECMA262Numeric.new('0'))
- StReturn.new(ExpCond.new(cond, then_exp, else_exp))
- else
- cond = ExpParen.new(@cond)
- then_exp = ExpParen.new(then_st.exp)
- else_exp = ExpParen.new(else_st.exp)
- StReturn.new(ExpCond.new(cond, then_exp, else_exp))
- end
+ cond = ExpParen.new(@cond)
+ then_exp = ExpParen.new(then_st.exp ? then_st.exp : ExpVoid.new(ExpParen.new(ECMA262Numeric.new(0))))
+ else_exp = ExpParen.new(else_st.exp ? else_st.exp : ExpVoid.new(ExpParen.new(ECMA262Numeric.new(0))))
+ StReturn.new(ExpCond.new(cond, then_exp, else_exp))
end
def to_exp?
if !@else_st
return false if @then_st.to_exp? == false
@@ -331,11 +309,11 @@
return false if @else_st.to_exp? == false
end
return true
end
- def to_exp(options)
+ def to_exp(options = {})
return nil if to_exp? == false
if @else_st
then_exp = @then_st.to_exp(options)
else_exp = @else_st.to_exp(options)
else
@@ -355,18 +333,37 @@
ExpCond.new(ExpParen.new(@cond), then_exp, else_exp)
else
ExpCond.new(@cond, then_exp, else_exp)
end
end
+
+ def remove_paren
+ if @cond.kind_of? ExpParen
+ @cond = @cond.val
+ end
+ end
+
+ def last_statement
+ list = [self]
+ if @else_st
+ list.concat @else_st.last_statement
+ else
+ list.concat @then_st.last_statement
+ end
+ end
end
#12.6
class StWhile < St
def initialize(exp, statement)
@exp, @statement = exp, statement
end
+ def deep_dup
+ self.class.new(@exp.deep_dup, @statement.deep_dup)
+ end
+
def replace(from, to)
if from == @statement
@statement = to
end
end
@@ -384,17 +381,32 @@
statement = @statement
end
concat(options, :while, "(", @exp, ")", statement)
end
+
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val
+ end
+ end
+
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
class StDoWhile < St
def initialize(exp, statement)
@exp, @statement = exp, statement
end
+ def deep_dup
+ self.class.new(@exp.deep_dup, @statement.deep_dup)
+ end
+
def replace(from, to)
if from == @statement
@statement = to
end
end
@@ -412,13 +424,81 @@
statement = @statement
end
concat options, :do, statement, :while, "(", @exp, ")", ";"
end
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val
+ end
+ end
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
#
+ # 12.6.3 the for statement
+ #
+ class StFor < St
+ def initialize(exp1, exp2, exp3, statement)
+ @exp1 = exp1
+ @exp2 = exp2
+ @exp3 = exp3
+ @statement = statement
+ end
+
+ def deep_dup
+ self.class.new(@exp1 && @exp1.deep_dup,
+ @exp2 && @exp2.deep_dup,
+ @exp3 && @exp3.deep_dup,
+ @statement.deep_dup)
+ end
+
+ def replace(from, to)
+ if from == @statement
+ @statement = to
+ end
+ end
+
+ def traverse(parent, &block)
+ @exp1.traverse(self, &block)
+ @exp2.traverse(self, &block)
+ @exp3.traverse(self, &block)
+ @statement.traverse(self, &block)
+ yield self, parent
+ end
+
+ def to_js(options = {})
+ if @statement.kind_of? StBlock and @statement.statement_list.length == 1
+ statement = @statement.statement_list.statement_list[0]
+ else
+ statement = @statement
+ end
+
+ concat options, :for, "(", @exp1, ";", @exp2, ";", @exp3, ")", statement
+ end
+
+ def remove_paren
+ if @exp1.kind_of? ExpParen
+ @exp1 = @exp1.val
+ end
+ if @exp2.kind_of? ExpParen
+ @exp2 = @exp2.val
+ end
+ if @exp3.kind_of? ExpParen
+ @exp3 = @exp3.val
+ end
+ end
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
+ end
+
+ #
# for(var i=0,... ; ; )
#
class StForVar < St
attr_reader :context
@@ -432,10 +512,20 @@
@exp2 = exp2
@exp3 = exp3
@statement = statement
end
+ def deep_dup
+ self.class.new(@context,
+ @var_decl_list.collect{|x,y|
+ [x.deep_dup, y.deep_dup]
+ },
+ @exp2 && @exp2.deep_dup,
+ @exp3 && @exp3.deep_dup,
+ @statement.deep_dup)
+ end
+
def replace(from, to)
if from == @statement
@statement = to
end
end
@@ -488,30 +578,50 @@
end
}.join(",")
t = concat({:for_args => true}.merge(options), :for, "(var", _var_decl_list, ";", @exp2, ";", @exp3, ")")
concat options, t, statement
end
+
+ def remove_paren
+ @var_decl_list.each do|x|
+ if x[1] and x[1].kind_of? ExpParen
+ x[1] = x[1].val
+ end
+ end
+ if @exp2.kind_of? ExpParen
+ @exp2 = @exp2.val
+ end
+ if @exp3.kind_of? ExpParen
+ @exp3 = @exp3.val
+ end
+ end
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
- class StFor < St
- def initialize(exp1, exp2, exp3, statement)
+ class StForIn < St
+ def initialize(exp1, exp2, statement)
@exp1 = exp1
@exp2 = exp2
- @exp3 = exp3
@statement = statement
end
+ def deep_dup
+ self.class.new(@exp1.deep_dup, @exp2.deep_dup, @statement.deep_dup)
+ end
+
def replace(from, to)
if from == @statement
@statement = to
end
end
def traverse(parent, &block)
@exp1.traverse(self, &block)
@exp2.traverse(self, &block)
- @exp3.traverse(self, &block)
@statement.traverse(self, &block)
yield self, parent
end
def to_js(options = {})
@@ -519,12 +629,25 @@
statement = @statement.statement_list.statement_list[0]
else
statement = @statement
end
- concat options, :for, "(", @exp1, ";", @exp2, ";", @exp3, ")", statement
+ concat options, :for, '(', @exp1, :in, @exp2, ')', statement
end
+
+ def remove_paren
+ if @exp1.kind_of? ExpParen and @exp1.priority <= 20 #left-hand
+ @exp1 = @exp1.val
+ end
+ if @exp2.kind_of? ExpParen
+ @exp2 = @exp2.val
+ end
+ end
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
class StForInVar < St
attr_reader :context
@@ -533,10 +656,17 @@
@var_decl = var_decl
@exp2 = exp2
@statement = statement
end
+ def deep_dup
+ self.class.new(@context,
+ [@var_decl[0].deep_dup, @var_decl[1] ? @var_decl[1].deep_dup : nil],
+ @exp2.deep_dup,
+ @statement.deep_dup)
+ end
+
def traverse(parent, &block)
@var_decl[0].traverse(self, &block)
@var_decl[1].traverse(self, &block) if @var_decl[1]
@exp2.traverse(self, &block)
@statement.traverse(self, &block)
@@ -568,54 +698,39 @@
_var_decl = concat(options, @var_decl[0], '=', @var_decl[1])
else
_var_decl = concat(options, @var_decl[0])
end
-# if options[:compress_var]
-# concat options, :for, "(", _var_decl, :in, @exp2, ")", statement
-# else
concat options, :for, "(", :var, _var_decl, :in, @exp2, ")", statement
-# end
end
- end
- class StForIn < St
- def initialize(exp1, exp2, statement)
- @exp1 = exp1
- @exp2 = exp2
- @statement = statement
- end
-
- def replace(from, to)
- if from == @statement
- @statement = to
+ def remove_paren
+ if @var_decl[1] and @var_decl[1].kind_of? ExpParen
+ @var_decl[1] = @var_decl[1].val
end
+ if @exp2.kind_of? ExpParen
+ @exp2 = @exp2.val
+ end
end
- def traverse(parent, &block)
- @exp1.traverse(self, &block)
- @exp2.traverse(self, &block)
- @statement.traverse(self, &block)
- yield self, parent
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
end
-
- def to_js(options = {})
- if @statement.kind_of? StBlock and @statement.statement_list.length == 1
- statement = @statement.statement_list.statement_list[0]
- else
- statement = @statement
- end
-
- concat options, :for, '(', @exp1, :in, @exp2, ')', statement
- end
end
+
#12.7
class StContinue < St
def initialize(exp = nil)
@exp = exp
end
+
+ def deep_dup
+ self.class.new(@exp)
+ end
+
def traverse(parent, &block)
@exp.traverse(self, &block) if @exp
yield self, parent
end
def to_js(options = {})
@@ -623,18 +738,25 @@
concat options, :continue, @exp, ";"
else
concat options, :continue, ";"
end
end
+ def last_statement
+ [self]
+ end
end
#12.8
class StBreak < St
def initialize(exp = nil)
@exp = exp
end
+ def deep_dup
+ self.class.new(@exp)
+ end
+
def traverse(parent, &block)
@exp.traverse(self, &block) if @exp
yield self, parent
end
@@ -643,54 +765,95 @@
concat options, :break, @exp, ";"
else
concat options, :break, ";"
end
end
+ def last_statement
+ [self]
+ end
end
#12.9
class StReturn < St
attr_reader :exp
def initialize(exp = nil)
@exp = exp
end
+ def deep_dup
+ self.class.new(@exp)
+ end
+
+ def deep_dup
+ self.class.new(exp ? exp.deep_dup : nil)
+ end
+
def replace(from, to)
if from == @exp
@exp = to
end
end
+
def traverse(parent, &block)
@exp.traverse(self, &block) if @exp
yield self, parent
end
+ def to_return?
+ true
+ end
+
+ def to_return
+ self
+ end
+
def to_js(options = {})
if @exp
concat options, :return, @exp, ";"
else
concat options, :return, ";"
end
end
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val
+ end
+ end
+ def last_statement
+ [self]
+ end
end
#12.10
class StWith < St
def initialize(exp, statement)
@exp = exp
@statement = statement
end
+ def deep_dup
+ self.class.new(@exp)
+ end
+
def traverse(parent, &block)
@exp.traverse(self, &block)
@statement.traverse(self, &block)
yield self, parent
end
def to_js(options = {})
concat options, :with, "(", @exp, ")", @statement
end
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val
+ end
+ end
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
#12.11
class StSwitch < St
#
# block: [condition, blocks]
@@ -698,10 +861,17 @@
def initialize(exp, blocks)
@exp = exp
@blocks = blocks
end
+ def deep_dup
+ self.class.new(@exp,
+ @blocks.collect{|x, y|
+ [x.deep_dup, y.deep_dup]
+ })
+ end
+
def replace(from, to)
if @exp == from
@exp = to
elsif @blocks == from
@blocks = to
@@ -728,18 +898,36 @@
t = concat(options, t, :default, ":", b[1])
end
end
t = concat(options, t, "}")
end
+
+ def remove_paren
+ if @exp.kind_of? ExpParen
+ @exp = @exp.val
+ end
+ @blocks.each do |b|
+ if b[0] and b[0].kind_of? ExpParen
+ b[0] = b[0].val
+ end
+ end
+ end
+ def last_statement
+ list = [self]
+ end
end
#12.12
class StLabelled < St
def initialize(id, statement)
@id = id
@statement = statement
end
+ def deep_dup
+ self.class.new(@id, @statement)
+ end
+
def replace(from, to)
if from == @id
@id = to
elsif from == @statement
@statement = to
@@ -753,36 +941,53 @@
end
def to_js(options = {})
concat options, @id, ":", @statement
end
+
+ def last_statement
+ list = [self]
+ list.concat @statement.last_statement
+ end
end
#12.13
class StThrow < St
def initialize(exp)
@exp = exp
end
+ def deep_dup
+ self.class.new(@exp)
+ end
+
def traverse(parent, &block)
@exp.traverse(self, &block)
yield self, parent
end
def to_js(options = {})
concat options, :throw, @exp, ";"
end
+
+ def last_statement
+ [self]
+ end
end
#12.14
class StTry < St
def initialize(try, catch, finally)
@try = try
@catch = catch
@finally = finally
end
+ def deep_dup
+ self.class.new(@try, @catch, @finally)
+ end
+
def replace(from, to)
if from == @try
@try = to
elsif from == @catch[0]
@catch[0] = to
@@ -810,21 +1015,36 @@
concat(options, :try, @try, :catch, "(", @catch[0], ")", @catch[1])
else
concat(options, :try, @try, :finally, @finally)
end
end
+ def last_statement
+ [self]
+ end
end
#12.15
class StDebugger < St
+ def deep_dup
+ self.class.new
+ end
+
def traverse
yield self, parent
end
def to_js(options = {})
concat options, :debugger, ";"
end
+ def last_statement
+ [self]
+ end
end
- #13 function
+
+ #
+ # 13 function / function expression
+ #
+ # 11.1.5 getter/setter
+ #
class StFunc < St
attr_reader :name
attr_reader :args
attr_reader :statements
attr_reader :context
@@ -837,14 +1057,21 @@
@decl = options[:decl]
@getter = options[:getter]
@setter = options[:setter]
end
- def priority(exp)
+ def priority
10
end
+ def deep_dup
+ self.class.new(@context, @name ? @name.deep_dup : nil,
+ @args.collect{|args|args.deep_dup},
+ @statements.deep_dup,
+ {decl: @decl, getter: @getter, setter: @setter})
+ end
+
def traverse(parent, &block)
@name.traverse(self, &block) if @name
@args.each do |arg|
arg.traverse(self, &block)
end
@@ -871,9 +1098,13 @@
@setter
end
def decl?
@decl
+ end
+
+ def last_statement
+ [self]
end
end
end
end