Skip to content

[RegexDiff X64] [stephentoub] Support auto-atomicity on {lazy} loops #1268

Description

@MihuBot

Job completed in 18 minutes 36 seconds (remote runner delay: 1 minute 6 seconds).
dotnet/runtime#117943
Using arguments: regexdiff

1464 out of 18857 patterns have generated source code changes.

Examples of GeneratedRegex source diffs
"^\\s*(((?<ORIGIN>(((\\d+>)?[a-zA-Z]?:[^:]*)| ..." (7826 uses)
[GeneratedRegex("^\\s*(((?<ORIGIN>(((\\d+>)?[a-zA-Z]?:[^:]*)|([^:]*))):)|())(?<SUBCATEGORY>(()|([^:]*? )))(?<CATEGORY>(error|warning))( \\s*(?<CODE>[^: ]*))?\\s*:(?<TEXT>.*)$", RegexOptions.IgnoreCase)]
  int loop_iteration = 0;
  int loop_iteration1 = 0;
  int stackpos = 0;
+   int startingStackpos = 0;
  ReadOnlySpan<char> slice = inputSpan.Slice(pos);
  
  // Match if at the beginning of the string.
                              // Branch 0
                              //{
                                  // 4th capture group.
-                                   //{
+                                   {
                                      capture_starting_pos4 = pos;
                                      
                                      // Optional (greedy).
-                                       //{
+                                       {
+                                           startingStackpos = stackpos;
                                          loop_iteration = 0;
                                          
                                          LoopBody:
                                          pos = base.runstack![--stackpos];
                                          UncaptureUntil(base.runstack![--stackpos]);
                                          slice = inputSpan.Slice(pos);
-                                           LoopEnd:;
-                                       //}
+                                           LoopEnd:
+                                           stackpos = startingStackpos; // Ensure any remaining backtracking state is removed.
+                                       }
                                      
                                      // Match a character in the set [A-Za-z\u212A] atomically, optionally.
                                      {
                                      // Match ':'.
                                      if (slice.IsEmpty || slice[0] != ':')
                                      {
-                                           goto LoopIterationNoMatch;
+                                           goto AlternationBranch1;
                                      }
                                      
                                      // Match a character other than ':' atomically any number of times.
                                      pos++;
                                      slice = inputSpan.Slice(pos);
                                      base.Capture(4, capture_starting_pos4, pos);
-                                       
-                                       goto CaptureSkipBacktrack;
-                                       
-                                       CaptureBacktrack:
-                                       goto LoopIterationNoMatch;
-                                       
-                                       CaptureSkipBacktrack:;
-                                   //}
+                                   }
                                  
                                  alternation_branch1 = 0;
                                  goto AlternationMatch1;
                              switch (alternation_branch1)
                              {
                                  case 0:
-                                       goto CaptureBacktrack;
+                                       goto AlternationBranch1;
                                  case 1:
                                      goto AlternationBranch;
                              }
                          
                          base.Capture(3, capture_starting_pos3, pos);
                          
-                           goto CaptureSkipBacktrack1;
+                           goto CaptureSkipBacktrack;
                          
-                           CaptureBacktrack1:
+                           CaptureBacktrack:
                          goto AlternationBacktrack1;
                          
-                           CaptureSkipBacktrack1:;
+                           CaptureSkipBacktrack:;
                      //}
                      
                      base.Capture(13, capture_starting_pos2, pos);
                      
-                       goto CaptureSkipBacktrack2;
+                       goto CaptureSkipBacktrack1;
                      
-                       CaptureBacktrack2:
-                       goto CaptureBacktrack1;
+                       CaptureBacktrack1:
+                       goto CaptureBacktrack;
                      
-                       CaptureSkipBacktrack2:;
+                       CaptureSkipBacktrack1:;
                  //}
                  
                  // Match ':'.
                  if (slice.IsEmpty || slice[0] != ':')
                  {
-                       goto CaptureBacktrack2;
+                       goto CaptureBacktrack1;
                  }
                  
                  pos++;
                  slice = inputSpan.Slice(pos);
                  base.Capture(2, capture_starting_pos1, pos);
                  
-                   goto CaptureSkipBacktrack3;
+                   goto CaptureSkipBacktrack2;
                  
-                   CaptureBacktrack3:
-                   goto CaptureBacktrack2;
+                   CaptureBacktrack2:
+                   goto CaptureBacktrack1;
                  
-                   CaptureSkipBacktrack3:;
+                   CaptureSkipBacktrack2:;
              //}
              
              alternation_branch = 0;
          switch (alternation_branch)
          {
              case 0:
-                   goto CaptureBacktrack3;
+                   goto CaptureBacktrack2;
              case 1:
                  goto CharLoopBacktrack;
          }
      
      base.Capture(1, capture_starting_pos, pos);
      
-       goto CaptureSkipBacktrack4;
+       goto CaptureSkipBacktrack3;
      
-       CaptureBacktrack4:
+       CaptureBacktrack3:
      goto AlternationBacktrack;
      
-       CaptureSkipBacktrack4:;
+       CaptureSkipBacktrack3:;
  //}
  
  // "SUBCATEGORY" capture group.
                          slice = inputSpan.Slice(pos);
                          if (slice.IsEmpty || slice[0] == ':')
                          {
-                               goto CaptureBacktrack4;
+                               goto CaptureBacktrack3;
                          }
                          pos++;
                          slice = inputSpan.Slice(pos);
                          lazyloop_pos = slice.IndexOfAny(':', ' ');
                          if ((uint)lazyloop_pos >= (uint)slice.Length || slice[lazyloop_pos] == ':')
                          {
-                               goto CaptureBacktrack4;
+                               goto CaptureBacktrack3;
                          }
                          pos += lazyloop_pos;
                          slice = inputSpan.Slice(pos);
                      slice = inputSpan.Slice(pos);
                      base.Capture(10, capture_starting_pos11, pos);
                      
-                       goto CaptureSkipBacktrack5;
+                       goto CaptureSkipBacktrack4;
                      
-                       CaptureBacktrack5:
+                       CaptureBacktrack4:
                      goto LazyLoopBacktrack;
                      
-                       CaptureSkipBacktrack5:;
+                       CaptureSkipBacktrack4:;
                  //}
                  
                  alternation_branch2 = 1;
                  case 0:
                      goto AlternationBranch2;
                  case 1:
-                       goto CaptureBacktrack5;
+                       goto CaptureBacktrack4;
              }
              
              AlternationMatch2:;
          
          base.Capture(8, capture_starting_pos9, pos);
          
