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