also looking at this
fix(vm): make findAll linear by stopping matchAt when no threads remain
#8
3 files
+102
-0
| @@ -227,6 +227,17 @@ pub const VM = struct { | ||
| 227 | 227 | next_threads.clearRetainingCapacity(); |
| 228 | 228 | |
| 229 | 229 | pos += 1; |
| 230 | ||
| 231 | // No live threads remain. matchAt only ever seeds the start-state | |
| 232 | // thread (at start_pos), and threads can only be spawned by cloning | |
| 233 | // existing ones, so once the set is empty no further match can | |
| 234 | // begin from this start_pos — the longest match found so far | |
| 235 | // (last_match) is final. Without this break the loop walks every | |
| 236 | // remaining byte doing nothing; because findAll restarts matchAt | |
| 237 | // per match, that dead-walk is what makes findAll O(n^2). Any | |
| 238 | // accepting state reached on the consumed input was already | |
| 239 | // recorded by the accept check at the top of the loop. | |
| 240 | if (current_threads.items.len == 0) break; | |
| 230 | 241 | } |
| 231 | 242 | |
| 232 | 243 | // Return the last (longest) match we found |