-           goto CaptureSkipBacktrack6;
+           goto CaptureSkipBacktrack5;
          
-           CaptureBacktrack6:
+           CaptureBacktrack5:
          goto AlternationBacktrack2;
          
-           CaptureSkipBacktrack6:;
+           CaptureSkipBacktrack5:;
      //}
      
      base.Capture(14, capture_starting_pos8, pos);
      
-       goto CaptureSkipBacktrack7;
+       goto CaptureSkipBacktrack6;
      
-       CaptureBacktrack7:
-       goto CaptureBacktrack6;
+       CaptureBacktrack6:
+       goto CaptureBacktrack5;
      
-       CaptureSkipBacktrack7:;
+       CaptureSkipBacktrack6:;
  //}
  
  // "CATEGORY" capture group.
          //{
              if (slice.IsEmpty)
              {
-                   goto CaptureBacktrack7;
+                   goto CaptureBacktrack6;
              }
              
              switch (slice[0])
                      if ((uint)slice.Length < 5 ||
                          !slice.Slice(1).StartsWith("rror", StringComparison.OrdinalIgnoreCase)) // Match the string "rror" (ordinal case-insensitive)
                      {
-                           goto CaptureBacktrack7;
+                           goto CaptureBacktrack6;
                      }
                      
                      pos += 5;
                      if ((uint)slice.Length < 7 ||
                          !slice.Slice(1).StartsWith("arning", StringComparison.OrdinalIgnoreCase)) // Match the string "arning" (ordinal case-insensitive)
                      {
-                           goto CaptureBacktrack7;
+                           goto CaptureBacktrack6;
                      }
                      
                      pos += 7;
                      break;
                      
                  default:
