Skip to content

Commit e42063a

Browse files
committed
Support destructuring parameters in method definitions
This allows `def foo(x, (y, z))`.
1 parent c9c1f4c commit e42063a

3 files changed

Lines changed: 46 additions & 11 deletions

File tree

lib/typeprof/core/ast/method.rb

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ def self.parse_params(tbl, raw_args, lenv)
3030
unless raw_args
3131
return {
3232
req_positionals: [],
33+
req_multi_targets: {},
3334
opt_positionals: [],
3435
opt_positional_defaults: [],
3536
rest_positionals: nil,
3637
post_positionals: [],
38+
post_multi_targets: {},
3739
req_keywords: [],
3840
opt_keywords: [],
3941
opt_keyword_defaults: [],
@@ -45,9 +47,15 @@ def self.parse_params(tbl, raw_args, lenv)
4547

4648
args_code_ranges = []
4749
req_positionals = []
48-
raw_args.requireds.each do |n|
50+
req_multi_targets = {}
51+
raw_args.requireds.each_with_index do |n, i|
4952
args_code_ranges << lenv.code_range_from_node(n.location)
50-
req_positionals << (n.is_a?(Prism::MultiTargetNode) ? nil : n.name)
53+
if n.is_a?(Prism::MultiTargetNode)
54+
req_positionals << nil
55+
req_multi_targets[i] = n
56+
else
57+
req_positionals << n.name
58+
end
5159
end
5260

5361
# pre_init = args[1]
@@ -59,7 +67,15 @@ def self.parse_params(tbl, raw_args, lenv)
5967
opt_positional_defaults << AST.create_node(n.value, lenv)
6068
end
6169

62-
post_positionals = raw_args.posts.map {|n| (n.is_a?(Prism::MultiTargetNode) ? nil : n.name) }
70+
post_multi_targets = {}
71+
post_positionals = raw_args.posts.each_with_index.map do |n, i|
72+
if n.is_a?(Prism::MultiTargetNode)
73+
post_multi_targets[i] = n
74+
nil
75+
else
76+
n.name
77+
end
78+
end
6379

6480
rest_positionals = raw_args.rest ? (raw_args.rest.name || :"*anonymous_rest") : nil
6581

@@ -97,10 +113,12 @@ def self.parse_params(tbl, raw_args, lenv)
97113

98114
{
99115
req_positionals:,
116+
req_multi_targets:,
100117
opt_positionals:,
101118
opt_positional_defaults:,
102119
rest_positionals:,
103120
post_positionals:,
121+
post_multi_targets:,
104122
req_keywords:,
105123
opt_keywords:,
106124
opt_keyword_defaults:,
@@ -140,10 +158,12 @@ def initialize(raw_node, lenv, use_result)
140158

141159
h = AST.parse_params(@tbl, raw_args, nlenv)
142160
@req_positionals = h[:req_positionals]
161+
@req_multi_targets = h[:req_multi_targets]
143162
@opt_positionals = h[:opt_positionals]
144163
@opt_positional_defaults = h[:opt_positional_defaults]
145164
@rest_positionals = h[:rest_positionals]
146165
@post_positionals = h[:post_positionals]
166+
@post_multi_targets = h[:post_multi_targets]
147167
@req_keywords = h[:req_keywords]
148168
@opt_keywords = h[:opt_keywords]
149169
@opt_keyword_defaults = h[:opt_keyword_defaults]
@@ -221,6 +241,8 @@ def install0(genv)
221241
opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
222242
rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
223243
post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
244+
install_multi_targets(genv, @req_multi_targets, req_positionals)
245+
install_multi_targets(genv, @post_multi_targets, post_positionals)
224246
req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
225247
opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
226248
rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
@@ -271,6 +293,16 @@ def install0(genv)
271293
Source.new(Type::Symbol.new(genv, @mid))
272294
end
273295

296+
def install_multi_targets(genv, multi_targets, positionals)
297+
multi_targets.each do |idx, raw_multi_target|
298+
param_vtx = positionals[idx]
299+
lefts = raw_multi_target.lefts.map do |n|
300+
@body.lenv.new_var(n.is_a?(Prism::MultiTargetNode) ? nil : n.name, self)
301+
end
302+
@changes.add_masgn_box(genv, param_vtx, lefts, nil, nil)
303+
end
304+
end
305+
274306
def last_stmt_code_range
275307
if @body
276308
if @body.is_a?(AST::StatementsNode)

scenario/args/multi_target_arg.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## update
2+
def check(z, (x, y))
3+
[z, y, x]
4+
end
5+
6+
check(1, [1, "str"])
7+
8+
## assert
9+
class Object
10+
def check: (Integer, [Integer, String]) -> [Integer, String, Integer]
11+
end

scenario/known-issues/multi_target_arg.rb

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)