class TypeProf::Core::EscapeBox::HashSplatBox::MethodDefBox
Attributes
cpath[R]
f_args[R]
mid[R]
node[RW]
ret[R]
singleton[R]
Public Class Methods
new(node, genv, cpath, singleton, mid, f_args, ret_boxes)
click to toggle source
Calls superclass method
TypeProf::Core::Box::new
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 336 def initialize(node, genv, cpath, singleton, mid, f_args, ret_boxes) super(node) @cpath = cpath @singleton = singleton @mid = mid raise unless f_args @f_args = f_args raise unless f_args.is_a?(FormalArguments) @record_block = RecordBlock.new(@node) if @f_args.block record_blk_ty = Source.new(Type::Proc.new(genv, @record_block)) record_blk_ty.add_edge(genv, @f_args.block) end @ret_boxes = ret_boxes @ret = Vertex.new(node) ret_boxes.each do |box| @changes.add_edge(genv, box.ret, @ret) end me = genv.resolve_method(@cpath, @singleton, @mid) me.add_def(self) if me.decls.empty? me.add_run_all_method_call_boxes(genv) else genv.add_run(self) end end
Public Instance Methods
call(changes, genv, a_args, ret)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 556 def call(changes, genv, a_args, ret) if pass_arguments(changes, genv, a_args) changes.add_edge(genv, a_args.block, @f_args.block) if @f_args.block && a_args.block changes.add_edge(genv, @ret, ret) end end
destroy(genv)
click to toggle source
Calls superclass method
TypeProf::Core::Box#destroy
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 369 def destroy(genv) me = genv.resolve_method(@cpath, @singleton, @mid) me.remove_def(self) if me.decls.empty? me.add_run_all_method_call_boxes(genv) else genv.add_run(self) end super(genv) end
pass_arguments(changes, genv, a_args)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 439 def pass_arguments(changes, genv, a_args) if a_args.splat_flags.any? # there is at least one splat actual argument lower = @f_args.req_positionals.size + @f_args.post_positionals.size upper = @f_args.rest_positionals ? nil : lower + @f_args.opt_positionals.size if upper && upper < a_args.positionals.size meth = changes.node.mid_code_range ? :mid_code_range : :code_range err = "#{ a_args.positionals.size } for #{ lower }#{ upper ? lower < upper ? "...#{ upper }" : "" : "+" }" changes.add_diagnostic(meth, "wrong number of arguments (#{ err })") return false end start_rest = [a_args.splat_flags.index(true), @f_args.req_positionals.size + @f_args.opt_positionals.size].min end_rest = [a_args.splat_flags.rindex(true) + 1, a_args.positionals.size - @f_args.post_positionals.size].max rest_vtxs = a_args.get_rest_args(genv, start_rest, end_rest) @f_args.req_positionals.each_with_index do |f_vtx, i| if i < start_rest changes.add_edge(genv, a_args.positionals[i], f_vtx) else rest_vtxs.each do |vtx| changes.add_edge(genv, vtx, f_vtx) end end end @f_args.opt_positionals.each_with_index do |f_vtx, i| i += @f_args.opt_positionals.size if i < start_rest changes.add_edge(genv, a_args.positionals[i], f_vtx) else rest_vtxs.each do |vtx| changes.add_edge(genv, vtx, f_vtx) end end end @f_args.post_positionals.each_with_index do |f_vtx, i| i += a_args.positionals.size - @f_args.post_positionals.size if end_rest <= i changes.add_edge(genv, a_args.positionals[i], f_vtx) else rest_vtxs.each do |vtx| changes.add_edge(genv, vtx, f_vtx) end end end if @f_args.rest_positionals rest_vtxs.each do |vtx| @f_args.rest_positionals.each_type do |ty| if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0] changes.add_edge(genv, vtx, ty.args[0]) end end end end else # there is no splat actual argument lower = @f_args.req_positionals.size + @f_args.post_positionals.size upper = @f_args.rest_positionals ? nil : lower + @f_args.opt_positionals.size if a_args.positionals.size < lower || (upper && upper < a_args.positionals.size) meth = changes.node.mid_code_range ? :mid_code_range : :code_range err = "#{ a_args.positionals.size } for #{ lower }#{ upper ? lower < upper ? "...#{ upper }" : "" : "+" }" changes.add_diagnostic(meth, "wrong number of arguments (#{ err })") return false end @f_args.req_positionals.each_with_index do |f_vtx, i| changes.add_edge(genv, a_args.positionals[i], f_vtx) end @f_args.post_positionals.each_with_index do |f_vtx, i| i -= @f_args.post_positionals.size changes.add_edge(genv, a_args.positionals[i], f_vtx) end start_rest = @f_args.req_positionals.size end_rest = a_args.positionals.size - @f_args.post_positionals.size i = 0 while i < @f_args.opt_positionals.size && start_rest < end_rest f_arg = @f_args.opt_positionals[i] changes.add_edge(genv, a_args.positionals[start_rest], f_arg) i += 1 start_rest += 1 end if start_rest < end_rest if @f_args.rest_positionals (start_rest..end_rest-1).each do |i| @f_args.rest_positionals.each_type do |ty| if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0] changes.add_edge(genv, a_args.positionals[i], ty.args[0]) end end end end end end if a_args.keywords # TODO: support diagnostics @node.req_keywords.zip(@f_args.req_keywords) do |name, f_vtx| changes.add_edge(genv, a_args.get_keyword_arg(genv, changes, name), f_vtx) end @node.opt_keywords.zip(@f_args.opt_keywords).each do |name, f_vtx| changes.add_edge(genv, a_args.get_keyword_arg(genv, changes, name), f_vtx) end if @node.rest_keywords # FIXME: Extract the rest keywords excluding req_keywords and opt_keywords. changes.add_edge(genv, a_args.keywords, @f_args.rest_keywords) end end return true end
run0(genv, changes)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 380 def run0(genv, changes) me = genv.resolve_method(@cpath, @singleton, @mid) return if me.decls.empty? # TODO: support "| ..." decl = me.decls.to_a.first # TODO: support overload? method_type = decl.method_types.first _block = method_type.block mod = genv.resolve_cpath(@cpath) if @singleton ty = Type::Singleton.new(genv, mod) param_map0 = Type.default_param_map(genv, ty) else type_params = mod.type_params.map {|ty_param| Source.new() } # TODO: better support ty = Type::Instance.new(genv, mod, type_params) param_map0 = Type.default_param_map(genv, ty) if ty.is_a?(Type::Instance) ty.mod.type_params.zip(ty.args) do |param, arg| param_map0[param] = arg end end end method_type.type_params.each do |param| param_map0[param] = Source.new() end positional_args = [] splat_flags = [] method_type.req_positionals.each do |a_arg| positional_args << a_arg.contravariant_vertex(genv, changes, param_map0) splat_flags << false end method_type.opt_positionals.each do |a_arg| positional_args << a_arg.contravariant_vertex(genv, changes, param_map0) splat_flags << false end if method_type.rest_positionals elems = method_type.rest_positionals.contravariant_vertex(genv, changes, param_map0) positional_args << Source.new(genv.gen_ary_type(elems)) splat_flags << true end method_type.post_positionals.each do |a_arg| positional_args << a_arg.contravariant_vertex(genv, changes, param_map0) splat_flags << false end a_args = ActualArguments.new(positional_args, splat_flags, nil, nil) # TODO: keywords and block if pass_arguments(changes, genv, a_args) # TODO: block f_ret = method_type.return_type.contravariant_vertex(genv, changes, param_map0) @ret_boxes.each do |ret_box| changes.add_edge(genv, f_ret, ret_box.f_ret) end end end
show(output_parameter_names)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 564 def show(output_parameter_names) block_show = [] if @record_block.used blk_f_args = @record_block.f_args.map {|arg| arg.show }.join(", ") blk_ret = @record_block.ret.show block_show << "{ (#{ blk_f_args }) -> #{ blk_ret } }" end args = [] @f_args.req_positionals.each do |f_vtx| args << Type.strip_parens(f_vtx.show) end @f_args.opt_positionals.each do |f_vtx| args << ("?" + Type.strip_parens(f_vtx.show)) end if @f_args.rest_positionals args << ("*" + Type.strip_array(Type.strip_parens(@f_args.rest_positionals.show))) end @f_args.post_positionals.each do |var| args << Type.strip_parens(var.show) end if @node.is_a?(AST::DefNode) @node.req_keywords.zip(@f_args.req_keywords) do |name, f_vtx| args << "#{ name }: #{Type.strip_parens(f_vtx.show)}" end @node.opt_keywords.zip(@f_args.opt_keywords) do |name, f_vtx| args << "?#{ name }: #{Type.strip_parens(f_vtx.show)}" end end if @f_args.rest_keywords args << "**#{ Type.strip_parens(@f_args.rest_keywords.show) }" end if output_parameter_names && @node.is_a?(AST::DefNode) names = [] names.concat(@node.req_positionals) names.concat(@node.opt_positionals) names.concat(@node.rest_positionals) if @node.rest_positionals names.concat(@node.post_positionals) names.concat(@node.req_keywords) names.concat(@node.opt_keywords) names.concat(@node.rest_keywords) if @node.rest_keywords args = args.zip(names).map do |arg, name| name ? "#{ arg } #{ name }" : arg end end args = args.join(", ") s = args.empty? ? [] : ["(#{ args })"] s << "#{ block_show.sort.join(" | ") }" unless block_show.empty? s << "-> #{ @ret.show }" s.join(" ") end