-                       goto CaptureBacktrack7;
+                       goto CaptureBacktrack6;
              }
          //}
          
              base.Capture(16, capture_starting_pos15, pos);
              
              Utilities.StackPush(ref base.runstack!, ref stackpos, capture_starting_pos15);
-               goto CaptureSkipBacktrack8;
+               goto CaptureSkipBacktrack7;
              
-               CaptureBacktrack8:
+               CaptureBacktrack7:
              capture_starting_pos15 = base.runstack![--stackpos];
              goto CharLoopBacktrack2;
              
-               CaptureSkipBacktrack8:;
+               CaptureSkipBacktrack7:;
          //}
          
          base.Capture(12, capture_starting_pos14, pos);
          
          Utilities.StackPush(ref base.runstack!, ref stackpos, capture_starting_pos14);
-           goto CaptureSkipBacktrack9;
+           goto CaptureSkipBacktrack8;
          
-           CaptureBacktrack9:
+           CaptureBacktrack8:
          capture_starting_pos14 = base.runstack![--stackpos];
-           goto CaptureBacktrack8;
+           goto CaptureBacktrack7;
          
-           CaptureSkipBacktrack9:;
+           CaptureSkipBacktrack8:;
      //}
      
      
      if (--loop_iteration1 < 0)
      {
          // Unable to match the remainder of the expression after exhausting the loop.
-           goto CaptureBacktrack7;
+           goto CaptureBacktrack6;
      }
      pos = base.runstack![--stackpos];
      UncaptureUntil(base.runstack![--stackpos]);
      if (loop_iteration1 == 0)
      {
          // No iterations of the loop remain to backtrack into. Fail the loop.
-           goto CaptureBacktrack7;
+           goto CaptureBacktrack6;
      }
-       goto CaptureBacktrack9;
+       goto CaptureBacktrack8;
      LoopEnd1:;
  //}
  
      
      base.Capture(17, capture_starting_pos16, pos);
      
-       goto CaptureSkipBacktrack10;
+       goto CaptureSkipBacktrack9;
      
-       CaptureBacktrack10:
+       CaptureBacktrack9:
      goto CharLoopBacktrack3;
      
-       CaptureSkipBacktrack10:;
+       CaptureSkipBacktrack9:;
  //}
  
  // Match if at the end of the string or if before an ending newline.
  if (pos < inputSpan.Length - 1 || ((uint)pos < (uint)inputSpan.Length && inputSpan[pos] != '\n'))
  {
-       goto CaptureBacktrack10;
+       goto CaptureBacktrack9;
  }
  
  // The input matched.
"\\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z ..." (5703 uses)
[GeneratedRegex("\\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\\Z", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant)]
  int loop_iteration2 = 0;
  int loop_iteration3 = 0;
  int stackpos = 0;
+   int startingStackpos = 0;
+   int startingStackpos1 = 0;
  ReadOnlySpan<char> slice = inputSpan.Slice(pos);
  
  // Match if at the beginning of the string.
          goto LoopIterationNoMatch1;
      }
      
