class TypeProf::Core::AST::Node - typeprof: Ruby Standard Library Documentation

# class TypeProf::Core::AST::Node

### Attributes

changes[R]
lenv[R]
prev_node[R]
ret[R]
static_ret[R]

### Public Class Methods

new(raw_node, lenv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 4
    def initialize(raw_node, lenv)
      @raw_node = raw_node
      @lenv = lenv
      @prev_node = nil
      @static_ret = nil
      @ret = nil

      @changes = ChangeSet.new(self, nil)
    end

### Public Instance Methods

attrs(= {}) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 21
      def attrs = {}

      #: { (TypeProf::Core::AST::Node) -> void } -> nil
      def each_subnode
        queue = subnodes.values

        until queue.empty?
          subnode = queue.shift
          next unless subnode

          case subnode
          when AST::Node
            yield subnode
          when Array
            queue.unshift(*subnode)
          when Hash
            queue.unshift(*subnode.values)
          else
            raise subnode.class.to_s
          end
        end
      end

      def traverse(&blk)
        yield :enter, self
        each_subnode do |subnode|
          subnode.traverse(&blk)
        end
        yield :leave, self
      end

      def code_range
        if @raw_node
          TypeProf::CodeRange.from_node(@raw_node)
        else
          pp self
          raise
        end
      end

      def define(genv)
        @static_ret = define0(genv)
      end

      def define_copy(genv)
        @lenv = @prev_node.lenv
        each_subnode do |subnode|
          subnode.define_copy(genv)
        end
        @prev_node.instance_variable_set(:@reused, true)
        @static_ret = @prev_node.static_ret
      end

      def define0(genv)
        each_subnode do |subnode|
          subnode.define(genv)
        end
        return nil
      end

      def undefine(genv)
        unless @reused
          undefine0(genv)
        end
      end

      def undefine0(genv)
        each_subnode do |subnode|
          subnode.undefine(genv)
        end
      end

      def install(genv)
        @ret = install0(genv)
        @changes.reinstall(genv)
        @ret
      end

      def install_copy(genv)
        @changes.copy_from(@prev_node.changes)
        @changes.reuse(self)
        each_subnode do |subnode|
          subnode.install_copy(genv)
        end
        @ret = @prev_node.ret
      end

      def install0(_)
        raise "should override"
      end

      def uninstall(genv)
        @changes.reinstall(genv)
        each_subnode do |subnode|
          subnode.uninstall(genv)
        end
      end

      def diff(prev_node)
        if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
          raise unless prev_node # annotation
          s1 = subnodes
          s2 = prev_node.subnodes
          return if s1.keys != s2.keys
          s1.each do |key, subnode|
            prev_subnode = s2[key]
            if subnode && prev_subnode
              subnode = [subnode] if subnode.is_a?(AST::Node)
              prev_subnode = [prev_subnode] if prev_subnode.is_a?(AST::Node)
              subnode.zip(prev_subnode) do |subnode0, prev_subnode0|
                next if subnode0 == nil && prev_subnode0 == nil
                subnode0.diff(prev_subnode0)
                return unless subnode0.prev_node
              end
            else
              return if subnode != prev_subnode
            end
          end
          @prev_node = prev_node
        end
      end

      def retrieve_at(pos, &blk)
        if code_range.include?(pos)
          each_subnode do |subnode|
            subnode.retrieve_at(pos, &blk)
          end
          yield self
        end
      end

      def boxes(key)
        @changes.boxes.each do |(k, *), box|
          # TODO: make it recursive
          box.changes.boxes.each do |(k, *), box|
            yield box if k == key
          end
          yield box if k == key
        end
      end

      def diagnostics(genv, &blk)
        @changes.diagnostics.each(&blk)
        @changes.boxes.each_value do |box|
          box.diagnostics(genv, &blk)
        end
        each_subnode do |subnode|
          subnode.diagnostics(genv, &blk)
        end
      end

      def get_vertexes(vtxs)
        return if @reused
        @changes.boxes.each_value do |box|
          vtxs << box.ret
        end
        vtxs << @ret
        each_subnode do |subnode|
          subnode.get_vertexes(vtxs)
        end
      end

      def modified_vars(tbl, vars)
        each_subnode do |subnode|
          subnode.modified_vars(tbl, vars)
        end
      end

      def pretty_print_instance_variables
        super() - [:@raw_node, :@lenv, :@prev_node, :@static_ret, :@changes]
      end
    end

boxes(key) { |box| ... } click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 152
    def boxes(key)
      @changes.boxes.each do |(k, *), box|
        # TODO: make it recursive
        box.changes.boxes.each do |(k, *), box|
          yield box if k == key
        end
        yield box if k == key
      end
    end

code_range() click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 52
    def code_range
      if @raw_node
        TypeProf::CodeRange.from_node(@raw_node)
      else
        pp self
        raise
      end
    end

define(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 61
    def define(genv)
      @static_ret = define0(genv)
    end

define0(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 74
    def define0(genv)
      each_subnode do |subnode|
        subnode.define(genv)
      end
      return nil
    end

define_copy(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 65
    def define_copy(genv)
      @lenv = @prev_node.lenv
      each_subnode do |subnode|
        subnode.define_copy(genv)
      end
      @prev_node.instance_variable_set(:@reused, true)
      @static_ret = @prev_node.static_ret
    end

diagnostics(genv, &blk) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 162
    def diagnostics(genv, &blk)
      @changes.diagnostics.each(&blk)
      @changes.boxes.each_value do |box|
        box.diagnostics(genv, &blk)
      end
      each_subnode do |subnode|
        subnode.diagnostics(genv, &blk)
      end
    end

diff(prev_node) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 119
    def diff(prev_node)
      if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
        raise unless prev_node # annotation
        s1 = subnodes
        s2 = prev_node.subnodes
        return if s1.keys != s2.keys
        s1.each do |key, subnode|
          prev_subnode = s2[key]
          if subnode && prev_subnode
            subnode = [subnode] if subnode.is_a?(AST::Node)
            prev_subnode = [prev_subnode] if prev_subnode.is_a?(AST::Node)
            subnode.zip(prev_subnode) do |subnode0, prev_subnode0|
              next if subnode0 == nil && prev_subnode0 == nil
              subnode0.diff(prev_subnode0)
              return unless subnode0.prev_node
            end
          else
            return if subnode != prev_subnode
          end
        end
        @prev_node = prev_node
      end
    end

each_subnode() { |subnode| ... } click to toggle source

: { (`TypeProf::Core::AST::Node`) -> void } -> nil

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 24
    def each_subnode
      queue = subnodes.values

      until queue.empty?
        subnode = queue.shift
        next unless subnode

        case subnode
        when AST::Node
          yield subnode
        when Array
          queue.unshift(*subnode)
        when Hash
          queue.unshift(*subnode.values)
        else
          raise subnode.class.to_s
        end
      end
    end

get_vertexes(vtxs) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 172
    def get_vertexes(vtxs)
      return if @reused
      @changes.boxes.each_value do |box|
        vtxs << box.ret
      end
      vtxs << @ret
      each_subnode do |subnode|
        subnode.get_vertexes(vtxs)
      end
    end

install(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 93
    def install(genv)
      @ret = install0(genv)
      @changes.reinstall(genv)
      @ret
    end

install0(_) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 108
    def install0(_)
      raise "should override"
    end

install_copy(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 99
    def install_copy(genv)
      @changes.copy_from(@prev_node.changes)
      @changes.reuse(self)
      each_subnode do |subnode|
        subnode.install_copy(genv)
      end
      @ret = @prev_node.ret
    end

modified_vars(tbl, vars) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 183
    def modified_vars(tbl, vars)
      each_subnode do |subnode|
        subnode.modified_vars(tbl, vars)
      end
    end

pretty_print_instance_variables() click to toggle source
Calls superclass method

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 189
    def pretty_print_instance_variables
      super() - [:@raw_node, :@lenv, :@prev_node, :@static_ret, :@changes]
    end

retrieve_at(pos) { |self| ... } click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 143
    def retrieve_at(pos, &blk)
      if code_range.include?(pos)
        each_subnode do |subnode|
          subnode.retrieve_at(pos, &blk)
        end
        yield self
      end
    end

subnodes(= {}) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 20
        def subnodes = {}
        def attrs = {}

        #: { (TypeProf::Core::AST::Node) -> void } -> nil
        def each_subnode
          queue = subnodes.values

          until queue.empty?
            subnode = queue.shift
            next unless subnode

            case subnode
            when AST::Node
              yield subnode
            when Array
              queue.unshift(*subnode)
            when Hash
              queue.unshift(*subnode.values)
            else
              raise subnode.class.to_s
            end
          end
        end

        def traverse(&blk)
          yield :enter, self
          each_subnode do |subnode|
            subnode.traverse(&blk)
          end
          yield :leave, self
        end

        def code_range
          if @raw_node
            TypeProf::CodeRange.from_node(@raw_node)
          else
            pp self
            raise
          end
        end

        def define(genv)
          @static_ret = define0(genv)
        end

        def define_copy(genv)
          @lenv = @prev_node.lenv
          each_subnode do |subnode|
            subnode.define_copy(genv)
          end
          @prev_node.instance_variable_set(:@reused, true)
          @static_ret = @prev_node.static_ret
        end

        def define0(genv)
          each_subnode do |subnode|
            subnode.define(genv)
          end
          return nil
        end

        def undefine(genv)
          unless @reused
            undefine0(genv)
          end
        end

        def undefine0(genv)
          each_subnode do |subnode|
            subnode.undefine(genv)
          end
        end

        def install(genv)
          @ret = install0(genv)
          @changes.reinstall(genv)
          @ret
        end

        def install_copy(genv)
          @changes.copy_from(@prev_node.changes)
          @changes.reuse(self)
          each_subnode do |subnode|
            subnode.install_copy(genv)
          end
          @ret = @prev_node.ret
        end

        def install0(_)
          raise "should override"
        end

        def uninstall(genv)
          @changes.reinstall(genv)
          each_subnode do |subnode|
            subnode.uninstall(genv)
          end
        end

        def diff(prev_node)
          if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
            raise unless prev_node # annotation
            s1 = subnodes
            s2 = prev_node.subnodes
            return if s1.keys != s2.keys
            s1.each do |key, subnode|
              prev_subnode = s2[key]
              if subnode && prev_subnode
                subnode = [subnode] if subnode.is_a?(AST::Node)
                prev_subnode = [prev_subnode] if prev_subnode.is_a?(AST::Node)
                subnode.zip(prev_subnode) do |subnode0, prev_subnode0|
                  next if subnode0 == nil && prev_subnode0 == nil
                  subnode0.diff(prev_subnode0)
                  return unless subnode0.prev_node
                end
              else
                return if subnode != prev_subnode
              end
            end
            @prev_node = prev_node
          end
        end

        def retrieve_at(pos, &blk)
          if code_range.include?(pos)
            each_subnode do |subnode|
              subnode.retrieve_at(pos, &blk)
            end
            yield self
          end
        end

        def boxes(key)
          @changes.boxes.each do |(k, *), box|
            # TODO: make it recursive
            box.changes.boxes.each do |(k, *), box|
              yield box if k == key
            end
            yield box if k == key
          end
        end

        def diagnostics(genv, &blk)
          @changes.diagnostics.each(&blk)
          @changes.boxes.each_value do |box|
            box.diagnostics(genv, &blk)
          end
          each_subnode do |subnode|
            subnode.diagnostics(genv, &blk)
          end
        end

        def get_vertexes(vtxs)
          return if @reused
          @changes.boxes.each_value do |box|
            vtxs << box.ret
          end
          vtxs << @ret
          each_subnode do |subnode|
            subnode.get_vertexes(vtxs)
          end
        end

        def modified_vars(tbl, vars)
          each_subnode do |subnode|
            subnode.modified_vars(tbl, vars)
          end
        end

        def pretty_print_instance_variables
          super() - [:@raw_node, :@lenv, :@prev_node, :@static_ret, :@changes]
        end
      end

      class ProgramNode < Node
        def initialize(raw_node, lenv)
          super(raw_node, lenv)

          @tbl = raw_node.locals
          raw_body = raw_node.statements

          @body = AST.create_node(raw_body, lenv, false)
        end

        attr_reader :tbl, :body

        def subnodes = { body: }
        def attrs = { tbl: }

        def install0(genv)
          @tbl.each {|var| @lenv.locals[var] = Source.new(genv.nil_type) }
          @lenv.locals[:"*self"] = lenv.cref.get_self(genv)

          # for toplevel return
          @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
          @body.install(genv)
        end
      end

      class DummyNilNode < Node
        def initialize(code_range, lenv)
          @code_range = code_range
          super(nil, lenv)
        end

        def code_range
          @code_range
        end

        def install0(genv)
          Source.new(genv.nil_type)
        end
      end

      class DummyRHSNode < Node
        def initialize(code_range, lenv)
          @code_range = code_range
          super(nil, lenv)
        end

        def code_range
          @code_range
        end

        def install0(_)
          Vertex.new(self)
        end
      end

      class DummySymbolNode
        def initialize(sym, code_range, ret)
          @sym = sym
          @code_range = code_range
          @ret = ret
        end

        attr_reader :lenv, :prev_node, :ret

        def boxes(_)
          []
        end
      end
    end

traverse() { |:enter, self| ... } click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 44
    def traverse(&blk)
      yield :enter, self
      each_subnode do |subnode|
        subnode.traverse(&blk)
      end
      yield :leave, self
    end

undefine(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 81
    def undefine(genv)
      unless @reused
        undefine0(genv)
      end
    end

undefine0(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 87
    def undefine0(genv)
      each_subnode do |subnode|
        subnode.undefine(genv)
      end
    end

uninstall(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/base.rb, line 112
    def uninstall(genv)
      @changes.reinstall(genv)
      each_subnode do |subnode|
        subnode.uninstall(genv)
      end
    end