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