-       // Optional (greedy).
-       //{
-           pos++;
-           slice = inputSpan.Slice(pos);
-           loop_iteration2 = 0;
+       // Atomic group.
+       {
+           int atomic_stackpos = stackpos;
          
-           LoopBody2:
-           Utilities.StackPush(ref base.runstack!, ref stackpos, pos);
-           
-           loop_iteration2++;
-           
-           // Match a character in the set [\-0-9A-Za-z\u212A] greedily any number of times.
+           // Optional (greedy).
          //{
-               charloop_starting_pos1 = pos;
+               pos++;
+               slice = inputSpan.Slice(pos);
+               startingStackpos = stackpos;
+               loop_iteration2 = 0;
              
-               int iteration2 = slice.IndexOfAnyExcept(Utilities.s_asciiLettersAndDigitsAndDashKelvinSign);
-               if (iteration2 < 0)
+               LoopBody2:
+               Utilities.StackPush(ref base.runstack!, ref stackpos, pos);
+               
+               loop_iteration2++;
+               
+               // Match a character in the set [\-0-9A-Za-z\u212A] greedily any number of times.
+               //{
+                   charloop_starting_pos1 = pos;
+                   
+                   int iteration2 = slice.IndexOfAnyExcept(Utilities.s_asciiLettersAndDigitsAndDashKelvinSign);
+                   if (iteration2 < 0)
+                   {
+                       iteration2 = slice.Length;
+                   }
+                   
+                   slice = slice.Slice(iteration2);
+                   pos += iteration2;
+                   
+                   charloop_ending_pos1 = pos;
+                   goto CharLoopEnd1;
+                   
+                   CharLoopBacktrack1:
+                   Utilities.StackPop(base.runstack!, ref stackpos, out charloop_ending_pos1, out charloop_starting_pos1);
+                   
+                   if (Utilities.s_hasTimeout)
+                   {
+                       base.CheckTimeout();
+                   }
+                   
+                   if (charloop_starting_pos1 >= charloop_ending_pos1 ||
+                       (charloop_ending_pos1 = inputSpan.Slice(charloop_starting_pos1, charloop_ending_pos1 - charloop_starting_pos1).LastIndexOfAny(Utilities.s_asciiLettersAndDigitsAndKelvinSign)) < 0)
+                   {
+                       goto LoopIterationNoMatch2;
+                   }
+                   charloop_ending_pos1 += charloop_starting_pos1;
+                   pos = charloop_ending_pos1;
+                   slice = inputSpan.Slice(pos);
+                   
+                   CharLoopEnd1:
+                   Utilities.StackPush(ref base.runstack!, ref stackpos, charloop_starting_pos1, charloop_ending_pos1);
+               //}
+               
+               // Match a character in the set [0-9A-Za-z\u212A].
+               if (slice.IsEmpty || ((ch = slice[0]) < 128 ? !char.IsAsciiLetterOrDigit(ch) : !RegexRunner.CharInClass((char)ch, "\0\b\00:A[a{KÅ")))
              {
-                   iteration2 = slice.Length;
+                   goto CharLoopBacktrack1;
              }
              
-               slice = slice.Slice(iteration2);
-               pos += iteration2;
-               
-               charloop_ending_pos1 = pos;
-               goto CharLoopEnd1;
-               
-               CharLoopBacktrack1:
-               Utilities.StackPop(base.runstack!, ref stackpos, out charloop_ending_pos1, out charloop_starting_pos1);
-               
-               if (Utilities.s_hasTimeout)
-               {
-                   base.CheckTimeout();
-               }
-               
-               if (charloop_starting_pos1 >= charloop_ending_pos1 ||
-                   (charloop_ending_pos1 = inputSpan.Slice(charloop_starting_pos1, charloop_ending_pos1 - charloop_starting_pos1).LastIndexOfAny(Utilities.s_asciiLettersAndDigitsAndKelvinSign)) < 0)
-               {
-                   goto LoopIterationNoMatch2;
-               }
-               charloop_ending_pos1 += charloop_starting_pos1;
-               pos = charloop_ending_pos1;
+               pos++;
              slice = inputSpan.Slice(pos);
              
-               CharLoopEnd1:
-               Utilities.StackPush(ref base.runstack!, ref stackpos, charloop_starting_pos1, charloop_ending_pos1);
+               // The loop has an upper bound of 1. Continue iterating greedily if it hasn't yet been reached.
+               if (loop_iteration2 == 0)
+               {
+                   goto LoopBody2;
+               }
+               goto LoopEnd2;
+               
+               // The loop iteration failed. Put state back to the way it was before the iteration.
+               LoopIterationNoMatch2:
+               if (--loop_iteration2 < 0)
+               {
+                   // Unable to match the remainder of the expression after exhausting the loop.
+                   goto LoopIterationNoMatch1;
+               }
+               pos = base.runstack![--stackpos];
+               slice = inputSpan.Slice(pos);
+               LoopEnd2:
+               stackpos = startingStackpos; // Ensure any remaining backtracking state is removed.
          //}
          
-           // Match a character in the set [0-9A-Za-z\u212A].
-           if (slice.IsEmpty || ((ch = slice[0]) < 128 ? !char.IsAsciiLetterOrDigit(ch) : !RegexRunner.CharInClass((char)ch, "\0\b\00:A[a{KÅ")))
-           {
-               goto CharLoopBacktrack1;
-           }
-           
-           pos++;
-           slice = inputSpan.Slice(pos);
-           
-           // The loop has an upper bound of 1. Continue iterating greedily if it hasn't yet been reached.
-           if (loop_iteration2 == 0)
-           {
-               goto LoopBody2;
-           }
-           goto LoopEnd2;
-           
-           // The loop iteration failed. Put state back to the way it was before the iteration.
-           LoopIterationNoMatch2:
-           if (--loop_iteration2 < 0)
-           {
-               // Unable to match the remainder of the expression after exhausting the loop.
-               goto LoopIterationNoMatch1;
-           }
-           pos = base.runstack![--stackpos];
-           slice = inputSpan.Slice(pos);
-           goto LoopEnd2;
-           
-           LoopBacktrack:
-           if (Utilities.s_hasTimeout)
-           {
-               base.CheckTimeout();
-           }
-           
-           if (loop_iteration2 == 0)
-           {
-               // No iterations of the loop remain to backtrack into. Fail the loop.
-               goto LoopIterationNoMatch1;
-           }
-           goto CharLoopBacktrack1;
-           LoopEnd2:
-           
-           Utilities.StackPush(ref base.runstack!, ref stackpos, loop_iteration2);
-           goto LoopSkipBacktrack;
-           
-           LoopBacktrack1:
-           loop_iteration2 = base.runstack![--stackpos];
-           if (Utilities.s_hasTimeout)
-           {
-               base.CheckTimeout();
-           }
-           
-           goto LoopBacktrack;
-           
-           LoopSkipBacktrack:;
-       //}
+           stackpos = atomic_stackpos;
+       }
      
      // Match '.'.
      if (slice.IsEmpty || slice[0] != '.')
      {
-           goto LoopBacktrack1;
+           goto LoopIterationNoMatch1;
      }
      
      pos++;
      slice = inputSpan.Slice(pos);
      if (loop_iteration1 == 0)
      {
-           // No iterations have been matched to backtrack into. Fail the loop.
+           // All possible iterations have matched, but it's below the required minimum of 1. Fail the loop.
          goto LoopIterationNoMatch;
      }
      
