Skip to content

Commit 4b086e3

Browse files
committed
Support optional parameters in block arguments
This allows blocks like `do |x, y = :default|`.
1 parent cae2ecd commit 4b086e3

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

lib/typeprof/core/ast/call.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc
1616
@block_pass = nil
1717
@block_tbl = nil
1818
@block_f_args = nil
19+
@block_opt_positional_defaults = nil
1920
@block_body = nil
2021
@safe_navigation = raw_node.respond_to?(:safe_navigation?) && raw_node.safe_navigation?
2122
@anonymous_block_forwarding = false
@@ -55,10 +56,12 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc
5556
else
5657
@block_pass = nil
5758
@block_tbl = raw_block.locals
58-
# TODO: optional args, etc.
5959
@block_f_args = case raw_block.parameters
6060
when Prism::BlockParametersNode
61-
raw_block.parameters.parameters.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name }
61+
params = raw_block.parameters.parameters
62+
req = params.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name }
63+
opt = params.optionals.map {|n| n.name }
64+
req + opt
6265
when Prism::NumberedParametersNode
6366
1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" }
6467
when Prism::ItParametersNode
@@ -70,6 +73,12 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc
7073
end
7174
ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref)
7275
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, @lenv.return_boxes)
76+
@block_opt_positional_defaults = []
77+
if raw_block.parameters.is_a?(Prism::BlockParametersNode)
78+
raw_block.parameters.parameters.optionals.each do |n|
79+
@block_opt_positional_defaults << AST.create_node(n.value, nlenv)
80+
end
81+
end
7382
@block_body = raw_block.body ? AST.create_node(raw_block.body, nlenv) : DummyNilNode.new(code_range, lenv)
7483
end
7584
end
@@ -79,10 +88,10 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc
7988

8089
attr_reader :recv, :mid, :mid_code_range, :yield
8190
attr_reader :positional_args, :splat_flags, :keyword_args
82-
attr_reader :block_tbl, :block_f_args, :block_body, :block_pass, :anonymous_block_forwarding
91+
attr_reader :block_tbl, :block_f_args, :block_opt_positional_defaults, :block_body, :block_pass, :anonymous_block_forwarding
8392
attr_reader :safe_navigation
8493

85-
def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: }
94+
def subnodes = { recv:, positional_args:, keyword_args:, block_opt_positional_defaults:, block_body:, block_pass: }
8695
def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield:, safe_navigation:, anonymous_block_forwarding: }
8796

8897
def install0(genv)
@@ -117,6 +126,13 @@ def install0(genv)
117126
end
118127
end
119128

129+
if @block_opt_positional_defaults && !@block_opt_positional_defaults.empty?
130+
req_count = blk_f_args.size - @block_opt_positional_defaults.size
131+
@block_opt_positional_defaults.each_with_index do |expr, i|
132+
@changes.add_edge(genv, expr.install(genv), blk_f_args[req_count + i])
133+
end
134+
end
135+
120136
@lenv.locals.each do |var, vtx|
121137
block_body.lenv.set_var(var, vtx)
122138
end
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ def check2
2323
## assert
2424
class Object
2525
def test_yield: { (Integer, Integer) -> bot } -> bot
26-
def check1: -> [Integer, Integer]?
26+
def check1: -> [Integer, :y | Integer]?
2727
def check2: -> [Integer, Integer, :z]?
2828
end

0 commit comments

Comments
 (0)