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

# class TypeProf::Core::AST::DefNode

### Attributes

block[R]
body[R]
mid[R]
mid_code_range[R]
opt_keyword_defaults[R]
opt_keywords[R]
opt_positional_defaults[R]
opt_positionals[R]
post_positionals[R]
rbs_method_type[R]
req_keywords[R]
req_positionals[R]
rest_keywords[R]
rest_positionals[R]
reusable[R]
singleton[R]
tbl[R]

### Public Class Methods

new(raw_node, lenv, use_result) click to toggle source
Calls superclass method `TypeProf::Core::AST::Node::new`

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 112
    def initialize(raw_node, lenv, use_result)
      super(raw_node, lenv)
      # TODO: warn "def self.foo" in a metaclass
      singleton = !!raw_node.receiver || lenv.cref.scope_level == :metaclass
      mid = raw_node.name
      mid_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
      @tbl = raw_node.locals
      raw_args = raw_node.parameters
      raw_body = raw_node.body

      @rbs_method_type = AST.get_rbs_comment_before(raw_node, lenv)

      @singleton = singleton
      @mid = mid
      @mid_code_range = mid_code_range

      ncref = CRef.new(lenv.cref.cpath, @singleton ? :class : :instance, @mid, lenv.cref)
      nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
      if raw_body
        @body = AST.create_node(raw_body, nlenv)
      else
        pos = code_range.last.left.left.left # before "end"
        cr = TypeProf::CodeRange.new(pos, pos)
        @body = DummyNilNode.new(cr, nlenv)
      end

      h = AST.parse_params(@tbl, raw_args, nlenv)
      @req_positionals = h[:req_positionals]
      @opt_positionals = h[:opt_positionals]
      @opt_positional_defaults = h[:opt_positional_defaults]
      @rest_positionals = h[:rest_positionals]
      @post_positionals = h[:post_positionals]
      @req_keywords = h[:req_keywords]
      @opt_keywords = h[:opt_keywords]
      @opt_keyword_defaults = h[:opt_keyword_defaults]
      @rest_keywords = h[:rest_keywords]
      @block = h[:block]
      @args_code_ranges = h[:args_code_ranges] || []

      # If the result of `def` statement, stop reusing this node
      # TODO: `private def ...` should be handled well
      @reusable = !use_result
    end

### Public Instance Methods

attrs(= { singleton:, mid:, mid_code_range:, tbl:, req_positionals:, opt_positionals:, rest_positionals:, post_positionals:, req_keywords:, opt_keywords:, rest_keywords:, block:, reusable:, }) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 178
        def attrs = {
          singleton:,
          mid:,
          mid_code_range:,
          tbl:,
          req_positionals:,
          opt_positionals:,
          rest_positionals:,
          post_positionals:,
          req_keywords:,
          opt_keywords:,
          rest_keywords:,
          block:,
          reusable:,
        }

        def mname_code_range(_name) = @mid_code_range

        def define(genv) # NOT define0
          return define_copy(genv) if @prev_node && @reusable
          super(genv)
        end

        def install(genv) # NOT install0
          return install_copy(genv) if @prev_node && @reusable
          super(genv)
        end

        def install0(genv)
          if @rbs_method_type
            @changes.add_method_decl_box(genv, @lenv.cref.cpath, @singleton, @mid, [@rbs_method_type], false)
          end

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

          req_positionals = @req_positionals.map {|var| @body.lenv.new_var(var, self) }
          opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
          rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
          post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
          req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
          opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
          rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
          block = @block ? @body.lenv.new_var(@block, self) : nil

          if rest_positionals
            @changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
          end

          @opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
            @changes.add_edge(genv, expr.install(genv), vtx)
          end
          @opt_keyword_defaults.zip(opt_keywords) do |expr, vtx|
            @changes.add_edge(genv, expr.install(genv), vtx)
          end

          if block
            block = @body.lenv.set_var(:"*given_block", block)
          else
            block = @body.lenv.new_var(:"*given_block", self)
          end

          if @body
            e_ret = @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
            @body.install(genv)
            @body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret, e_ret))
          end

          f_args = FormalArguments.new(
            req_positionals,
            opt_positionals,
            rest_positionals,
            post_positionals,
            req_keywords,
            opt_keywords,
            rest_keywords,
            block,
          )

          @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)

          Source.new(Type::Symbol.new(genv, @mid))
        end

        def last_stmt_code_range
          if @body
            if @body.is_a?(AST::StatementsNode)
              @body.stmts.last.code_range
            else
              @body.code_range
            end
          else
            nil
          end
        end

        def retrieve_at(pos, &blk)
          if @rbs_method_type
            if @rbs_method_type.code_range.include?(pos) # annotation
              @rbs_method_type.retrieve_at(pos, &blk)
            end
          end
          @args_code_ranges.each_with_index do |cr, i|
            if cr.include?(pos)
              yield DummySymbolNode.new(@tbl[i], cr, @body.lenv.get_var(@tbl[i]))
              break
            end
          end
          super(pos, &blk)
        end

        def modified_vars(tbl, vars)
          # skip
        end
      end

      class AliasNode < Node
        def initialize(raw_node, lenv)
          super(raw_node, lenv)
          @new_mid = AST.create_node(raw_node.new_name, lenv)
          @old_mid = AST.create_node(raw_node.old_name, lenv)
        end

        attr_reader :new_mid, :old_mid

        def subnodes = { new_mid:, old_mid: }

        def install0(genv)
          @new_mid.install(genv)
          @old_mid.install(genv)
          if @new_mid.is_a?(SymbolNode) && @old_mid.is_a?(SymbolNode)
            new_mid = @new_mid.lit
            old_mid = @old_mid.lit
            box = @changes.add_method_alias_box(genv, @lenv.cref.cpath, false, new_mid, old_mid)
            box.ret
          else
            Source.new(genv.nil_type)
          end
        end
      end

      class UndefNode < Node
        def initialize(raw_node, lenv)
          super(raw_node, lenv)
          @names = raw_node.names.map do |raw_name|
            AST.create_node(raw_name, lenv)
          end
        end

        attr_reader :names

        def subnodes = { names: }

        def install0(genv)
          @names.each do |name|
            name.install(genv)
          end
          Source.new(genv.nil_type)
        end
      end
    end

