|
2 | 2 |
|
3 | 3 | import org.perlonjava.operators.WarnDie;
|
4 | 4 | import org.perlonjava.runtime.*;
|
| 5 | +import org.perlonjava.runtime.GlobalContext; // Add this import |
5 | 6 |
|
6 | 7 | import java.util.ArrayList;
|
7 | 8 | import java.util.Iterator;
|
@@ -65,6 +66,7 @@ protected boolean removeEldestEntry(Map.Entry<String, RuntimeRegex> eldest) {
|
65 | 66 | private RuntimeScalar replacement = null;
|
66 | 67 | // Tracks if a match has occurred: this is used as a counter for m?PAT?
|
67 | 68 | private boolean matched = false;
|
| 69 | + private boolean hasCodeBlockCaptures = false; // True if regex has (?{...}) code blocks |
68 | 70 |
|
69 | 71 | public RuntimeRegex() {
|
70 | 72 | this.regexFlags = null;
|
@@ -104,6 +106,18 @@ public static RuntimeRegex compile(String patternString, String modifiers) {
|
104 | 106 |
|
105 | 107 | // Compile the regex pattern
|
106 | 108 | regex.pattern = Pattern.compile(javaPattern, regex.patternFlags);
|
| 109 | + |
| 110 | + // Check if pattern has code block captures for $^R optimization |
| 111 | + // Code blocks are encoded as named captures like (?<cb010...>) |
| 112 | + Map<String, Integer> namedGroups = regex.pattern.namedGroups(); |
| 113 | + if (namedGroups != null) { |
| 114 | + for (String groupName : namedGroups.keySet()) { |
| 115 | + if (CaptureNameEncoder.isCodeBlockCapture(groupName)) { |
| 116 | + regex.hasCodeBlockCaptures = true; |
| 117 | + break; |
| 118 | + } |
| 119 | + } |
| 120 | + } |
107 | 121 | } catch (Exception e) {
|
108 | 122 | if (GlobalVariable.getGlobalHash("main::ENV").get("JPERL_UNIMPLEMENTED").toString().equals("warn")
|
109 | 123 | ) {
|
@@ -428,6 +442,14 @@ public static RuntimeBase matchRegex(RuntimeScalar quotedRegex, RuntimeScalar st
|
428 | 442 | lastSuccessfulMatchEnd = lastMatchEnd;
|
429 | 443 | lastSuccessfulMatchString = globalMatchString;
|
430 | 444 |
|
| 445 | + // Update $^R if this regex has code block captures (performance optimization) |
| 446 | + if (regex.hasCodeBlockCaptures) { |
| 447 | + RuntimeScalar codeBlockResult = regex.getLastCodeBlockResult(); |
| 448 | + // Set $^R to the code block result (or undef if no code blocks matched) |
| 449 | + GlobalVariable.getGlobalVariable(GlobalContext.encodeSpecialVar("R")) |
| 450 | + .set(codeBlockResult != null ? codeBlockResult : RuntimeScalarCache.scalarUndef); |
| 451 | + } |
| 452 | + |
431 | 453 | // Reset pos() after global match in LIST context (matches Perl behavior)
|
432 | 454 | if (regex.regexFlags.isGlobalMatch() && ctx == RuntimeContextType.LIST) {
|
433 | 455 | posScalar.set(scalarUndef);
|
|
0 commit comments