lib/minjs/ecma262/exp.rb in minjs-0.1.3 vs lib/minjs/ecma262/exp.rb in minjs-0.1.5

- old
+ new

@@ -10,20 +10,54 @@ end def reduce(parent) end - def priority(exp) + def priority 9999 end end + module BinaryOperation + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority <= self.priority + @val = @val.val if @val.remove_paren? + end + if @val2.kind_of? ExpParen and @val2.val.priority < self.priority + @val2 = @val2.val + end + end + end + + module UnaryOperation + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority <= self.priority + @val = @val.val if @val.remove_paren? + end + end + end + + module AssignmentOperation + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority <= 20 + @val = @val.val if @val.remove_paren? + end + if @val2.kind_of? ExpParen and @val2.val.priority <= 130 + @val2 = @val2.val + end + end + end + class ExpArg1 < Exp def initialize(val) @val = val end + def deep_dup + self.class.new(@val.deep_dup) + end + def replace(from, to) if @val == from @val = to end end @@ -44,10 +78,14 @@ def initialize(val, val2) @val = val @val2 = val2 end + def deep_dup + self.class.new(@val.deep_dup, @val2.deep_dup) + end + def replace(from, to) if @val == from @val = to elsif @val2 == from @val2 = to @@ -63,31 +101,44 @@ def to_js(options = {}) concat options, @val, sym, @val2 end end + # # "" + # class ExpEmpty < Exp + def deep_dup + self.class.new + end + def traverse(parent, &block) end + def to_js(options = {}) "" end end - # ( exp ) + # + # 11.1 primary expression + # class ExpParen < Exp attr_reader :val def initialize(val) @val = val end - def priority(exp) - 0 + def priority + 10 end + def deep_dup + self.class.new(@val.deep_dup) + end + def replace(from, to) if @val == from @val = to end end @@ -98,274 +149,423 @@ end def to_js(options = {}) "(#{@val.to_js(options)})" end - end - # val = val2 - class ExpAssign < ExpArg2 - def sym - "=" + def remove_paren? + js = @val.to_js + if js.match(/^function/) or js.match(/^{/) + false + else + true + end end - def priority(exp) - 130 + + def remove_paren + if @val.kind_of? ExpParen + @val = @val.val if @val.remove_paren? + end end end - class ExpDivAssign < ExpAssign - def sym - "/=" + # + # 11.2 Left-Hand-Side Expressions + # + # function expression: see st.rb:StFunc + # + # 11.2.1 Property Accessors val[val2] + # + class ExpPropBrac < ExpArg2 + def priority + 20 end - def priority(exp) - 130 + + def traverse(parent, &block) + @val.traverse(self, &block) + @val2.traverse(self, &block) + yield self, parent end - end - class ExpMulAssign < ExpAssign - def sym - "*=" + + def to_js(options = {}) + "#{@val.to_js(options)}[#{@val2.to_js(options)}]" end - def priority(exp) - 130 + + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority <= 20 + @val = @val.val if @val.remove_paren? + end + if @val2.kind_of? ExpParen + @val2 = @val2.val + end end end - class ExpModAssign < ExpAssign - def sym - "%=" + # + # => val.val2 + # + class ExpProp < ExpArg2 + def initialize(val, val2) + @val = val + if val2.kind_of? IdentifierName + @val2 = ECMA262::ECMA262String.new(val2.val) + elsif val2.kind_of? ECMA262String + @val2 = val2 + end end - def priority(exp) - 130 + + def priority + 20 end - end - class ExpAddAssign < ExpAssign - def sym - "+=" + + def traverse(parent, &block) + @val.traverse(self, &block) + @val2.traverse(self, &block) + yield self, parent end - def priority(exp) - 130 + + def to_js(options = {}) + "#{@val.to_js(options)}.#{@val2.val}" end - end - class ExpSubAssign < ExpAssign - def sym - "-=" + + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority <= 20 + @val = @val.val if @val.remove_paren? + end end - def priority(exp) - 130 - end end - class ExpLShiftAssign < ExpAssign - def sym - "<<=" + #11.2 + # => name(args) + # + class ExpCall < Exp + attr_reader :name + attr_reader :args + + def initialize(name, args) + @name = name + @args = args end - def priority(exp) - 130 + + def priority + 20 end - end - class ExpRShiftAssign < ExpAssign - def sym - ">>=" + + def deep_dup + self.class.new(@name.deep_dup, @args.collect{|x| x.deep_dup}) end - def priority(exp) - 130 + + def replace(from, to) + @args.each_index do |i| + arg = @args[i] + if arg == from + @args[i] = to + break + end + end end - end - class ExpURShiftAssign < ExpAssign - def sym - ">>>=" + + def traverse(parent, &block) + @name.traverse(self, &block) + @args.each do |x| + x.traverse(self, &block) + end + yield self, parent end - def priority(exp) - 130 + + def to_js(options = {}) + args = @args.collect{|x| x.to_js(options)}.join(",") + "#{@name.to_js(options)}(#{args})" end - end - class ExpAndAssign < ExpAssign - def sym - "&=" + + def remove_paren + if @name.kind_of? ExpParen and @name.val.priority <= 20 + @name = @name.val if @name.remove_paren? + end + if @args + @args.map! do |arg| + if arg.kind_of? ExpParen and arg.val.priority <= 130 #AssignmentOperators + arg.val if arg.remove_paren? + else + arg + end + end + end end - def priority(exp) - 130 - end + end - class ExpOrAssign < ExpAssign - def sym - "|=" + + # + # new M + # new M(a,b,c...) + # + class ExpNew < Exp + def initialize(name, args) + @name = name + @args = args end - def priority(exp) - 130 - end - end - class ExpXorAssign < ExpAssign - def sym - "^=" - end - def priority(exp) - 130 - end - end - # a ? b : c - class ExpCond < Exp - def initialize(val, val2, val3) - @val = val - @val2 = val2 - @val3 = val3 + def priority + 20 end - def priority(exp) - 120 + def deep_dup + self.class.new(@name, + @args.collect{|x| x.deep_dup}) end def replace(from, to) - if from == @val - @val = to - elsif from == @val2 - @val2 = to - elsif from == @val3 - @val3 = to + if @name == from + @name = from + elsif @args and (idx = @args.index(from)) + @args[idx] = to end end def traverse(parent, &block) - @val.traverse(self, &block) - @val2.traverse(self, &block) - @val3.traverse(self, &block) + @name.traverse(self, &block) + if @args + @args.each do |arg| + arg.traverse(self, &block) + end + end yield self, parent end def to_js(options = {}) - "#{@val.to_js(options)}?#{@val2.to_js(options)}:#{@val3.to_js(options)}" + if @args + args = @args.collect{|x| x.to_js(options)}.join(",") + concat options, :new, @name, '(', args, ')' + else + concat options, :new, @name + end end + + def remove_paren + if @name.kind_of? ExpParen and @name.val.priority <= 20 + @name = @name.val if @name.remove_paren? + end + if @args + @args.map! do |arg| + if arg.kind_of? ExpParen and arg.val.priority <= 130 #AssignmentOperators + arg.val if arg.remove_paren? + else + arg + end + end + end + end end - # || - class ExpLogicalOr < ExpArg2 + # + # 11.3 Postfix Expressions + # + class ExpPostInc < ExpArg1 + include UnaryOperation def sym - "||" + "++" end - def priority(exp) - 118 + def priority + 30 end + def to_js(options = {}) + concat options, @val, sym + end end - - # && - class ExpLogicalAnd < ExpArg2 + class ExpPostDec < ExpArg1 + include UnaryOperation def sym - "&&" + "--" end - def priority(exp) - 116 + def priority + 30 end + def to_js(options = {}) + concat options, @val, sym + end end - - # | - class ExpOr < ExpArg2 + # + # 11.4 + # unary expression + # + class ExpDelete < ExpArg1 + include UnaryOperation def sym - "|" + "delete" end - def priority(exp) - 108 + def priority + 40 end end - - # ^ - class ExpXor < ExpArg2 + class ExpVoid < ExpArg1 + include UnaryOperation def sym - "^" + "void" end - def priority(exp) - 106 + def priority + 40 end end - - # & - class ExpAnd < ExpArg2 + class ExpTypeof < ExpArg1 + include UnaryOperation def sym - "&" + "typeof" end - def priority(exp) - 104 + def priority + 40 end end - # 11.9 - # == - class ExpEq < ExpArg2 + class ExpPreInc < ExpArg1 + include UnaryOperation def sym - "==" + "++" end - def priority(exp) - 90 + def priority + 40 end end - # != - class ExpNotEq < ExpArg2 + class ExpPreDec < ExpArg1 + include UnaryOperation def sym - "!=" + "--" end - def priority(exp) - 90 + def priority + 40 end end - # === - class ExpStrictEq < ExpArg2 + class ExpPositive < ExpArg1 + include UnaryOperation def sym - "===" + "+" end - def priority(exp) - 90 + def priority + 40 end + + def reduce(parent) + if @val.kind_of? ECMA262Numeric + parent.replace(self, @val) + end + end end - # !== - class ExpStrictNotEq < ExpArg2 + + class ExpNegative < ExpArg1 + include UnaryOperation def sym - "!==" + "-" end - def priority(exp) - 90 + def priority + 40 end - end - class ExpLt < ExpArg2 + def reduce(parent) + if @val.kind_of? ECMA262Numeric + if @val.integer.match(/^\-/) + integer = $' + else + integer = "-#{@val.integer}" + end + val = ECMA262Numeric.new(integer, @val.decimal, @val.exp) + parent.replace(self, val) + end + end + end + class ExpBitwiseNot < ExpArg1 + include UnaryOperation def sym - "<" + "~" end - def priority(exp) - 80 + def priority + 40 end end + class ExpLogicalNot < ExpArg1 + include UnaryOperation + def sym + "!" + end + def priority + 40 + end + end - class ExpGt < ExpArg2 + # + # 11.5.1 Applying the * Operator + # + class ExpMul < ExpArg2 + include BinaryOperation + def sym - ">" + "*" end - def priority(exp) - 80 + + def priority + 50 end + + def reduce(parent) + # a * 1 => a + if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.to_num == 1 + parent.replace(self, @val2) + end + # 1 * b => b + if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val2.to_num == 1 + parent.replace(self, @val) + end + # N * M => (N * M) + if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer? + parent.replace(self, ECMA262Numeric.new(@val.to_num * @val2.to_num)) + end +=begin + # ((a * N) * M) or ((N * a) * M) + if @val2.kind_of? ECMA262Numeric and @val2.integer? and @val.kind_of? ExpMul + if @val.val2.kind_of? ECMA262Numeric and @val.val2.integer? + @val2 = ECMA262Numeric.new(@val.val2.to_num * @val2.to_num) + @val = @val.val + elsif @val.val.kind_of? ECMA262Numeric and @val.val.integer? + @val2 = ECMA262Numeric.new(@val.val.to_num * @val2.to_num) + @val = @val.val2 + end + end +=end + end end - class ExpLtEq < ExpArg2 + # + # 11.5.2 Applying the / Operator + # + class ExpDiv < ExpArg2 + include BinaryOperation def sym - "<=" + "/" end - def priority(exp) - 80 + def priority + 50 end end - class ExpGtEq < ExpArg2 + # + # 11.5.3 Applying the % Operator + # + class ExpMod < ExpArg2 + include BinaryOperation def sym - ">=" + "%" end - def priority(exp) - 80 + def priority + 50 end end - #+ + # + #11.6.1 The Addition operator ( + ) + # class ExpAdd < ExpArg2 + include BinaryOperation def sym "+" end - def priority(exp) + + def priority 60 end def reduce(parent) # a + 0 => a @@ -378,10 +578,11 @@ end # N + M => (N + M) if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer? parent.replace(self, ECMA262Numeric.new(@val.to_num + @val2.to_num)) end +=begin if @val2.kind_of? ECMA262Numeric and @val2.integer? # ((a + N) + M) or ((N + a) + M) if @val.kind_of? ExpAdd if @val.val2.kind_of? ECMA262Numeric and @val.val2.integer? @val2 = ECMA262Numeric.new(@val.val2.to_num + @val2.to_num) @@ -399,19 +600,25 @@ @val2 = ECMA262Numeric.new(-(@val.val.to_num - @val2.to_num)) @val = @val.val2 end end end +=end end end - + # + # 11.6.2 The Subtraction Operator ( - ) + # class ExpSub < ExpArg2 + include BinaryOperation + def sym "-" end - def priority(exp) + + def priority 60 end def reduce(parent) # a - 0 => a @@ -424,10 +631,11 @@ end # N - M => (N - M) if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer? parent.replace(self, ECMA262Numeric.new(@val.to_num - @val2.to_num)) end +=begin if @val2.kind_of? ECMA262Numeric and @val2.integer? # ((a - N) - M) or ((N - a) - M) if @val.kind_of? ExpSub if @val.val2.kind_of? ECMA262Numeric and @val.val2.integer? @val2 = ECMA262Numeric.new(@val.val2.to_num + @val2.to_num) @@ -445,352 +653,400 @@ @val2 = ECMA262Numeric.new(-(@val.val.to_num - @val2.to_num)) @val = @val.val2 end end end +=end end end - class ExpInstanceOf < ExpArg2 - def sym - "instanceof" - end - def priority(exp) - 80 - end - end - - class ExpIn < ExpArg2 - def sym - "in" - end - def priority(exp) - 80 - end - end - + # + # 11.7.1 The Left Shift Operator ( << ) + # class ExpLShift < ExpArg2 + include BinaryOperation def sym "<<" end - def priority(exp) + def priority 70 end end + # + # 11.7.2 The Signed Right Shift Operator ( >> ) + # class ExpRShift < ExpArg2 + include BinaryOperation def sym ">>" end - def priority(exp) + def priority 70 end end + # + # 11.7.3 The Unsigned Right Shift Operator ( >>> ) + # class ExpURShift < ExpArg2 + include BinaryOperation def sym ">>>" end - def priority(exp) + def priority 70 end end - - class ExpMul < ExpArg2 + # + # 11.8.1 The Less-than Operator ( < ) + # + class ExpLt < ExpArg2 + include BinaryOperation def sym - "*" + "<" end - def priority(exp) - 50 + def priority + 80 end + end - def reduce(parent) - # a * 1 => a - if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.to_num == 1 - parent.replace(self, @val2) - end - # 1 * b => b - if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val2.to_num == 1 - parent.replace(self, @val) - end - # N * M => (N * M) - if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer? - parent.replace(self, ECMA262Numeric.new(@val.to_num * @val2.to_num)) - end - # ((a * N) * M) or ((N * a) * M) - if @val2.kind_of? ECMA262Numeric and @val2.integer? and @val.kind_of? ExpMul - if @val.val2.kind_of? ECMA262Numeric and @val.val2.integer? - @val2 = ECMA262Numeric.new(@val.val2.to_num * @val2.to_num) - @val = @val.val - elsif @val.val.kind_of? ECMA262Numeric and @val.val.integer? - @val2 = ECMA262Numeric.new(@val.val.to_num * @val2.to_num) - @val = @val.val2 - end - end + # + # 11.8.2 The Greater-than Operator ( > ) + # + class ExpGt < ExpArg2 + include BinaryOperation + def sym + ">" end + def priority + 80 + end end - class ExpDiv < ExpArg2 + # + # 11.8.3 The Less-than-or-equal Operator ( <= ) + # + class ExpLtEq < ExpArg2 + include BinaryOperation def sym - "/" + "<=" end - def priority(exp) - 50 + def priority + 80 end end - class ExpMod < ExpArg2 + # + # 11.8.4 The Greater-than-or-equal Operator ( >= ) + # + class ExpGtEq < ExpArg2 + include BinaryOperation def sym - "%" + ">=" end - def priority(exp) - 50 + def priority + 80 end end # - # 11.4 - # unary expression + # 11.8.6 The instanceof operator # - class ExpDelete < ExpArg1 + class ExpInstanceOf < ExpArg2 + include BinaryOperation def sym - "delete" + "instanceof" end - def priority(exp) - 40 + def priority + 80 end end - class ExpVoid < ExpArg1 + # + # 11.8.7 The in operator + # + class ExpIn < ExpArg2 + include BinaryOperation def sym - "void" + "in" end - def priority(exp) - 40 + def priority + 80 end end - class ExpTypeof < ExpArg1 + # + # 11.9.1 The Equals Operator ( == ) + # + class ExpEq < ExpArg2 + include BinaryOperation def sym - "typeof" + "==" end - def priority(exp) - 40 + def priority + 90 end end - class ExpPostInc < ExpArg1 + # + # 11.9.2 The Does-not-equals Operator ( != ) + # + class ExpNotEq < ExpArg2 + include BinaryOperation def sym - "++" + "!=" end - def priority(exp) - 30 + def priority + 90 end - def to_js(options = {}) - concat options, @val, sym - end end - class ExpPostDec < ExpArg1 + # + # 11.9.4 The Strict Equals Operator ( === ) + # + class ExpStrictEq < ExpArg2 + include BinaryOperation def sym - "--" + "===" end - def priority(exp) - 30 + def priority + 90 end - def to_js(options = {}) - concat options, @val, sym - end end - class ExpPreInc < ExpArg1 + # + # 11.9.5 The Strict Does-not-equal Operator ( !== ) + # + class ExpStrictNotEq < ExpArg2 + include BinaryOperation def sym - "++" + "!==" end - def priority(exp) - 40 + def priority + 90 end end - class ExpPreDec < ExpArg1 + # + # 11.10 Binary Bitwise Operators + # + class ExpAnd < ExpArg2 + include BinaryOperation def sym - "--" + "&" end - def priority(exp) - 40 + def priority + 100 end end - class ExpPositive < ExpArg1 + # ^ + class ExpXor < ExpArg2 + include BinaryOperation def sym - "+" + "^" end - def priority(exp) - 40 + def priority + 106 end - - def reduce(parent) - if @val.kind_of? ECMA262Numeric - parent.replace(self, @val) - end - end end - class ExpNegative < ExpArg1 + # | + class ExpOr < ExpArg2 + include BinaryOperation def sym - "-" + "|" end - def priority(exp) - 40 + def priority + 108 end - - def reduce(parent) - if @val.kind_of? ECMA262Numeric - if @val.integer.match(/^\-/) - integer = $' - else - integer = "-#{@val.integer}" - end - val = ECMA262Numeric.new(integer, @val.decimal, @val.exp) - parent.replace(self, val) - end - end end - class ExpBitwiseNot < ExpArg1 + # + # 11.11 Binary Logical Operators + # + # && + class ExpLogicalAnd < ExpArg2 + include BinaryOperation def sym - "~" + "&&" end - def priority(exp) - 40 + def priority + 110 end end - class ExpLogicalNot < ExpArg1 + # || + class ExpLogicalOr < ExpArg2 + include BinaryOperation def sym - "!" + "||" end - def priority(exp) - 40 + def priority + 116 end end - - class ExpNew < Exp - def initialize(name, args) - @name = name - @args = args + # + # 11.12 Conditional Operator ( ? : ) + # + # val ? val2 : val3 + # + class ExpCond < Exp + def initialize(val, val2, val3) + @val = val + @val2 = val2 + @val3 = val3 end - def priority(exp) - 20 + def priority + 120 end - def replace(from, to) - if @name == from - @name = from - elsif @args and (idx = @args.index(from)) - @args[idx] = to + def remove_paren + if @val.kind_of? ExpParen and @val.val.priority < 120 + @val = @val.val if @val.remove_paren? end - end - - def traverse(parent, &block) - @name.traverse(self, &block) - if @args - @args.each do |arg| - arg.traverse(self, &block) - end + if @val2.kind_of? ExpParen and @val2.val.priority <= 130 + @val2 = @val2.val end - yield self, parent - end - - def to_js(options = {}) - if @args - args = @args.collect{|x| x.to_js(options)}.join(",") - concat options, :new, @name, '(', args, ')' - else - concat options, :new, @name + if @val3.kind_of? ExpParen and @val3.val.priority <= 130 + @val3 = @val3.val end end - end - #11.2 - # => name(args) - # - class ExpCall < Exp - attr_reader :name - attr_reader :args - def initialize(name, args) - @name = name - @args = args + def deep_dup + self.class.new(@val.deep_dup, @val2.deep_dup, @val3.deep_dup) end - def priority(exp) - if @args.index(exp) - 999 - else - 20 - end - end - def replace(from, to) - @args.each_index do |i| - arg = @args[i] - if arg == from - @args[i] = to - break - end + if from == @val + @val = to + elsif from == @val2 + @val2 = to + elsif from == @val3 + @val3 = to end end def traverse(parent, &block) - @name.traverse(self, &block) - @args.each do |x| - x.traverse(self, &block) - end + @val.traverse(self, &block) + @val2.traverse(self, &block) + @val3.traverse(self, &block) yield self, parent end def to_js(options = {}) - args = @args.collect{|x| x.to_js(options)}.join(",") - "#{@name.to_js(options)}(#{args})" + "#{@val.to_js(options)}?#{@val2.to_js(options)}:#{@val3.to_js(options)}" end end # - # => val.val2 + # 11.13 Assignment Operators # - class ExpProp < ExpArg2 - def initialize(val, val2) - @val = val - if val2.kind_of? IdentifierName - @val2 = ECMA262::ECMA262String.new(val2.val) - else - raise "internal error: val2 must be kind_of ItentiferName" - end + class ExpAssign < ExpArg2 + include AssignmentOperation + def sym + "=" end - - def priority(exp) - 20 + def priority + 130 end - - def traverse(parent, &block) - @val.traverse(self, &block) - @val2.traverse(self, &block) - yield self, parent + end + class ExpDivAssign < ExpAssign + include AssignmentOperation + def sym + "/=" end - def to_js(options = {}) - "#{@val.to_js(options)}.#{@val2.val}" + def priority + 130 end end - # - # => val[val2] - # - class ExpPropBrac < ExpArg2 - def priority(exp) - 20 + class ExpMulAssign < ExpAssign + include AssignmentOperation + def sym + "*=" end - - def traverse(parent, &block) - @val.traverse(self, &block) - @val2.traverse(self, &block) - yield self, parent + def priority + 130 end - def to_js(options = {}) - "#{@val.to_js(options)}[#{@val2.to_js(options)}]" + end + class ExpModAssign < ExpAssign + include AssignmentOperation + def sym + "%=" end + def priority + 130 + end end - + class ExpAddAssign < ExpAssign + include AssignmentOperation + def sym + "+=" + end + def priority + 130 + end + end + class ExpSubAssign < ExpAssign + include AssignmentOperation + def sym + "-=" + end + def priority + 130 + end + end + class ExpLShiftAssign < ExpAssign + include AssignmentOperation + def sym + "<<=" + end + def priority + 130 + end + end + class ExpRShiftAssign < ExpAssign + include AssignmentOperation + def sym + ">>=" + end + def priority + 130 + end + end + class ExpURShiftAssign < ExpAssign + include AssignmentOperation + def sym + ">>>=" + end + def priority + 130 + end + end + class ExpAndAssign < ExpAssign + include AssignmentOperation + def sym + "&=" + end + def priority + 130 + end + end + class ExpOrAssign < ExpAssign + include AssignmentOperation + def sym + "|=" + end + def priority + 130 + end + end + class ExpXorAssign < ExpAssign + include AssignmentOperation + def sym + "^=" + end + def priority + 130 + end + end + # + # Comma Operator ( , ) + # class ExpComma < ExpArg2 + include BinaryOperation def sym "," end - def priority(exp) + def priority 140 end end end end