define(genv) click to toggle source
Calls superclass method `TypeProf::Core::AST::Node#define`

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 196
    def define(genv) # NOT define0
      return define_copy(genv) if @prev_node && @reusable
      super(genv)
    end

install(genv) click to toggle source
Calls superclass method `TypeProf::Core::AST::Node#install`

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 201
    def install(genv) # NOT install0
      return install_copy(genv) if @prev_node && @reusable
      super(genv)
    end

install0(genv) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 206
    def install0(genv)
      if @rbs_method_type
        @changes.add_method_decl_box(genv, @lenv.cref.cpath, @singleton, @mid, [@rbs_method_type], false)
      end

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

      req_positionals = @req_positionals.map {|var| @body.lenv.new_var(var, self) }
      opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
      rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
      post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
      req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
      opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
      rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
      block = @block ? @body.lenv.new_var(@block, self) : nil

      if rest_positionals
        @changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
      end

      @opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
        @changes.add_edge(genv, expr.install(genv), vtx)
      end
      @opt_keyword_defaults.zip(opt_keywords) do |expr, vtx|
        @changes.add_edge(genv, expr.install(genv), vtx)
      end

      if block
        block = @body.lenv.set_var(:"*given_block", block)
      else
        block = @body.lenv.new_var(:"*given_block", self)
      end

      if @body
        e_ret = @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
        @body.install(genv)
        @body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret, e_ret))
      end

      f_args = FormalArguments.new(
        req_positionals,
        opt_positionals,
        rest_positionals,
        post_positionals,
        req_keywords,
        opt_keywords,
        rest_keywords,
        block,
      )

      @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)

      Source.new(Type::Symbol.new(genv, @mid))
    end

last_stmt_code_range() click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 262
    def last_stmt_code_range
      if @body
        if @body.is_a?(AST::StatementsNode)
          @body.stmts.last.code_range
        else
          @body.code_range
        end
      else
        nil
      end
    end

mname_code_range(_name) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 194
      def mname_code_range(_name) = @mid_code_range

      def define(genv) # NOT define0
        return define_copy(genv) if @prev_node && @reusable
        super(genv)
      end

      def install(genv) # NOT install0
        return install_copy(genv) if @prev_node && @reusable
        super(genv)
      end

      def install0(genv)
        if @rbs_method_type
          @changes.add_method_decl_box(genv, @lenv.cref.cpath, @singleton, @mid, [@rbs_method_type], false)
        end

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

        req_positionals = @req_positionals.map {|var| @body.lenv.new_var(var, self) }
        opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
        rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
        post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
        req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
        opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
        rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
        block = @block ? @body.lenv.new_var(@block, self) : nil

        if rest_positionals
          @changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
        end

        @opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
          @changes.add_edge(genv, expr.install(genv), vtx)
        end
        @opt_keyword_defaults.zip(opt_keywords) do |expr, vtx|
          @changes.add_edge(genv, expr.install(genv), vtx)
        end

        if block
          block = @body.lenv.set_var(:"*given_block", block)
        else
          block = @body.lenv.new_var(:"*given_block", self)
        end

        if @body
          e_ret = @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
          @body.install(genv)
          @body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret, e_ret))
        end

        f_args = FormalArguments.new(
          req_positionals,
          opt_positionals,
          rest_positionals,
          post_positionals,
          req_keywords,
          opt_keywords,
          rest_keywords,
          block,
        )

        @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)

        Source.new(Type::Symbol.new(genv, @mid))
      end

      def last_stmt_code_range
        if @body
          if @body.is_a?(AST::StatementsNode)
            @body.stmts.last.code_range
          else
            @body.code_range
          end
        else
          nil
        end
      end

      def retrieve_at(pos, &blk)
        if @rbs_method_type
          if @rbs_method_type.code_range.include?(pos) # annotation
            @rbs_method_type.retrieve_at(pos, &blk)
          end
        end
        @args_code_ranges.each_with_index do |cr, i|
          if cr.include?(pos)
            yield DummySymbolNode.new(@tbl[i], cr, @body.lenv.get_var(@tbl[i]))
            break
          end
        end
        super(pos, &blk)
      end

      def modified_vars(tbl, vars)
        # skip
      end
    end