-       goto LoopEnd1;
-       
-       LoopBacktrack2:
-       if (Utilities.s_hasTimeout)
-       {
-           base.CheckTimeout();
-       }
-       
-       if (loop_iteration1 == 0)
-       {
-           // No iterations of the loop remain to backtrack into. Fail the loop.
-           goto LoopIterationNoMatch;
-       }
-       goto LoopBacktrack1;
      LoopEnd1:;
  //}
  
  // Match a character in the set [0-9A-Za-z\u212A].
  if (slice.IsEmpty || ((ch = slice[0]) < 128 ? !char.IsAsciiLetterOrDigit(ch) : !RegexRunner.CharInClass((char)ch, "\0\b\00:A[a{KÅ")))
  {
-       goto LoopBacktrack2;
+       goto LoopIterationNoMatch1;
  }
  
-   // Optional (greedy).
-   //{
-       pos++;
-       slice = inputSpan.Slice(pos);
-       loop_iteration3 = 0;
+   // Atomic group.
+   {
+       int atomic_stackpos1 = stackpos;
      
-       LoopBody3:
-       Utilities.StackPush(ref base.runstack!, ref stackpos, pos);
-       
-       loop_iteration3++;
-       
-       // Match a character in the set [\-0-9A-Za-z\u212A] greedily any number of times.
+       // Optional (greedy).
      //{
-           charloop_starting_pos2 = pos;
+           pos++;
+           slice = inputSpan.Slice(pos);
+           startingStackpos1 = stackpos;
+           loop_iteration3 = 0;
          
-           int iteration3 = slice.IndexOfAnyExcept(Utilities.s_asciiLettersAndDigitsAndDashKelvinSign);
-           if (iteration3 < 0)
+           LoopBody3:
+           Utilities.StackPush(ref base.runstack!, ref stackpos, pos);
+           
+           loop_iteration3++;
+           
+           // Match a character in the set [\-0-9A-Za-z\u212A] greedily any number of times.
+           //{
+               charloop_starting_pos2 = pos;
+               
+               int iteration3 = slice.IndexOfAnyExcept(Utilities.s_asciiLettersAndDigitsAndDashKelvinSign);
+               if (iteration3 < 0)
+               {
+                   iteration3 = slice.Length;
+               }
+               
+               slice = slice.Slice(iteration3);
+               pos += iteration3;
+               
+               charloop_ending_pos2 = pos;
+               goto CharLoopEnd2;
+               
+               CharLoopBacktrack2:
+               Utilities.StackPop(base.runstack!, ref stackpos, out charloop_ending_pos2, out charloop_starting_pos2);
+               
+               if (Utilities.s_hasTimeout)
+               {
+                   base.CheckTimeout();
+               }
+               
+               if (charloop_starting_pos2 >= charloop_ending_pos2 ||
+                   (charloop_ending_pos2 = inputSpan.Slice(charloop_starting_pos2, charloop_ending_pos2 - charloop_starting_pos2).LastIndexOfAny(Utilities.s_asciiLettersAndDigitsAndKelvinSign)) < 0)
+               {
+                   goto LoopIterationNoMatch3;
+               }
+               charloop_ending_pos2 += charloop_starting_pos2;
+               pos = charloop_ending_pos2;
+               slice = inputSpan.Slice(pos);
+               
+               CharLoopEnd2:
+               Utilities.StackPush(ref base.runstack!, ref stackpos, charloop_starting_pos2, charloop_ending_pos2);
+           //}
+           
+           // Match a character in the set [0-9A-Za-z\u212A].
+           if (slice.IsEmpty || ((ch = slice[0]) < 128 ? !char.IsAsciiLetterOrDigit(ch) : !RegexRunner.CharInClass((char)ch, "\0\b\00:A[a{KÅ")))
          {
-               iteration3 = slice.Length;
+               goto CharLoopBacktrack2;
          }
          
-           slice = slice.Slice(iteration3);
-           pos += iteration3;
-           
-           charloop_ending_pos2 = pos;
-           goto CharLoopEnd2;
-           
-           CharLoopBacktrack2:
-           Utilities.StackPop(base.runstack!, ref stackpos, out charloop_ending_pos2, out charloop_starting_pos2);
-           
-           if (Utilities.s_hasTimeout)
-           {
-               base.CheckTimeout();
-           }
-           
-           if (charloop_starting_pos2 >= charloop_ending_pos2 ||
-               (charloop_ending_pos2 = inputSpan.Slice(charloop_starting_pos2, charloop_ending_pos2 - charloop_starting_pos2).LastIndexOfAny(Utilities.s_asciiLettersAndDigitsAndKelvinSign)) < 0)
-           {
-               goto LoopIterationNoMatch3;
-           }
-           charloop_ending_pos2 += charloop_starting_pos2;
-           pos = charloop_ending_pos2;
+           pos++;
          slice = inputSpan.Slice(pos);
          
-           CharLoopEnd2:
-           Utilities.StackPush(ref base.runstack!, ref stackpos, charloop_starting_pos2, charloop_ending_pos2);
+           // The loop has an upper bound of 1. Continue iterating greedily if it hasn't yet been reached.
+           if (loop_iteration3 == 0)
+           {
+               goto LoopBody3;
+           }
+           goto LoopEnd3;
+           
+           // The loop iteration failed. Put state back to the way it was before the iteration.
+           LoopIterationNoMatch3:
+           if (--loop_iteration3 < 0)
+           {
+               // Unable to match the remainder of the expression after exhausting the loop.
+               goto LoopIterationNoMatch1;
+           }
+           pos = base.runstack![--stackpos];
+           slice = inputSpan.Slice(pos);
+           LoopEnd3:
+           stackpos = startingStackpos1; // Ensure any remaining backtracking state is removed.
      //}
      
-       // Match a character in the set [0-9A-Za-z\u212A].
-       if (slice.IsEmpty || ((ch = slice[0]) < 128 ? !char.IsAsciiLetterOrDigit(ch) : !RegexRunner.CharInClass((char)ch, "\0\b\00:A[a{KÅ")))
-       {
-           goto CharLoopBacktrack2;
-       }
-       
-       pos++;
-       slice = inputSpan.Slice(pos);
-       
-       // The loop has an upper bound of 1. Continue iterating greedily if it hasn't yet been reached.
-       if (loop_iteration3 == 0)
-       {
-           goto LoopBody3;
-       }
-       goto LoopEnd3;
-       
-       // The loop iteration failed. Put state back to the way it was before the iteration.
-       LoopIterationNoMatch3:
-       if (--loop_iteration3 < 0)
-       {
-           // Unable to match the remainder of the expression after exhausting the loop.
-           goto LoopBacktrack2;
-       }
-       pos = base.runstack![--stackpos];
-       slice = inputSpan.Slice(pos);
-       goto LoopEnd3;
-       
-       LoopBacktrack3:
-       if (Utilities.s_hasTimeout)
-       {
-           base.CheckTimeout();
-       }
-       
-       if (loop_iteration3 == 0)
-       {
-           // No iterations of the loop remain to backtrack into. Fail the loop.
-           goto LoopBacktrack2;
-       }
-       goto CharLoopBacktrack2;
-       LoopEnd3:;
-   //}
+       stackpos = atomic_stackpos1;
+   }
  
  // Match if at the end of the string or if before an ending newline.
  if (pos < inputSpan.Length - 1 || ((uint)pos < (uint)inputSpan.Length && inputSpan[pos] != '\n'))
  {
-       goto LoopBacktrack3;
+       goto LoopIterationNoMatch1;
  }
  
  // The input matched.
