@@ -160,67 +160,61 @@ defmodule Module.Types.Pattern do
160160 { args_paths , vars_paths , vars_deps } = pattern_info
161161
162162 try do
163- Enum . map_reduce ( args_paths , context , fn { version , paths } , context ->
164- context =
165- Enum . reduce ( paths , context , fn
166- % { var: var , expr: expr , root: { :arg , index } , path: path } , context ->
167- actual = Enum . fetch! ( types , index )
163+ args_paths
164+ |> Enum . reverse ( )
165+ |> Enum . reduce ( { % { } , context } , fn { version , node } , { changed , context } ->
166+ % { var: var , expr: expr , root: root , path: path } = node
167+
168+ { actual , index } =
169+ case root do
170+ { :arg , index } -> { Enum . fetch! ( types , index ) , index }
171+ _ -> { of_pattern_tree ( root , context ) , nil }
172+ end
168173
169- case of_pattern_var ( path , actual , context ) do
170- { :ok , new_type } ->
171- case Of . refine_head_var ( var , new_type , expr , stack , context ) do
172- { :ok , _type , context } ->
173- context
174-
175- { :error , old_type , error_context } ->
176- if match_error? ( var , new_type ) do
177- throw ( badpattern_error ( expr , index , tag , stack , context ) )
178- else
179- throw ( badvar_error ( var , old_type , new_type , stack , error_context ) )
180- end
174+ context =
175+ case of_pattern_var ( path , actual , context ) do
176+ { :ok , new_type } ->
177+ case Of . refine_head_var ( var , new_type , expr , stack , context ) do
178+ { :ok , _type , context } ->
179+ context
180+
181+ { :error , old_type , error_context } ->
182+ if match_error? ( var , new_type ) do
183+ throw ( badpattern_error ( expr , index , tag , stack , context ) )
184+ else
185+ throw ( badvar_error ( var , old_type , new_type , stack , error_context ) )
181186 end
182-
183- :error ->
184- throw ( badpattern_error ( expr , index , tag , stack , context ) )
185187 end
186- end )
187188
188- { version , context }
189+ :error ->
190+ throw ( badpattern_error ( expr , index , tag , stack , context ) )
191+ end
192+
193+ { Map . merge ( changed , Map . get ( vars_deps , version , % { } ) ) , context }
189194 end )
190195 catch
191196 context -> error_vars ( pattern_info , context )
192197 else
193198 { changed , context } ->
194- context =
195- Enum . reduce ( changed , context , fn version , context ->
196- { _ , context } = of_pattern_var_dep ( vars_paths , version , stack , context )
197- context
198- end )
199-
200199 of_pattern_var_deps ( changed , vars_paths , vars_deps , stack , context )
201200 end
202201 end
203202
204- defp of_pattern_var_deps ( [ ] , _vars_paths , _vars_deps , _stack , context ) do
203+ defp of_pattern_var_deps ( changed , _vars_paths , _vars_deps , _stack , context )
204+ when changed == % { } do
205205 context
206206 end
207207
208208 defp of_pattern_var_deps ( previous_changed , vars_paths , vars_deps , stack , context ) do
209209 { changed , context } =
210210 previous_changed
211- |> Enum . reduce ( % { } , fn version , acc ->
212- case vars_deps do
213- % { ^ version => deps } -> Map . merge ( acc , deps )
214- % { } -> acc
215- end
216- end )
217211 |> Map . keys ( )
218- |> Enum . reduce ( { [ ] , context } , fn version , { changed , context } ->
212+ |> Enum . reduce ( { % { } , context } , fn version , { changed , context } ->
219213 { var_changed? , context } = of_pattern_var_dep ( vars_paths , version , stack , context )
220214
221215 case var_changed? do
222216 false -> { changed , context }
223- true -> { [ version | changed ] , context }
217+ true -> { Map . merge ( changed , Map . get ( vars_deps , version , % { } ) ) , context }
224218 end
225219 end )
226220
@@ -269,32 +263,36 @@ defmodule Module.Types.Pattern do
269263 end
270264 end
271265
272- defp error_vars ( { args_paths , vars_paths , _vars_deps } , context ) do
273- callback = fn [ % { var: var } | _paths ] , context ->
266+ defp error_vars ( { args_paths , _vars_paths , _vars_deps } , context ) do
267+ Enum . reduce ( args_paths , context , fn { _version , % { var: var } } , context ->
274268 Of . error_var ( var , context )
275- end
276-
277- context = Enum . reduce ( Map . values ( args_paths ) , context , callback )
278- context = Enum . reduce ( Map . values ( vars_paths ) , context , callback )
279- context
269+ end )
280270 end
281271
282272 defp match_error? ( { :match , _ , __MODULE__ } , _type ) , do: true
283273 defp match_error? ( _var , type ) , do: empty? ( type )
284274
285- defp badmatch_error ( var , expr , stack , context ) do
286- context = Of . error_var ( var , context )
287- error ( __MODULE__ , { :badmatch , expr , context } , error_meta ( expr , stack ) , stack , context )
288- end
289-
290275 defp badvar_error ( var , old_type , new_type , stack , context ) do
291276 error = { :badvar , old_type , new_type , var , context }
292277 error ( __MODULE__ , error , error_meta ( var , stack ) , stack , context )
293278 end
294279
280+ defp badmatch_error ( var , expr , stack , context ) do
281+ context = Of . error_var ( var , context )
282+ error ( __MODULE__ , { :badmatch , expr , context } , error_meta ( expr , stack ) , stack , context )
283+ end
284+
295285 defp badpattern_error ( expr , index , tag , stack , context ) do
296286 meta = error_meta ( expr , stack )
297- error ( __MODULE__ , { :badpattern , meta , expr , index , tag , context } , meta , stack , context )
287+
288+ error =
289+ if index do
290+ { :badpattern , meta , expr , index , tag , context }
291+ else
292+ { :badmatch , expr , context }
293+ end
294+
295+ error ( __MODULE__ , error , meta , stack , context )
298296 end
299297
300298 defp error_meta ( expr , stack ) do
@@ -630,21 +628,19 @@ defmodule Module.Types.Pattern do
630628 pattern_info =
631629 case root do
632630 { :arg , _ } ->
633- paths = [ node | Map . get ( args_paths , version , [ ] ) ]
634- args_paths = Map . put ( args_paths , version , paths )
635- { args_paths , vars_paths , vars_deps }
631+ { [ { version , node } | args_paths ] , vars_paths , vars_deps }
636632
637633 { :var , other } ->
638634 paths = [ node | Map . get ( vars_paths , version , [ ] ) ]
639635 vars_paths = Map . put ( vars_paths , version , paths )
640636 vars_deps = Map . update ( vars_deps , version , % { other => [ ] } , & Map . put ( & 1 , other , [ ] ) )
641637 vars_deps = Map . update ( vars_deps , other , % { version => [ ] } , & Map . put ( & 1 , version , [ ] ) )
642- { args_paths , vars_paths , vars_deps }
638+ { [ { version , node } | args_paths ] , vars_paths , vars_deps }
643639
644640 _ ->
645641 paths = [ node | Map . get ( vars_paths , version , [ ] ) ]
646642 vars_paths = Map . put ( vars_paths , version , paths )
647- { args_paths , vars_paths , vars_deps }
643+ { [ { version , node } | args_paths ] , vars_paths , vars_deps }
648644 end
649645
650646 % { context | pattern_info: pattern_info }
@@ -837,7 +833,7 @@ defmodule Module.Types.Pattern do
837833 # the number of list heads.
838834 # TODO: Consider moving pattern_info into context.vars.
839835 defp init_pattern_info ( context ) do
840- % { context | pattern_info: { % { } , % { } , % { } } }
836+ % { context | pattern_info: { [ ] , % { } , % { } } }
841837 end
842838
843839 defp pop_pattern_info ( % { pattern_info: pattern_info } = context ) do
0 commit comments