Parent

Class Index [+]

Quicksearch

RKelly::Visitors::EvaluationVisitor

Attributes

scope_chain[R]

(Not documented)

Public Class Methods

new(scope) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 5
      def initialize(scope)
        super()
        @scope_chain = scope
        @operand = []
      end

Public Instance Methods

visit_AddNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 52
      def visit_AddNode(o)
        left  = to_primitive(o.left.accept(self), 'Number')
        right = to_primitive(o.value.accept(self), 'Number')

        if left.value.is_a?(::String) || right.value.is_a?(::String)
          RKelly::JS::Property.new(:add,
            "#{left.value}#{right.value}"
          )
        else
          additive_operator(:+, left, right)
        end
      end
visit_ArgumentsNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 241
      def visit_ArgumentsNode(o)
        o.value.map { |x| x.accept(self) }
      end
visit_AssignExprNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 137
      def visit_AssignExprNode(o)
        scope_chain[@operand.last] = o.value.accept(self)
      end
visit_BitwiseNotNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 205
      def visit_BitwiseNotNode(o)
        orig = o.value.accept(self)
        number = to_int_32(orig)
        RKelly::JS::Property.new(nil, ~number.value)
      end
visit_BlockNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 192
      def visit_BlockNode(o)
        o.value.accept(self)
      end
visit_DivideNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 86
      def visit_DivideNode(o)
        left = to_number(o.left.accept(self)).value
        right = to_number(o.value.accept(self)).value
        return_val = 
          if [left, right].any? { |x|
            x.respond_to?(:nan?) && x.nan? ||
            x.respond_to?(:intinite?) && x.infinite?
          }
            RKelly::JS::NaN.new
          elsif [left, right].all? { |x| x == 0 }
            RKelly::JS::NaN.new
          elsif right == 0
            left * (right.eql?(0) ? (1.0/0.0) : (-1.0/0.0))
          else
            left / right
          end
        RKelly::JS::Property.new(:divide, return_val)
      end
visit_DotAccessorNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 178
      def visit_DotAccessorNode(o)
        left = o.value.accept(self)
        right = left.value[o.accessor]
        right.binder = left.value
        right
      end
visit_EqualNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 185
      def visit_EqualNode(o)
        left = o.left.accept(self)
        right = o.value.accept(self)

        RKelly::JS::Property.new(:equal_node, left.value == right.value)
      end
visit_ExpressionStatementNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 48
      def visit_ExpressionStatementNode(o)
        o.value.accept(self)
      end
visit_FalseNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 158
      def visit_FalseNode(o)
        RKelly::JS::Property.new(false, false)
      end
visit_FunctionBodyNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 196
      def visit_FunctionBodyNode(o)
        o.value.accept(self)
        scope_chain.return
      end
visit_FunctionCallNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 168
      def visit_FunctionCallNode(o)
        left      = o.value.accept(self)
        arguments = o.arguments.accept(self)
        call_function(left, arguments)
      end
visit_FunctionDeclNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 18
      def visit_FunctionDeclNode(o)
      end
visit_IfNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 31
      def visit_IfNode(o)
        truthiness = o.conditions.accept(self)
        if truthiness.value && truthiness.value != 0
          o.value.accept(self)
        else
          o.else && o.else.accept(self)
        end
      end
visit_LogicalNotNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 235
      def visit_LogicalNotNode(o)
        bool = to_boolean(o.value.accept(self))
        bool.value = !bool.value
        bool
      end
visit_ModulusNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 105
      def visit_ModulusNode(o)
        left = to_number(o.left.accept(self)).value
        right = to_number(o.value.accept(self)).value
        return_val = 
          if [left, right].any? { |x| x.respond_to?(:nan?) && x.nan? }
            RKelly::JS::NaN.new
          elsif [left, right].all? { |x| x.respond_to?(:infinite?) && x.infinite? }
            RKelly::JS::NaN.new
          elsif right == 0
            RKelly::JS::NaN.new
          elsif left.respond_to?(:infinite?) && left.infinite?
            RKelly::JS::NaN.new
          elsif right.respond_to?(:infinite?) && right.infinite?
            left
          else
            left % right
          end
        RKelly::JS::Property.new(:divide, return_val)
      end