"^!([0-9A-Za-z_\\-]*!)?$" (3395 uses)
[GeneratedRegex("^!([0-9A-Za-z_\\-]*!)?$")]
  int matchStart = pos;
  int loop_iteration = 0;
  int stackpos = 0;
+   int startingStackpos = 0;
  ReadOnlySpan<char> slice = inputSpan.Slice(pos);
  
  // Match if at the beginning of the string.
  }
  
  // Optional (greedy).
-   //{
+   {
      pos++;
      slice = inputSpan.Slice(pos);
+       startingStackpos = stackpos;
      loop_iteration = 0;
      
      LoopBody:
      pos = base.runstack![--stackpos];
      UncaptureUntil(base.runstack![--stackpos]);
      slice = inputSpan.Slice(pos);
-       LoopEnd:;
-   //}
+       LoopEnd:
+       stackpos = startingStackpos; // Ensure any remaining backtracking state is removed.
+   }
  
  // Match if at the end of the string or if before an ending newline.
  if (pos < inputSpan.Length - 1 || ((uint)pos < (uint)inputSpan.Length && inputSpan[pos] != '\n'))
  {
-       goto LoopIterationNoMatch;
+       UncaptureUntil(0);
+       return false; // The input didn't match.
  }
  
  // The input matched.
"AssemblyFileVersion(Attribute)?\\s*\\(.*\\)\\s*" (2417 uses)
[GeneratedRegex("AssemblyFileVersion(Attribute)?\\s*\\(.*\\)\\s*")]
  int charloop_starting_pos = 0, charloop_ending_pos = 0;
  int loop_iteration = 0;
  int stackpos = 0;
