class TypeProf::Core::AST::CallBaseNode
Attributes
block_body[R]
block_f_args[R]
block_pass[R]
block_tbl[R]
keyword_args[R]
mid[R]
mid_code_range[R]
positional_args[R]
recv[R]
splat_flags[R]
yield[R]
Public Class Methods
new(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_block, lenv)
click to toggle source
Calls superclass method
TypeProf::Core::AST::Node::new
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 4 def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_block, lenv) super(raw_node, lenv) @recv = recv @mid = mid @mid_code_range = mid_code_range # args @positional_args = [] @splat_flags = [] @keyword_args = nil @block_pass = nil @block_tbl = nil @block_f_args = nil @block_body = nil if raw_args args = [] @splat_flags = [] raw_args.arguments.each do |raw_arg| if raw_arg.is_a?(Prism::SplatNode) args << raw_arg.expression @splat_flags << true else args << raw_arg @splat_flags << false end end @positional_args = args.map {|arg| AST.create_node(arg, lenv) } if @positional_args.last.is_a?(TypeProf::Core::AST::HashNode) && @positional_args.last.keywords @keyword_args = @positional_args.pop end end @positional_args << last_arg if last_arg if raw_block if raw_block.type == :block_argument_node @block_pass = AST.create_node(raw_block.expression, lenv) else @block_pass = nil @block_tbl = raw_block.locals # TODO: optional args, etc. @block_f_args = case raw_block.parameters when Prism::BlockParametersNode raw_block.parameters.parameters.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name } when Prism::NumberedParametersNode 1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" } when nil [] else raise "not supported yet: #{ raw_block.parameters.class }" end ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref) nlenv = LocalEnv.new(@lenv.path, ncref, {}, @lenv.return_boxes) @block_body = raw_block.body ? AST.create_node(raw_block.body, nlenv) : DummyNilNode.new(code_range, lenv) end end @yield = raw_node.type == :yield_node end
Public Instance Methods
attrs(= { mid:, splat_flags:, block_tbl:, block_f_args:, yield: })
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 73 def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: } def install0(genv) recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self") positional_args = @positional_args.map do |arg| arg.install(genv) end keyword_args = @keyword_args ? @keyword_args.install(genv) : nil if @block_body @lenv.locals.each {|var, vtx| @block_body.lenv.locals[var] = vtx } @block_tbl.each {|var| @block_body.lenv.locals[var] = Source.new(genv.nil_type) } @block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv) blk_f_args = [] if @block_f_args @block_f_args.each do |arg| blk_f_args << @block_body.lenv.new_var(arg, self) end end @lenv.locals.each do |var, vtx| @block_body.lenv.set_var(var, vtx) end vars = [] @block_body.modified_vars(@lenv.locals.keys - @block_tbl, vars) vars.uniq! vars.each do |var| vtx = @lenv.get_var(var) nvtx = vtx.new_vertex(genv, self) @lenv.set_var(var, nvtx) @block_body.lenv.set_var(var, nvtx) end e_ret = @block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self) @block_body.install(genv) @block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret, e_ret)) vars.each do |var| @changes.add_edge(genv, @block_body.lenv.get_var(var), @lenv.get_var(var)) end blk_f_ary_arg = Vertex.new(self) @changes.add_masgn_box(genv, blk_f_ary_arg, blk_f_args, nil, nil) # TODO: support splat "do |a, *b, c|" block = Block.new(self, blk_f_ary_arg, blk_f_args, @block_body.lenv.next_boxes) blk_ty = Source.new(Type::Proc.new(genv, block)) elsif @block_pass blk_ty = @block_pass.install(genv) end a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty) box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv) if @block_body && @block_body.lenv.break_vtx ret = Vertex.new(self) @changes.add_edge(genv, box.ret, ret) @changes.add_edge(genv, @block_body.lenv.break_vtx, ret) ret else box.ret end end def block_last_stmt_code_range if @block_body if @block_body.is_a?(AST::StatementsNode) @block_body.stmts.last.code_range else @block_body.code_range end else nil end end def retrieve_at(pos, &blk) yield self if @mid_code_range && @mid_code_range.include?(pos) each_subnode do |subnode| next unless subnode subnode.retrieve_at(pos, &blk) end end def modified_vars(tbl, vars) subnodes.each do |key, subnode| next unless subnode if key == :block_body subnode.modified_vars(tbl - self.block_tbl, vars) elsif subnode.is_a?(AST::Node) subnode.modified_vars(tbl, vars) else subnode.each {|n| n.modified_vars(tbl, vars) } end end end end
block_last_stmt_code_range()
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 138 def block_last_stmt_code_range if @block_body if @block_body.is_a?(AST::StatementsNode) @block_body.stmts.last.code_range else @block_body.code_range end else nil end end
install0(genv)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 75 def install0(genv) recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self") positional_args = @positional_args.map do |arg| arg.install(genv) end keyword_args = @keyword_args ? @keyword_args.install(genv) : nil if @block_body @lenv.locals.each {|var, vtx| @block_body.lenv.locals[var] = vtx } @block_tbl.each {|var| @block_body.lenv.locals[var] = Source.new(genv.nil_type) } @block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv) blk_f_args = [] if @block_f_args @block_f_args.each do |arg| blk_f_args << @block_body.lenv.new_var(arg, self) end end @lenv.locals.each do |var, vtx| @block_body.lenv.set_var(var, vtx) end vars = [] @block_body.modified_vars(@lenv.locals.keys - @block_tbl, vars) vars.uniq! vars.each do |var| vtx = @lenv.get_var(var) nvtx = vtx.new_vertex(genv, self) @lenv.set_var(var, nvtx) @block_body.lenv.set_var(var, nvtx) end e_ret = @block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self) @block_body.install(genv) @block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret, e_ret)) vars.each do |var| @changes.add_edge(genv, @block_body.lenv.get_var(var), @lenv.get_var(var)) end blk_f_ary_arg = Vertex.new(self) @changes.add_masgn_box(genv, blk_f_ary_arg, blk_f_args, nil, nil) # TODO: support splat "do |a, *b, c|" block = Block.new(self, blk_f_ary_arg, blk_f_args, @block_body.lenv.next_boxes) blk_ty = Source.new(Type::Proc.new(genv, block)) elsif @block_pass blk_ty = @block_pass.install(genv) end a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty) box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv) if @block_body && @block_body.lenv.break_vtx ret = Vertex.new(self) @changes.add_edge(genv, box.ret, ret) @changes.add_edge(genv, @block_body.lenv.break_vtx, ret) ret else box.ret end end
modified_vars(tbl, vars)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 158 def modified_vars(tbl, vars) subnodes.each do |key, subnode| next unless subnode if key == :block_body subnode.modified_vars(tbl - self.block_tbl, vars) elsif subnode.is_a?(AST::Node) subnode.modified_vars(tbl, vars) else subnode.each {|n| n.modified_vars(tbl, vars) } end end end
retrieve_at(pos) { |self| ... }
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 150 def retrieve_at(pos, &blk) yield self if @mid_code_range && @mid_code_range.include?(pos) each_subnode do |subnode| next unless subnode subnode.retrieve_at(pos, &blk) end end
subnodes(= { recv:, positional_args:, keyword_args:, block_body:, block_pass: })
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/ast/call.rb, line 72 def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: } def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: } def install0(genv) recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self") positional_args = @positional_args.map do |arg| arg.install(genv) end keyword_args = @keyword_args ? @keyword_args.install(genv) : nil if @block_body @lenv.locals.each {|var, vtx| @block_body.lenv.locals[var] = vtx } @block_tbl.each {|var| @block_body.lenv.locals[var] = Source.new(genv.nil_type) } @block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv) blk_f_args = [] if @block_f_args @block_f_args.each do |arg| blk_f_args << @block_body.lenv.new_var(arg, self) end end @lenv.locals.each do |var, vtx| @block_body.lenv.set_var(var, vtx) end vars = [] @block_body.modified_vars(@lenv.locals.keys - @block_tbl, vars) vars.uniq! vars.each do |var| vtx = @lenv.get_var(var) nvtx = vtx.new_vertex(genv, self) @lenv.set_var(var, nvtx) @block_body.lenv.set_var(var, nvtx) end e_ret = @block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self) @block_body.install(genv) @block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret, e_ret)) vars.each do |var| @changes.add_edge(genv, @block_body.lenv.get_var(var), @lenv.get_var(var)) end blk_f_ary_arg = Vertex.new(self) @changes.add_masgn_box(genv, blk_f_ary_arg, blk_f_args, nil, nil) # TODO: support splat "do |a, *b, c|" block = Block.new(self, blk_f_ary_arg, blk_f_args, @block_body.lenv.next_boxes) blk_ty = Source.new(Type::Proc.new(genv, block)) elsif @block_pass blk_ty = @block_pass.install(genv) end a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty) box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv) if @block_body && @block_body.lenv.break_vtx ret = Vertex.new(self) @changes.add_edge(genv, box.ret, ret) @changes.add_edge(genv, @block_body.lenv.break_vtx, ret) ret else box.ret end end def block_last_stmt_code_range if @block_body if @block_body.is_a?(AST::StatementsNode) @block_body.stmts.last.code_range else @block_body.code_range end else nil end end def retrieve_at(pos, &blk) yield self if @mid_code_range && @mid_code_range.include?(pos) each_subnode do |subnode| next unless subnode subnode.retrieve_at(pos, &blk) end end def modified_vars(tbl, vars) subnodes.each do |key, subnode| next unless subnode if key == :block_body subnode.modified_vars(tbl - self.block_tbl, vars) elsif subnode.is_a?(AST::Node) subnode.modified_vars(tbl, vars) else subnode.each {|n| n.modified_vars(tbl, vars) } end end end end class CallNode < CallBaseNode def initialize(raw_node, lenv) recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil mid = raw_node.name mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) if raw_node.message_loc raw_args = raw_node.arguments raw_block = raw_node.block super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv) end end class SuperNode < CallBaseNode def initialize(raw_node, lenv) raw_args = raw_node.arguments raw_block = raw_node.block super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv) end end class ForwardingSuperNode < CallBaseNode def initialize(raw_node, lenv) raw_args = nil # TODO: forward args properly raw_block = raw_node.block super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv) end end class YieldNode < CallBaseNode def initialize(raw_node, lenv) raw_args = raw_node.arguments super(raw_node, nil, :call, nil, raw_args, nil, nil, lenv) end end class OperatorNode < CallBaseNode def initialize(raw_node, recv, lenv) mid = raw_node.binary_operator mid_code_range = TypeProf::CodeRange.from_node(raw_node.binary_operator_loc) last_arg = AST.create_node(raw_node.value, lenv) super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv) end end class IndexReadNode < CallBaseNode def initialize(raw_node, lenv) recv = AST.create_node(raw_node.receiver, lenv) mid = :[] mid_code_range = nil raw_args = raw_node.arguments super(raw_node, recv, mid, mid_code_range, raw_args, nil, nil, lenv) end end class IndexWriteNode < CallBaseNode def initialize(raw_node, rhs, lenv) recv = AST.create_node(raw_node.receiver, lenv) mid = :[]= mid_code_range = nil raw_args = raw_node.arguments @rhs = rhs super(raw_node, recv, mid, mid_code_range, raw_args, rhs, nil, lenv) end attr_reader :rhs end class CallReadNode < CallBaseNode def initialize(raw_node, lenv) recv = AST.create_node(raw_node.receiver, lenv) mid = raw_node.read_name mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv) end end class CallWriteNode < CallBaseNode def initialize(raw_node, rhs, lenv) recv = AST.create_node(raw_node.receiver, lenv) mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) @rhs = rhs super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv) end attr_reader :rhs end end