visit_MultiplyNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 71
      def visit_MultiplyNode(o)
        left = to_number(o.left.accept(self)).value
        right = to_number(o.value.accept(self)).value
        return_val = 
          if [left, right].any? { |x| x.respond_to?(:nan?) && x.nan? }
            RKelly::JS::NaN.new
          else
            [left, right].any? { |x|
              x.respond_to?(:intinite?) && x.infinite?
            } && [left, right].any? { |x| x == 0
            } ? RKelly::JS::NaN.new : left * right
          end
        RKelly::JS::Property.new(:multiple, return_val)
      end
visit_NewExprNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 174
      def visit_NewExprNode(o)
        visit_FunctionCallNode(o)
      end
visit_NullNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 150
      def visit_NullNode(o)
        RKelly::JS::Property.new(nil, nil)
      end
visit_NumberNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 141
      def visit_NumberNode(o)
        RKelly::JS::Property.new(o.value, o.value)
      end
visit_OpEqualNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 125
      def visit_OpEqualNode(o)
        left = o.left.accept(self)
        right = o.value.accept(self)
        left.value = right.value
        left.function = right.function
        left
      end
visit_OpPlusEqualNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 133
      def visit_OpPlusEqualNode(o)
        o.left.accept(self).value += o.value.accept(self).value
      end
visit_PostfixNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 211
      def visit_PostfixNode(o)
        orig = o.operand.accept(self)
        number = to_number(orig)
        case o.value
        when '++'
          orig.value = number.value + 1
        when '--'
          orig.value = number.value - 1
        end
        number
      end
visit_PrefixNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 223
      def visit_PrefixNode(o)
        orig = o.operand.accept(self)
        number = to_number(orig)
        case o.value
        when '++'
          orig.value = number.value + 1
        when '--'
          orig.value = number.value - 1
        end
        orig
      end
visit_ResolveNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 40
      def visit_ResolveNode(o)
        scope_chain[o.value]
      end
visit_ReturnNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 201
      def visit_ReturnNode(o)
        scope_chain.return = o.value.accept(self)
      end
visit_SourceElementsNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 11
      def visit_SourceElementsNode(o)
        o.value.each { |x|
          next if scope_chain.returned?
          x.accept(self)
        }
      end