+   int startingStackpos = 0;
  ReadOnlySpan<char> slice = inputSpan.Slice(pos);
  
  // Match the string "AssemblyFileVersion".
  }
  
  // Optional (greedy).
-   //{
+   {
      pos += 19;
      slice = inputSpan.Slice(pos);
+       startingStackpos = stackpos;
      loop_iteration = 0;
      
      LoopBody:
      pos = base.runstack![--stackpos];
      UncaptureUntil(base.runstack![--stackpos]);
      slice = inputSpan.Slice(pos);
-       LoopEnd:;
-   //}
+       LoopEnd:
+       stackpos = startingStackpos; // Ensure any remaining backtracking state is removed.
+   }
  
  // Match a whitespace character atomically any number of times.
  {
  // Match '('.
  if (slice.IsEmpty || slice[0] != '(')
  {
-       goto LoopIterationNoMatch;
+       UncaptureUntil(0);
+       return false; // The input didn't match.
  }
  
  // Match a character other than '\n' greedily any number of times.
      if (charloop_starting_pos >= charloop_ending_pos ||
          (charloop_ending_pos = inputSpan.Slice(charloop_starting_pos, charloop_ending_pos - charloop_starting_pos).LastIndexOf(')')) < 0)
      {
-           goto LoopIterationNoMatch;
+           UncaptureUntil(0);
+           return false; // The input didn't match.
      }
      charloop_ending_pos += charloop_starting_pos;
      pos = charloop_ending_pos;

For more diff examples, see https://gist.github.com/MihuBot/890f4991a1798fc6e523c034b42d8950

Total bytes of base: 54706120
Total bytes of diff: 54274946
Total bytes of delta: -431174 (-0.79 % of base)
Total relative delta: -56.87
    diff is an improvement.
    relative diff is an improvement.

For a list of JIT diff regressions, see Regressions.md
For a list of JIT diff improvements, see Improvements.md

Sample source code for further analysis
const string JsonPath = "RegexResults-1268.json";
if (!File.Exists(JsonPath))
{
    await using var archiveStream = await new HttpClient().GetStreamAsync("https://mihubot.xyz/r/E2WocUI");
    using var archive = new ZipArchive(archiveStream, ZipArchiveMode.Read);
    archive.Entries.First(e => e.Name == "Results.json").ExtractToFile(JsonPath);
}

using FileStream jsonFileStream = File.OpenRead(JsonPath);
RegexEntry[] entries = JsonSerializer.Deserialize<RegexEntry[]>(jsonFileStream, new JsonSerializerOptions { IncludeFields = true })!;
Console.WriteLine($"Working with {entries.Length} patterns");



record KnownPattern(string Pattern, RegexOptions Options, int Count);

sealed class RegexEntry
{
    public required KnownPattern Regex { get; set; }
    public required string MainSource { get; set; }
    public required string PrSource { get; set; }
    public string? FullDiff { get; set; }
    public string? ShortDiff { get; set; }
    public (string Name, string Values)[]? SearchValuesOfChar { get; set; }
    public (string[] Values, StringComparison ComparisonType)[]? SearchValuesOfString { get; set; }
}

Artifacts:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions