@@ -114,26 +114,37 @@ defmodule Module.Types.Pattern do
114114    { type ,  context } 
115115  end 
116116
117+   defp  all_single_path? ( vars ,  info ,  index )  do 
118+     info 
119+     |>  Map . get ( index ,  [ ] ) 
120+     |>  Enum . all? ( fn  version  ->  match? ( [ _ ] ,  Map . fetch! ( vars ,  version ) )  end ) 
121+   end 
122+ 
117123  defp  of_pattern_recur ( types ,  tag ,  stack ,  context ,  callback )  do 
118-     % { pattern_info:  { pattern_vars ,   pattern_info ,  _counter } }  =  context 
124+     % { pattern_info:  { vars ,   info ,  _counter } }  =  context 
119125    context  =  nilify_pattern_info ( context ) 
120-     pattern_vars  =  Map . to_list ( pattern_vars ) 
121126    changed  =  :lists . seq ( 0 ,  length ( types )  -  1 ) 
122127
128+     # If all variables in a given index have a single path, 
129+     # then there are no changes to propagate 
130+     unchangeable  =  for  index  <-  changed ,  all_single_path? ( vars ,  info ,  index ) ,  do:  index 
131+ 
132+     vars  =  Map . to_list ( vars ) 
133+ 
123134    try  do 
124135      case  callback . ( types ,  changed ,  context )  do 
125136        { :ok ,  types ,  context }  -> 
126-           of_pattern_recur ( types ,  pattern_vars ,   pattern_info ,  tag ,  stack ,  context ,  callback ) 
137+           of_pattern_recur ( types ,  unchangeable ,   vars ,   info ,  tag ,  stack ,  context ,  callback ) 
127138
128139        { :error ,  context }  -> 
129-           { types ,  error_vars ( pattern_vars ,  context ) } 
140+           { types ,  error_vars ( vars ,  context ) } 
130141      end 
131142    catch 
132-       { types ,  context }  ->  { types ,  error_vars ( pattern_vars ,  context ) } 
143+       { types ,  context }  ->  { types ,  error_vars ( vars ,  context ) } 
133144    end 
134145  end 
135146
136-   defp  of_pattern_recur ( types ,  vars ,  info ,  tag ,  stack ,  context ,  callback )  do 
147+   defp  of_pattern_recur ( types ,  unchangeable ,   vars ,  info ,  tag ,  stack ,  context ,  callback )  do 
137148    { changed ,  context }  = 
138149      Enum . reduce ( vars ,  { [ ] ,  context } ,  fn  { version ,  paths } ,  { changed ,  context }  -> 
139150        { var_changed? ,  context }  = 
@@ -165,23 +176,12 @@ defmodule Module.Types.Pattern do
165176            { changed ,  context } 
166177
167178          true  -> 
168-             case  paths  do 
169-               # A single change, check if there are other variables in this index. 
170-               [ [ _var ,  { :arg ,  index ,  _ }  |  _ ] ]  -> 
171-                 case  info  do 
172-                   % { ^ index  =>  true }  ->  { [ index  |  changed ] ,  context } 
173-                   % { ^ index  =>  false }  ->  { changed ,  context } 
174-                 end 
175- 
176-               # Several changes, we have to recompute all indexes. 
177-               _  -> 
178-                 var_changed  =  Enum . map ( paths ,  fn  [ _var ,  { :arg ,  index ,  _ }  |  _ ]  ->  index  end ) 
179-                 { var_changed  ++  changed ,  context } 
180-             end 
179+             var_changed  =  Enum . map ( paths ,  fn  [ _var ,  { :arg ,  index ,  _ }  |  _ ]  ->  index  end ) 
180+             { var_changed  ++  changed ,  context } 
181181        end 
182182      end ) 
183183
184-     case  :lists . usort ( changed )  do 
184+     case  :lists . usort ( changed )  --   unchangeable   do 
185185      [ ]  -> 
186186        { types ,  context } 
187187
@@ -192,7 +192,7 @@ defmodule Module.Types.Pattern do
192192            { types ,  context } 
193193
194194          { :ok ,  types ,  context }  -> 
195-             of_pattern_recur ( types ,  vars ,  info ,  tag ,  stack ,  context ,  callback ) 
195+             of_pattern_recur ( types ,  unchangeable ,   vars ,  info ,  tag ,  stack ,  context ,  callback ) 
196196
197197          { :error ,  context }  -> 
198198            { types ,  error_vars ( vars ,  context ) } 
@@ -487,14 +487,8 @@ defmodule Module.Types.Pattern do
487487    paths  =  [ [ var  |  path ]  |  Map . get ( vars ,  version ,  [ ] ) ] 
488488    vars  =  Map . put ( vars ,  version ,  paths ) 
489489
490-     # Our goal here is to compute if an argument has more than one variable. 
491-     info  = 
492-       case  info  do 
493-         % { ^ arg  =>  false }  ->  % { info  |  arg  =>  true } 
494-         % { ^ arg  =>  true }  ->  info 
495-         % { }  ->  Map . put ( info ,  arg ,  false ) 
496-       end 
497- 
490+     # Stores all variables used at any given argument 
491+     info  =  Map . update ( info ,  arg ,  [ version ] ,  & [ version  |  & 1 ] ) 
498492    { { :var ,  version } ,  % { context  |  pattern_info:  { vars ,  info ,  counter } } } 
499493  end 
500494
0 commit comments