visit_StringNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 162
      def visit_StringNode(o)
        RKelly::JS::Property.new(:string,
          o.value.gsub(/\A['"]/, '').gsub(/['"]$/, '')
        )
      end
visit_SubtractNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 65
      def visit_SubtractNode(o)
        RKelly::JS::Property.new(:subtract,
          o.left.accept(self).value - o.value.accept(self).value
        )
      end
visit_ThisNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 44
      def visit_ThisNode(o)
        scope_chain.this
      end
visit_TrueNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 154
      def visit_TrueNode(o)
        RKelly::JS::Property.new(true, true)
      end
visit_TypeOfNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 245
      def visit_TypeOfNode(o)
        val = o.value.accept(self)
        return RKelly::JS::Property.new(:string, 'object') if val.value.nil?

        case val.value
        when String
          RKelly::JS::Property.new(:string, 'string')
        when Numeric
          RKelly::JS::Property.new(:string, 'number')
        when true
          RKelly::JS::Property.new(:string, 'boolean')
        when false
          RKelly::JS::Property.new(:string, 'boolean')
        when :undefined
          RKelly::JS::Property.new(:string, 'undefined')
        else
          RKelly::JS::Property.new(:object, 'object')
        end
      end
visit_UnaryMinusNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 270
      def visit_UnaryMinusNode(o)
        orig = o.value.accept(self)
        v = to_number(orig)
        v.value = v.value == 0 ? -0.0 : 0 - v.value
        v
      end
visit_UnaryPlusNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 265
      def visit_UnaryPlusNode(o)
        orig = o.value.accept(self)
        to_number(orig)
      end
visit_VarDeclNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 25
      def visit_VarDeclNode(o)
        @operand << o.name
        o.value.accept(self) if o.value
        @operand.pop
      end
visit_VarStatementNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 21
      def visit_VarStatementNode(o)
        o.value.each { |x| x.accept(self) }
      end
visit_VoidNode(o) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 145
      def visit_VoidNode(o)
        o.value.accept(self)
        RKelly::JS::Property.new(:undefined, :undefined)
      end

Private Instance Methods

additive_operator(operator, left, right) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 388
      def additive_operator(operator, left, right)
        left, right = to_number(left).value, to_number(right).value

        left = left.respond_to?(:nan?) && left.nan? ? 0.0/0.0 : left
        right = right.respond_to?(:nan?) && right.nan? ? 0.0/0.0 : right

        result = left.send(operator, right)
        result = result.respond_to?(:nan?) && result.nan? ? JS::NaN.new : result

        RKelly::JS::Property.new(operator, result)
      end
call_function(property, arguments = []) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 400
      def call_function(property, arguments = [])
        function  = property.function || property.value
        case function
        when RKelly::JS::Function
          scope_chain.new_scope { |chain|
            function.js_call(chain, *arguments)
          }
        when UnboundMethod
          RKelly::JS::Property.new(:ruby,
            function.bind(property.binder).call(*(arguments.map { |x| x.value}))
          )
        else
          RKelly::JS::Property.new(:ruby,
            function.call(*(arguments.map { |x| x.value }))
          )
        end
      end
to_boolean(object) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 342
      def to_boolean(object)
        return RKelly::JS::Property.new(false, false) unless object.value
        value = object.value
        boolean =
          case value
          when :undefined
            false
          when true
            true
          when Numeric
            value == 0 || value.respond_to?(:nan?) && value.nan? ? false : true
          when ::String
            value.length == 0 ? false : true
          when RKelly::JS::Base
            true
          else
            raise
          end
        RKelly::JS::Property.new(boolean, boolean)
      end
to_int_32(object) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 363
      def to_int_32(object)
        number = to_number(object)
        value = number.value
        return number if value == 0
        if value.respond_to?(:nan?) && (value.nan? || value.infinite?)
          RKelly::JS::Property.new(nil, 0)
        end
        value = ((value < 0 ? -1 : 1) * value.abs.floor) % (2 ** 32)
        if value >= 2 ** 31
          RKelly::JS::Property.new(nil, value - (2 ** 32))
        else
          RKelly::JS::Property.new(nil, value)
        end
      end
to_number(object) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 304
      def to_number(object)
        return RKelly::JS::Property.new('0', 0) unless object.value

        return_val =
          case object.value
          when :undefined
            RKelly::JS::NaN.new
          when false
            0
          when true
            1
          when Numeric
            object.value
          when ::String
            s = object.value.gsub(/(\A[\s\xB\xA0]*|[\s\xB\xA0]*\Z)/, '')
            if s.length == 0
              0
            else
              case s
              when /^([+-])?Infinity/
                $1 == '-' ? -1.0/0.0 : 1.0/0.0
              when /\A[-+]?\d+\.\d*(?:[eE][-+]?\d+)?$|\A[-+]?\d+(?:\.\d*)?[eE][-+]?\d+$|\A[-+]?\.\d+(?:[eE][-+]?\d+)?$/, /\A[-+]?0[xX][\da-fA-F]+$|\A[+-]?0[0-7]*$|\A[+-]?\d+$/
                s.gsub!(/\.(\D)/, '.0\1') if s =~ /\.\w/
                s.gsub!(/\.$/, '.0') if s =~ /\.$/
                s.gsub!(/^\./, '0.') if s =~ /^\./
                s.gsub!(/^([+-])\./, '\10.') if s =~ /^[+-]\./
                s = s.gsub(/^[0]*/, '') if /^0[1-9]+$/.match(s)
                eval(s)
              else
                RKelly::JS::NaN.new
              end
            end
          when RKelly::JS::Base
            return to_number(to_primitive(object, 'Number'))
          end
        RKelly::JS::Property.new(nil, return_val)
      end
to_primitive(object, preferred_type = nil) click to toggle source

(Not documented)

# File lib/rkelly/visitors/evaluation_visitor.rb, line 378
      def to_primitive(object, preferred_type = nil)
        return object unless object.value
        case object.value
        when false, true, :undefined, ::String, Numeric
          RKelly::JS::Property.new(nil, object.value)
        when RKelly::JS::Base
          call_function(object.value.default_value(preferred_type))
        end
      end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.