Skip to content

Commit

Permalink
Support rest arguments
Browse files Browse the repository at this point in the history
- Initialized rest arguments in method definitions as array.
- Updated method call to add edges to array types.

Further improvements may be possible.
  • Loading branch information
alpaca-tc authored and mame committed Dec 20, 2024
1 parent dbb3fe5 commit 2e9ef02
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 20 deletions.
4 changes: 4 additions & 0 deletions lib/typeprof/core/ast/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ def install0(genv)
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
Expand Down
15 changes: 11 additions & 4 deletions lib/typeprof/core/graph/box.rb
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,11 @@ def pass_arguments(changes, genv, a_args)

if @f_args.rest_positionals
rest_vtxs.each do |vtx|
changes.add_edge(genv, vtx, @f_args.rest_positionals)
@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
Expand Down Expand Up @@ -519,9 +523,12 @@ def pass_arguments(changes, genv, a_args)

if start_rest < end_rest
if @f_args.rest_positionals
f_arg = @f_args.rest_positionals
(start_rest..end_rest-1).each do |i|
changes.add_edge(genv, a_args.positionals[i], f_arg)
@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
Expand Down Expand Up @@ -569,7 +576,7 @@ def show(output_parameter_names)
args << ("?" + Type.strip_parens(f_vtx.show))
end
if @f_args.rest_positionals
args << ("*" + Type.strip_parens(@f_args.rest_positionals.show))
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)
Expand Down
4 changes: 4 additions & 0 deletions lib/typeprof/core/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def self.strip_parens(s)
s.start_with?("(") && s.end_with?(")") ? s[1..-2] || raise : s
end

def self.strip_array(s)
s.start_with?("Array[") && s.end_with?("]") ? s[6..-2] || raise : s
end

def self.default_param_map(genv, ty)
ty = ty.base_type(genv)
instance_ty = ty.is_a?(Type::Instance) ? ty : Type::Instance.new(genv, ty.mod, []) # TODO: type params
Expand Down
16 changes: 0 additions & 16 deletions scenario/known-issues/splat-arg.rb

This file was deleted.

16 changes: 16 additions & 0 deletions scenario/method/splat-arg.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## update
class Foo
def rest(*args)
args
end

def call_rest_method
rest(1)
end
end

## assert
class Foo
def rest: (*Integer) -> Array[Integer]
def call_rest_method: -> Array[Integer]
end

0 comments on commit 2e9ef02

Please sign in to comment.