modified_vars(tbl, vars) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 289
    def modified_vars(tbl, vars)
      # skip
    end

retrieve_at(pos) { |dummy_symbol_node(tbl, cr, lenv.get_var(tbl))| ... } click to toggle source
Calls superclass method `TypeProf::Core::AST::Node#retrieve_at`

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 274
    def retrieve_at(pos, &blk)
      if @rbs_method_type
        if @rbs_method_type.code_range.include?(pos) # annotation
          @rbs_method_type.retrieve_at(pos, &blk)
        end
      end
      @args_code_ranges.each_with_index do |cr, i|
        if cr.include?(pos)
          yield DummySymbolNode.new(@tbl[i], cr, @body.lenv.get_var(@tbl[i]))
          break
        end
      end
      super(pos, &blk)
    end

subnodes(= { body:, opt_positional_defaults:, opt_keyword_defaults:, rbs_method_type:, }) click to toggle source

    # File typeprof-0.30.1/lib/typeprof/core/ast/method.rb, line 172
      def subnodes = {
        body:,
        opt_positional_defaults:,
        opt_keyword_defaults:,
        rbs_method_type:,
      }
      def attrs = {
        singleton:,
        mid:,
        mid_code_range:,
        tbl:,
        req_positionals:,
        opt_positionals:,
        rest_positionals:,
        post_positionals:,
        req_keywords:,
        opt_keywords:,
        rest_keywords:,
        block:,
        reusable:,
      }

      def mname_code_range(_name) = @mid_code_range

      def define(genv) # NOT define0
        return define_copy(genv) if @prev_node && @reusable
        super(genv)
      end

      def install(genv) # NOT install0
        return install_copy(genv) if @prev_node && @reusable
        super(genv)
      end

      def install0(genv)
        if @rbs_method_type
          @changes.add_method_decl_box(genv, @lenv.cref.cpath, @singleton, @mid, [@rbs_method_type], false)
        end

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

        req_positionals = @req_positionals.map {|var| @body.lenv.new_var(var, self) }
        opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
        rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
        post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
        req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
        opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
        rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
        block = @block ? @body.lenv.new_var(@block, self) : nil

        if rest_positionals
          @changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
        end

        @opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
          @changes.add_edge(genv, expr.install(genv), vtx)
        end
        @opt_keyword_defaults.zip(opt_keywords) do |expr, vtx|
          @changes.add_edge(genv, expr.install(genv), vtx)
        end

        if block
          block = @body.lenv.set_var(:"*given_block", block)
        else
          block = @body.lenv.new_var(:"*given_block", self)
        end

        if @body
          e_ret = @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
          @body.install(genv)
          @body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret, e_ret))
        end

        f_args = FormalArguments.new(
          req_positionals,
          opt_positionals,
          rest_positionals,
          post_positionals,
          req_keywords,
          opt_keywords,
          rest_keywords,
          block,
        )

        @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)

        Source.new(Type::Symbol.new(genv, @mid))
      end

      def last_stmt_code_range
        if @body
          if @body.is_a?(AST::StatementsNode)
            @body.stmts.last.code_range
          else
            @body.code_range
          end
        else
          nil
        end
      end

      def retrieve_at(pos, &blk)
        if @rbs_method_type
          if @rbs_method_type.code_range.include?(pos) # annotation
            @rbs_method_type.retrieve_at(pos, &blk)
          end
        end
        @args_code_ranges.each_with_index do |cr, i|
          if cr.include?(pos)
            yield DummySymbolNode.new(@tbl[i], cr, @body.lenv.get_var(@tbl[i]))
            break
          end
        end
        super(pos, &blk)
      end

      def modified_vars(tbl, vars)
        # skip
      end
    end

    class AliasNode < Node
      def initialize(raw_node, lenv)
        super(raw_node, lenv)
        @new_mid = AST.create_node(raw_node.new_name, lenv)
        @old_mid = AST.create_node(raw_node.old_name, lenv)
      end

      attr_reader :new_mid, :old_mid

      def subnodes = { new_mid:, old_mid: }

      def install0(genv)
        @new_mid.install(genv)
        @old_mid.install(genv)
        if @new_mid.is_a?(SymbolNode) && @old_mid.is_a?(SymbolNode)
          new_mid = @new_mid.lit
          old_mid = @old_mid.lit
          box = @changes.add_method_alias_box(genv, @lenv.cref.cpath, false, new_mid, old_mid)
          box.ret
        else
          Source.new(genv.nil_type)
        end
      end
    end

    class UndefNode < Node
      def initialize(raw_node, lenv)
        super(raw_node, lenv)
        @names = raw_node.names.map do |raw_name|
          AST.create_node(raw_name, lenv)
        end
      end

      attr_reader :names

      def subnodes = { names: }

      def install0(genv)
        @names.each do |name|
          name.install(genv)
        end
        Source.new(genv.nil_type)
      end
    end