@@ -56,9 +56,9 @@ defmodule Module.Types.Pattern do
5656 end
5757
5858 defp of_pattern_args ( patterns , expected , tag , stack , context ) do
59- context = init_match_info ( context )
59+ context = init_pattern_info ( context )
6060 { trees , context } = of_pattern_args_zip ( patterns , expected , 0 , [ ] , stack , context )
61- { pattern_info , context } = pop_match_info ( context )
61+ { pattern_info , context } = pop_pattern_info ( context )
6262
6363 context =
6464 case of_pattern_intersect ( trees , 0 , [ ] , pattern_info , tag , stack , context ) do
@@ -82,9 +82,9 @@ defmodule Module.Types.Pattern do
8282 Handles the match operator.
8383 """
8484 def of_match ( pattern , expected_fun , expr , stack , context ) do
85- context = init_match_info ( context )
85+ context = init_pattern_info ( context )
8686 { tree , context } = of_pattern ( pattern , [ % { root: { :arg , 0 } , expr: expr } ] , stack , context )
87- { pattern_info , context } = pop_match_info ( context )
87+ { pattern_info , context } = pop_pattern_info ( context )
8888 { expected , context } = expected_fun . ( of_pattern_tree ( tree , context ) , context )
8989
9090 args = [ { tree , expected , expr } ]
@@ -100,9 +100,9 @@ defmodule Module.Types.Pattern do
100100 Handles matches in generators.
101101 """
102102 def of_generator ( pattern , guards , expected , tag , expr , stack , context ) do
103- context = init_match_info ( context )
103+ context = init_pattern_info ( context )
104104 { tree , context } = of_pattern ( pattern , [ % { root: { :arg , 0 } , expr: expr } ] , stack , context )
105- { pattern_info , context } = pop_match_info ( context )
105+ { pattern_info , context } = pop_pattern_info ( context )
106106 args = [ { tree , expected , pattern } ]
107107
108108 context =
@@ -128,11 +128,11 @@ defmodule Module.Types.Pattern do
128128 end
129129
130130 defp of_pattern_intersect ( [ ] , _index , acc , pattern_info , tag , stack , context ) do
131- { args_paths , vars_paths , vars_deps } = pattern_info
131+ % { vars: context_vars } = context
132132 types = Enum . reverse ( acc )
133133
134134 try do
135- args_paths
135+ pattern_info
136136 |> Enum . reverse ( )
137137 |> Enum . reduce ( { % { } , context } , fn { version , node } , { changed , context } ->
138138 % { var: var , expr: expr , root: root , path: path } = node
@@ -162,56 +162,54 @@ defmodule Module.Types.Pattern do
162162 throw ( badpattern_error ( expr , index , tag , stack , context ) )
163163 end
164164
165- { Map . merge ( changed , Map . get ( vars_deps , version , % { } ) ) , context }
165+ % { ^ version => % { deps: deps } } = context_vars
166+ { Map . merge ( changed , deps ) , context }
166167 end )
167168 catch
168169 context -> { :error , error_vars ( pattern_info , context ) }
169170 else
170171 { changed , context } ->
171- { :ok , types , of_pattern_recur ( changed , vars_paths , vars_deps , stack , context ) }
172+ { :ok , types , of_pattern_recur ( changed , stack , context ) }
172173 end
173174 end
174175
175- defp of_pattern_recur ( changed , _vars_paths , _vars_deps , _stack , context )
176+ defp of_pattern_recur ( changed , _stack , context )
176177 when changed == % { } do
177178 context
178179 end
179180
180- defp of_pattern_recur ( previous_changed , vars_paths , vars_deps , stack , context ) do
181+ defp of_pattern_recur ( previous_changed , stack , context ) do
181182 { changed , context } =
182183 previous_changed
183184 |> Map . keys ( )
184185 |> Enum . reduce ( { % { } , context } , fn version , { changed , context } ->
185- { var_changed? , context } = of_pattern_recur_var ( vars_paths , version , stack , context )
186-
187- case var_changed? do
188- false -> { changed , context }
189- true -> { Map . merge ( changed , Map . get ( vars_deps , version , % { } ) ) , context }
190- end
186+ { new_deps , context } = of_pattern_recur_var ( version , stack , context )
187+ { Map . merge ( changed , new_deps ) , context }
191188 end )
192189
193- of_pattern_recur ( changed , vars_paths , vars_deps , stack , context )
190+ of_pattern_recur ( changed , stack , context )
194191 end
195192
196- defp of_pattern_recur_var ( vars_paths , version , stack , context ) do
197- paths = Map . get ( vars_paths , version , [ ] )
198-
193+ defp of_pattern_recur_var ( version , stack , context ) do
199194 case context . vars do
200- % { ^ version => % { type: old_type } = data } when not is_map_key ( data , :errored ) ->
195+ % { ^ version => % { type: old_type , deps: deps , paths: paths } = data }
196+ when not is_map_key ( data , :errored ) ->
201197 try do
202- Enum . reduce ( paths , { false , context } , fn
203- % { var: var , expr: expr , root: root , path: path } , { var_changed? , context } ->
198+ Enum . reduce ( paths , { % { } , context } , fn
199+ % { var: var , expr: expr , root: root , path: path } , { new_deps , context } ->
204200 actual = of_pattern_tree ( root , context )
205201
206202 case of_pattern_var ( path , actual , context ) do
207203 { :ok , new_type } ->
208- # Optimization: if current type is already a subtype, there is nothing to refine.
204+ # Optimization: if current type is already a subtype,
205+ # there is nothing to refine
209206 if old_type != term ( ) and subtype? ( old_type , new_type ) do
210- { var_changed? , context }
207+ { new_deps , context }
211208 else
212209 case Of . refine_head_var ( var , new_type , expr , stack , context ) do
213210 { :ok , _type , context } ->
214- { true , context }
211+ # Return the actual deps to be recomputed
212+ { deps , context }
215213
216214 { :error , _old_type , error_context } ->
217215 if match_error? ( var , new_type ) do
@@ -227,16 +225,16 @@ defmodule Module.Types.Pattern do
227225 end
228226 end )
229227 catch
230- context -> { false , context }
228+ context -> { % { } , context }
231229 end
232230
233231 _ ->
234- { false , context }
232+ { % { } , context }
235233 end
236234 end
237235
238- defp error_vars ( { args_paths , _vars_paths , _vars_deps } , context ) do
239- Enum . reduce ( args_paths , context , fn { _version , % { var: var } } , context ->
236+ defp error_vars ( pattern_info , context ) do
237+ Enum . reduce ( pattern_info , context , fn { _version , % { var: var } } , context ->
240238 Of . error_var ( var , context )
241239 end )
242240 end
@@ -275,16 +273,12 @@ defmodule Module.Types.Pattern do
275273 end
276274 end
277275
278- # pattern_info stores the variables defined in patterns,
279- # additional information about the number of variables in
280- # arguments and list heads, and a counter used to compute
281- # the number of list heads.
282- # TODO: Move vars_deps and vars_paths into context.vars.
283- defp init_match_info ( context ) do
284- % { context | pattern_info: { [ ] , % { } , % { } } }
276+ # pattern_info stores the paths defined from patterns.
277+ defp init_pattern_info ( context ) do
278+ % { context | pattern_info: [ ] }
285279 end
286280
287- defp pop_match_info ( % { pattern_info: pattern_info } = context ) do
281+ defp pop_pattern_info ( % { pattern_info: pattern_info } = context ) do
288282 { pattern_info , % { context | pattern_info: nil } }
289283 end
290284
@@ -623,30 +617,22 @@ defmodule Module.Types.Pattern do
623617 defp is_versioned_var ( _ ) , do: false
624618
625619 defp of_var ( var , version , reverse_path , context ) do
626- context = Of . declare_var ( var , context )
627- { args_paths , vars_paths , vars_deps } = context . pattern_info
628620 [ % { root: root , expr: expr } | path ] = Enum . reverse ( reverse_path )
629621 node = % { root: root , var: var , expr: expr , path: path }
622+ context = Of . declare_var ( var , context )
623+ context = % { context | pattern_info: [ { version , node } | context . pattern_info ] }
630624
631- pattern_info =
632- case root do
633- { :arg , _ } ->
634- { [ { version , node } | args_paths ] , vars_paths , vars_deps }
635-
636- { :var , other } ->
637- paths = [ node | Map . get ( vars_paths , version , [ ] ) ]
638- vars_paths = Map . put ( vars_paths , version , paths )
639- vars_deps = Map . update ( vars_deps , version , % { other => [ ] } , & Map . put ( & 1 , other , [ ] ) )
640- vars_deps = Map . update ( vars_deps , other , % { version => [ ] } , & Map . put ( & 1 , version , [ ] ) )
641- { [ { version , node } | args_paths ] , vars_paths , vars_deps }
642-
643- _ ->
644- paths = [ node | Map . get ( vars_paths , version , [ ] ) ]
645- vars_paths = Map . put ( vars_paths , version , paths )
646- { [ { version , node } | args_paths ] , vars_paths , vars_deps }
647- end
625+ case root do
626+ { :arg , _ } ->
627+ context
628+
629+ { :var , other } ->
630+ context = Of . track_var ( version , [ other ] , [ node ] , context )
631+ Of . track_var ( other , [ version ] , [ ] , context )
648632
649- % { context | pattern_info: pattern_info }
633+ _ ->
634+ Of . track_var ( version , [ ] , [ node ] , context )
635+ end
650636 end
651637
652638 defp of_open_map ( args , static , dynamic , path , stack , context ) do
0 commit comments