-
Notifications
You must be signed in to change notification settings - Fork 560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
re eval stack unwinding #16197
Comments
From @hvdsCreated by @hvds[Re-edited after github import] The code below shows an unexpected difference in stack unwinding the second time we enter a GOSUB inside a SUSPEND, that does not happen if only one or neither of those is present. This causes problems, for example, if you attempt to use SUSPEND inside rules in a Regexp::Grammars grammar. Bisect suggests this has always been there, so I'm guessing this is original behaviour preserved through DaveM's rework of the handling of regexp code blocks. I haven't yet attempted to follow this into the code, that's next. (But I hope Dave will take a look too.) The
I assume this is a bug primarily because I can see no reason for case 3 to differ from case 2. Hugo
Perl Info
|
Confirmed this problem persists in blead@6568ef821. |
I've spent some time trying to trace through this. The unexpected stack unwinding (which results in the diagnostic "remove frame post-D 3" appearing prematurely) is triggered in the FREETMPS of the PP(nextstate) that is the first op of the CALLRUNOPS invoked by the third EVAL. At this point in the above program, running with argument 1 vs argument 3, in both cases we're trying to go from
.. and with argument 3 it is identical, except the last 3 of those have a refcnt of 1. The refcnt_dec of the last of them (PL_tmps_stack[9]) triggers the releasing of the frame object. Tracking where those refcounts diverge between the two cases with a hardware watchpoint on PL_tmps_stack[9]->sv_refcnt points me to the
.. but in this case I assume the EVAL_postponed_AB state has been pushed via the GOSUB case which finishes with:
@iabyn can you maybe explain a bit more about the difference between EVAL_postponed_AB and EVAL_B, and whether it is correct that GOSUB is using the former? I've been focused enough on regcomp that it's quite a while since I delved into regexec. In case it helps here are the one-linish versions of the two cases:
Hugo |
Oh, it's a bit more complicated than that: |
.. I see Replacing
Replacing instead
My expectation is that none of the localizations should be unwound unless we backtrack, and there is no backtracking going on here. |
On Fri, 24 Jan 2020 at 14:14, Hugo van der Sanden ***@***.***> wrote:
$^R is also a confounding factor, since it is capturing the unintended
return from the evals. Avoiding that, we see an additional premature
unwinding, and more variation. With the main pattern:
m{
^ (
[a-z]
(?>
(?{ local @stack = push_frame("pre-D"); () })
(?&D)
(?{ local @stack = push_frame("post-D"); () })
)
)* $
(?(DEFINE) (?<D> [0-9] ) )
}x
.. I see remove frame post-D 3 between the first pair of SUCCEED:
subpattern success... and CLOSE1 and remove frame post-D 5 between the
second pair.
Replacing (?&D) with ([0-9]) I see no premature removals, and we finish
with:
Match successful!
remove frame post-D 5
remove frame pre-D 4
remove frame post-D 3
remove frame pre-D 2
remove frame start 1
Replacing instead (?> with (?:, I see no premature removals, but we now
finish with:
remove frame post-D 5
remove frame pre-D 4
remove frame post-D 3
Match successful!
remove frame pre-D 2
remove frame start 1
My expectation is that none of the localizations should be unwound unless
we backtrack, and there is no backtracking going on here.
I have worked on all of this at some point or another, but I am not sure I
understand what you are reporting as wrong.
Is it that the 1 and 3 variants do not have the same stack pattern?
Also, are you aware of
use re Debug => 'ALL';
use re Debug => 'State';
use re Debug => 'STATE';
all of which allow you see what is happening in the regex engine state
machine. For this case I suspect that STATE is the one you want:
$ ./perl -Ilib hv_bug.pl 1
add frame start 1
| 0| Setting an EVAL scope, savestack=12,
| 0| push #0 CURLYX_end yes
| 1| Setting an EVAL scope, savestack=18,
| 1| push #1 WHILEM_A_max
| 1| #0 CURLYX_end yes
| 2| push #2 IFMATCH_A yes
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
| 3| Setting an EVAL scope, savestack=25,
re EVAL PL_op=0x55ca275e61f0
add frame pre-D 2
before push pre-D: [start 1]
| 3| push #3 EVAL_B
| 3| #2 IFMATCH_A yes
| 3| #1 WHILEM_A_max
| 4| Setting an EVAL scope, savestack=45,
re EVAL PL_op=0x55ca2766bd98
add frame post-D 3
before push post-D: [start 1, pre-D 2]
| 4| push #4 EVAL_B
| 4| #3 EVAL_B
| 4| #2 IFMATCH_A yes
2 <a9> <b8> | 5| pop (yes) EVAL_B
2 <a9> <b8> | 4| pop (yes) EVAL_B
2 <a9> <b8> | 3| pop (yes) IFMATCH_A[Y]
| 2| Setting an EVAL scope, savestack=61,
| 2| push #2 WHILEM_A_max
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
| 3| push #3 IFMATCH_A yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
| 4| Setting an EVAL scope, savestack=71,
re EVAL PL_op=0x55ca275e61f0
add frame pre-D 4
before push pre-D: [start 1, pre-D 2, post-D 3]
| 4| push #4 EVAL_B
| 4| #3 IFMATCH_A yes
| 4| #2 WHILEM_A_max
| 5| Setting an EVAL scope,
savestack=87,
re EVAL PL_op=0x55ca2766bd98
add frame post-D 5
before push post-D: [start 1, pre-D 2, post-D 3, pre-D 4]
| 5| push #5 EVAL_B
| 5| #4 EVAL_B
| 5| #3 IFMATCH_A yes
4 <a9b8> <> | 6| pop (yes) EVAL_B
4 <a9b8> <> | 5| pop (yes) EVAL_B
4 <a9b8> <> | 4| pop (yes) IFMATCH_A[Y]
| 3| Setting an EVAL scope, savestack=103,
| 3| push #3 WHILEM_A_max
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
4 <a9b8> <> | 4| pop WHILEM_A_max
| 3| push #3 WHILEM_B_max yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
4 <a9b8> <> | 4| pop (yes) WHILEM_B_max[Y]
4 <a9b8> <> | 3| pop (yes) WHILEM_A_max
4 <a9b8> <> | 2| pop (yes) WHILEM_A_max
4 <a9b8> <> | 1| pop (yes) CURLYX_end[Y]
ok a9b8 (cut paren)
final[start 1]
remove frame post-D 5
remove frame pre-D 4
remove frame post-D 3
remove frame pre-D 2
remove frame start 1
$ ./perl -Ilib hv_bug.pl 3
add frame start 1
| 0| Setting an EVAL scope, savestack=12,
| 0| push #0 CURLYX_end yes
| 1| Setting an EVAL scope, savestack=18,
| 1| push #1 WHILEM_A_max
| 1| #0 CURLYX_end yes
| 2| push #2 IFMATCH_A yes
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
| 3| Setting an EVAL scope, savestack=25,
re EVAL PL_op=0x563ab08ba270
add frame pre-D 2
before push pre-D: [start 1]
| 3| push #3 EVAL_B
| 3| #2 IFMATCH_A yes
| 3| #1 WHILEM_A_max
| 4| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=563ab089c509
| 4| Setting an EVAL scope, savestack=42,
| 4| push #4 EVAL_postponed_AB yes
| 4| #3 EVAL_B
| 4| #2 IFMATCH_A yes
| 5| FAKE-END[before] GOSUB2
ce=563ab0832000 recurse_locinput=0
| 5| Setting an EVAL scope,
savestack=52,
| 5| push #5 EVAL_postponed_AB yes
| 5| #4 EVAL_postponed_AB yes
| 5| #3 EVAL_B
| 6| Setting an EVAL scope,
savestack=59,
re EVAL PL_op=0x563ab08ba968
add frame post-D 3
before push post-D: [start 1, pre-D 2]
| 6| push #6 EVAL_B
| 6| #5 EVAL_postponed_AB yes
| 6| #4 EVAL_postponed_AB yes
2 <a9> <b8> | 7| pop (yes) EVAL_B
2 <a9> <b8> | 6| pop (yes) EVAL_postponed_AB[Y]
| 5| EVAL_AB cur_eval=0
prev_eval=563ab0832000
| 5| EVAL_AB[after] GOSUB2
ce=563ab0832000 recurse_locinput=563ab089c509
2 <a9> <b8> | 5| pop (yes) EVAL_postponed_AB[Y]
| 4| EVAL_AB cur_eval=563ab0832000
prev_eval=0
| 4| EVAL_AB[before] GOSUB2
ce=563ab0832000 recurse_locinput=0
2 <a9> <b8> | 4| pop (yes) EVAL_B
2 <a9> <b8> | 3| pop (yes) IFMATCH_A[Y]
| 2| Setting an EVAL scope, savestack=42,
| 2| push #2 WHILEM_A_max
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
| 3| push #3 IFMATCH_A yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
| 4| Setting an EVAL scope, savestack=49,
re EVAL PL_op=0x563ab08ba270
remove frame post-D 3
add frame pre-D 4
before push pre-D: [start 1, pre-D 2]
| 4| push #4 EVAL_B
| 4| #3 IFMATCH_A yes
| 4| #2 WHILEM_A_max
| 5| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=563ab089c50b
| 5| Setting an EVAL scope,
savestack=62,
| 5| push #5 EVAL_postponed_AB yes
| 5| #4 EVAL_B
| 5| #3 IFMATCH_A yes
| 6| FAKE-END[before] GOSUB2
ce=563ab0832088 recurse_locinput=0
| 6| Setting an EVAL scope,
savestack=72,
| 6| push #6 EVAL_postponed_AB yes
| 6| #5 EVAL_postponed_AB yes
| 6| #4 EVAL_B
| 7| Setting an EVAL scope,
savestack=79,
re EVAL PL_op=0x563ab08ba968
add frame post-D 5
before push post-D: [start 1, pre-D 2, pre-D 4]
| 7| push #7 EVAL_B
| 7| #6 EVAL_postponed_AB yes
| 7| #5 EVAL_postponed_AB yes
4 <a9b8> <> | 8| pop (yes) EVAL_B
4 <a9b8> <> | 7| pop (yes) EVAL_postponed_AB[Y]
| 6| EVAL_AB cur_eval=0
prev_eval=563ab0832088
| 6| EVAL_AB[after] GOSUB2
ce=563ab0832088 recurse_locinput=563ab089c50b
4 <a9b8> <> | 6| pop (yes) EVAL_postponed_AB[Y]
| 5| EVAL_AB cur_eval=563ab0832088
prev_eval=0
| 5| EVAL_AB[before] GOSUB2
ce=563ab0832088 recurse_locinput=0
4 <a9b8> <> | 5| pop (yes) EVAL_B
4 <a9b8> <> | 4| pop (yes) IFMATCH_A[Y]
| 3| Setting an EVAL scope, savestack=62,
| 3| push #3 WHILEM_A_max
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
4 <a9b8> <> | 4| pop WHILEM_A_max
| 3| push #3 WHILEM_B_max yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
4 <a9b8> <> | 4| pop (yes) WHILEM_B_max[Y]
4 <a9b8> <> | 3| pop (yes) WHILEM_A_max
4 <a9b8> <> | 2| pop (yes) WHILEM_A_max
4 <a9b8> <> | 1| pop (yes) CURLYX_end[Y]
ok a9b8 (cut gosub)
final[start 1]
remove frame post-D 5
remove frame pre-D 4
remove frame pre-D 2
remove frame start 1
…--
perl -Mre=debug -e "/just|another|perl|hacker/"'
|
BTW, here is the diff of the two (hex values were normalized to deadbeef)
…--- hv1.txt 2020-01-25 06:32:52.742235628 +0100
+++ hv3.txt 2020-01-25 06:32:42.338168019 +0100
@@ -11,35 +11,67 @@
| 3| push #3 EVAL_B
| 3| #2 IFMATCH_A yes
| 3| #1 WHILEM_A_max
- | 4| Setting an EVAL scope,
savestack=45,
- re EVAL PL_op=0xdeadbeef
- | 4| push #4 EVAL_B
+ | 4| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=deadbeef
+ | 4| Setting an EVAL scope,
savestack=42,
+ | 4| push #4 EVAL_postponed_AB yes
| 4| #3 EVAL_B
| 4| #2 IFMATCH_A yes
- 2 <a9> <b8> | 5| pop (yes) EVAL_B
+ | 5| FAKE-END[before] GOSUB2
ce=deadbeef recurse_locinput=0
+ | 5| Setting an EVAL scope,
savestack=52,
+ | 5| push #5 EVAL_postponed_AB yes
+ | 5| #4 EVAL_postponed_AB yes
+ | 5| #3 EVAL_B
+ | 6| Setting an EVAL scope,
savestack=59,
+ re EVAL PL_op=0xdeadbeef
+ | 6| push #6 EVAL_B
+ | 6| #5 EVAL_postponed_AB yes
+ | 6| #4 EVAL_postponed_AB yes
+ 2 <a9> <b8> | 7| pop (yes) EVAL_B
+ 2 <a9> <b8> | 6| pop (yes) EVAL_postponed_AB[Y]
+ | 5| EVAL_AB cur_eval=0
prev_eval=deadbeef
+ | 5| EVAL_AB[after] GOSUB2 ce=deadbeef
recurse_locinput=deadbeef
+ 2 <a9> <b8> | 5| pop (yes) EVAL_postponed_AB[Y]
+ | 4| EVAL_AB cur_eval=deadbeef
prev_eval=0
+ | 4| EVAL_AB[before] GOSUB2 ce=deadbeef
recurse_locinput=0
2 <a9> <b8> | 4| pop (yes) EVAL_B
2 <a9> <b8> | 3| pop (yes) IFMATCH_A[Y]
- | 2| Setting an EVAL scope, savestack=61,
+ | 2| Setting an EVAL scope, savestack=42,
| 2| push #2 WHILEM_A_max
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
| 3| push #3 IFMATCH_A yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
- | 4| Setting an EVAL scope,
savestack=71,
+ | 4| Setting an EVAL scope,
savestack=49,
re EVAL PL_op=0xdeadbeef
| 4| push #4 EVAL_B
| 4| #3 IFMATCH_A yes
| 4| #2 WHILEM_A_max
- | 5| Setting an EVAL scope,
savestack=87,
- re EVAL PL_op=0xdeadbeef
- | 5| push #5 EVAL_B
+ | 5| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=deadbeef
+ | 5| Setting an EVAL scope,
savestack=62,
+ | 5| push #5 EVAL_postponed_AB yes
| 5| #4 EVAL_B
| 5| #3 IFMATCH_A yes
- 4 <a9b8> <> | 6| pop (yes) EVAL_B
+ | 6| FAKE-END[before] GOSUB2
ce=deadbeef recurse_locinput=0
+ | 6| Setting an EVAL scope,
savestack=72,
+ | 6| push #6 EVAL_postponed_AB yes
+ | 6| #5 EVAL_postponed_AB yes
+ | 6| #4 EVAL_B
+ | 7| Setting an EVAL scope,
savestack=79,
+ re EVAL PL_op=0xdeadbeef
+ | 7| push #7 EVAL_B
+ | 7| #6 EVAL_postponed_AB yes
+ | 7| #5 EVAL_postponed_AB yes
+ 4 <a9b8> <> | 8| pop (yes) EVAL_B
+ 4 <a9b8> <> | 7| pop (yes) EVAL_postponed_AB[Y]
+ | 6| EVAL_AB cur_eval=0
prev_eval=deadbeef
+ | 6| EVAL_AB[after] GOSUB2
ce=deadbeef recurse_locinput=deadbeef
+ 4 <a9b8> <> | 6| pop (yes) EVAL_postponed_AB[Y]
+ | 5| EVAL_AB cur_eval=deadbeef
prev_eval=0
+ | 5| EVAL_AB[before] GOSUB2
ce=deadbeef recurse_locinput=0
4 <a9b8> <> | 5| pop (yes) EVAL_B
4 <a9b8> <> | 4| pop (yes) IFMATCH_A[Y]
- | 3| Setting an EVAL scope,
savestack=103,
+ | 3| Setting an EVAL scope, savestack=62,
| 3| push #3 WHILEM_A_max
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
@@ -56,14 +88,14 @@
before push pre-D: [start 1]
add frame post-D 3
before push post-D: [start 1, pre-D 2]
+remove frame post-D 3
add frame pre-D 4
-before push pre-D: [start 1, pre-D 2, post-D 3]
+before push pre-D: [start 1, pre-D 2]
add frame post-D 5
-before push post-D: [start 1, pre-D 2, post-D 3, pre-D 4]
-ok a9b8 (cut paren)
+before push post-D: [start 1, pre-D 2, pre-D 4]
+ok a9b8 (cut gosub)
final[start 1]
remove frame post-D 5
remove frame pre-D 4
-remove frame post-D 3
remove frame pre-D 2
remove frame start 1
--
perl -Mre=debug -e "/just|another|perl|hacker/"
|
On Sat, 25 Jan 2020 at 06:39, demerphq ***@***.***> wrote:
BTW, here is the diff of the two (hex values were normalized to deadbeef)
And here is the same thing use Debug => 'State', which includes EXECUTE.
$ diff -u hv1.txt hv3.txt
--- hv1.txt 2020-01-25 06:40:05.820079429 +0100
+++ hv3.txt 2020-01-25 06:40:11.428094016 +0100
@@ -325,16 +325,16 @@
Intuit: Successfully guessed: match at offset 0
| 0| Setting an EVAL scope, savestack=12,
0 <> <a9b8> | 0| 1:SBOL /^/(2)
- 0 <> <a9b8> | 0| 2:CURLYX[0]{0,INFTY}(25)
+ 0 <> <a9b8> | 0| 2:CURLYX[0]{0,INFTY}(23)
| 0| push #0 CURLYX_end yes
- 0 <> <a9b8> | 1| 24:WHILEM[1/1](0)
+ 0 <> <a9b8> | 1| 22:WHILEM[1/1](0)
| 1| WHILEM: matched 0 out of 0..65535
| 1| Setting an EVAL scope, savestack=18,
| 1| push #1 WHILEM_A_max
| 1| #0 CURLYX_end yes
0 <> <a9b8> | 2| 4:OPEN1(6)
0 <> <a9b8> | 2| 6:POSIXA[:lower:](7)
- 1 <a> <9b8> | 2| 7:SUSPEND(22)
+ 1 <a> <9b8> | 2| 7:SUSPEND(20)
| 2| push #2 IFMATCH_A yes
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
@@ -344,57 +344,93 @@
| 3| push #3 EVAL_B
| 3| #2 IFMATCH_A yes
| 3| #1 WHILEM_A_max
- 1 <a> <9b8> | 4| 12:OPEN2(14)
- 1 <a> <9b8> | 4| 14:POSIXA[\d](15)
- 2 <a9> <b8> | 4| 15:CLOSE2(17)
- 2 <a9> <b8> | 4| 17:EVAL(20)
- | 4| Setting an EVAL scope,
savestack=45,
- re EVAL PL_op=0xdeadbeef
- | 4| push #4 EVAL_B
+ 1 <a> <9b8> | 4| 12:GOSUB2[+17:29] 'D'(15)
+ | 4| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=deadbeef
+ | 4| Setting an EVAL scope,
savestack=42,
+ | 4| push #4 EVAL_postponed_AB yes
| 4| #3 EVAL_B
| 4| #2 IFMATCH_A yes
- 2 <a9> <b8> | 5| 20:SUCCEED(0)
- | 5| SUCCEED: subpattern success...
- 2 <a9> <b8> | 5| pop (yes) EVAL_B
+ 1 <a> <9b8> | 5| 29:OPEN2 'D'(31)
+ 1 <a> <9b8> | 5| 31:POSIXA[\d](32)
+ 2 <a9> <b8> | 5| 32:CLOSE2 'D'(37)
+ | 5| FAKE-END[before] GOSUB2
ce=deadbeef recurse_locinput=0
+ | 5| Setting an EVAL scope,
savestack=52,
+ | 5| END: EVAL trying tail ...
(cur_eval=0)
+ | 5| push #5 EVAL_postponed_AB yes
+ | 5| #4 EVAL_postponed_AB yes
+ | 5| #3 EVAL_B
+ 2 <a9> <b8> | 6| 15:EVAL(18)
+ | 6| Setting an EVAL scope,
savestack=59,
+ re EVAL PL_op=0xdeadbeef
+ | 6| push #6 EVAL_B
+ | 6| #5 EVAL_postponed_AB yes
+ | 6| #4 EVAL_postponed_AB yes
+ 2 <a9> <b8> | 7| 18:SUCCEED(0)
+ | 7| SUCCEED: subpattern success...
+ 2 <a9> <b8> | 7| pop (yes) EVAL_B
+ 2 <a9> <b8> | 6| pop (yes) EVAL_postponed_AB[Y]
+ | 5| EVAL_AB cur_eval=0
prev_eval=deadbeef
+ | 5| EVAL_AB[after] GOSUB2 ce=deadbeef
recurse_locinput=deadbeef
+ 2 <a9> <b8> | 5| pop (yes) EVAL_postponed_AB[Y]
+ | 4| EVAL_AB cur_eval=deadbeef
prev_eval=0
+ | 4| EVAL_AB[before] GOSUB2 ce=deadbeef
recurse_locinput=0
2 <a9> <b8> | 4| pop (yes) EVAL_B
2 <a9> <b8> | 3| pop (yes) IFMATCH_A[Y]
- 2 <a9> <b8> | 2| 22:CLOSE1(24)
- 2 <a9> <b8> | 2| 24:WHILEM[1/1](0)
+ 2 <a9> <b8> | 2| 20:CLOSE1(22)
+ 2 <a9> <b8> | 2| 22:WHILEM[1/1](0)
| 2| WHILEM: matched 1 out of 0..65535
- | 2| Setting an EVAL scope, savestack=61,
+ | 2| Setting an EVAL scope, savestack=42,
| 2| push #2 WHILEM_A_max
| 2| #1 WHILEM_A_max
| 2| #0 CURLYX_end yes
2 <a9> <b8> | 3| 4:OPEN1(6)
2 <a9> <b8> | 3| 6:POSIXA[:lower:](7)
- 3 <a9b> <8> | 3| 7:SUSPEND(22)
+ 3 <a9b> <8> | 3| 7:SUSPEND(20)
| 3| push #3 IFMATCH_A yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
3 <a9b> <8> | 4| 9:EVAL(12)
- | 4| Setting an EVAL scope,
savestack=71,
+ | 4| Setting an EVAL scope,
savestack=49,
re EVAL PL_op=0xdeadbeef
| 4| push #4 EVAL_B
| 4| #3 IFMATCH_A yes
| 4| #2 WHILEM_A_max
- 3 <a9b> <8> | 5| 12:OPEN2(14)
- 3 <a9b> <8> | 5| 14:POSIXA[\d](15)
- 4 <a9b8> <> | 5| 15:CLOSE2(17)
- 4 <a9b8> <> | 5| 17:EVAL(20)
- | 5| Setting an EVAL scope,
savestack=87,
- re EVAL PL_op=0xdeadbeef
- | 5| push #5 EVAL_B
+ 3 <a9b> <8> | 5| 12:GOSUB2[+17:29] 'D'(15)
+ | 5| entering GOSUB,
prev_recurse_locinput=0 recurse_locinput[2]=deadbeef
+ | 5| Setting an EVAL scope,
savestack=62,
+ | 5| push #5 EVAL_postponed_AB yes
| 5| #4 EVAL_B
| 5| #3 IFMATCH_A yes
- 4 <a9b8> <> | 6| 20:SUCCEED(0)
- | 6| SUCCEED: subpattern success...
- 4 <a9b8> <> | 6| pop (yes) EVAL_B
+ 3 <a9b> <8> | 6| 29:OPEN2 'D'(31)
+ 3 <a9b> <8> | 6| 31:POSIXA[\d](32)
+ 4 <a9b8> <> | 6| 32:CLOSE2 'D'(37)
+ | 6| FAKE-END[before] GOSUB2
ce=deadbeef recurse_locinput=0
+ | 6| Setting an EVAL scope,
savestack=72,
+ | 6| END: EVAL trying tail ...
(cur_eval=0)
+ | 6| push #6 EVAL_postponed_AB yes
+ | 6| #5 EVAL_postponed_AB yes
+ | 6| #4 EVAL_B
+ 4 <a9b8> <> | 7| 15:EVAL(18)
+ | 7| Setting an EVAL scope,
savestack=79,
+ re EVAL PL_op=0xdeadbeef
+ | 7| push #7 EVAL_B
+ | 7| #6 EVAL_postponed_AB yes
+ | 7| #5 EVAL_postponed_AB yes
+ 4 <a9b8> <> | 8| 18:SUCCEED(0)
+ | 8| SUCCEED: subpattern success...
+ 4 <a9b8> <> | 8| pop (yes) EVAL_B
+ 4 <a9b8> <> | 7| pop (yes) EVAL_postponed_AB[Y]
+ | 6| EVAL_AB cur_eval=0
prev_eval=deadbeef
+ | 6| EVAL_AB[after] GOSUB2
ce=deadbeef recurse_locinput=deadbeef
+ 4 <a9b8> <> | 6| pop (yes) EVAL_postponed_AB[Y]
+ | 5| EVAL_AB cur_eval=deadbeef
prev_eval=0
+ | 5| EVAL_AB[before] GOSUB2
ce=deadbeef recurse_locinput=0
4 <a9b8> <> | 5| pop (yes) EVAL_B
4 <a9b8> <> | 4| pop (yes) IFMATCH_A[Y]
- 4 <a9b8> <> | 3| 22:CLOSE1(24)
- 4 <a9b8> <> | 3| 24:WHILEM[1/1](0)
+ 4 <a9b8> <> | 3| 20:CLOSE1(22)
+ 4 <a9b8> <> | 3| 22:WHILEM[1/1](0)
| 3| WHILEM: matched 2 out of 0..65535
- | 3| Setting an EVAL scope,
savestack=103,
+ | 3| Setting an EVAL scope, savestack=62,
| 3| push #3 WHILEM_A_max
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
@@ -406,12 +442,12 @@
| 3| push #3 WHILEM_B_max yes
| 3| #2 WHILEM_A_max
| 3| #1 WHILEM_A_max
- 4 <a9b8> <> | 4| 25:NOTHING(26)
- 4 <a9b8> <> | 4| 26:SEOL(27)
- 4 <a9b8> <> | 4| 27:DEFINEP(29)
- 4 <a9b8> <> | 4| 29:IFTHEN(38)
- 4 <a9b8> <> | 4| 38:TAIL(39)
- 4 <a9b8> <> | 4| 39:END(0)
+ 4 <a9b8> <> | 4| 23:NOTHING(24)
+ 4 <a9b8> <> | 4| 24:SEOL(25)
+ 4 <a9b8> <> | 4| 25:DEFINEP(27)
+ 4 <a9b8> <> | 4| 27:IFTHEN(36)
+ 4 <a9b8> <> | 4| 36:TAIL(37)
+ 4 <a9b8> <> | 4| 37:END(0)
4 <a9b8> <> | 4| pop (yes) WHILEM_B_max[Y]
4 <a9b8> <> | 3| pop (yes) WHILEM_A_max
4 <a9b8> <> | 2| pop (yes) WHILEM_A_max
@@ -419,6 +455,8 @@
Match successful!
Freeing REx: "%n ^ ( [a-z]%n (?:%t(?# 1: cut or uncut )%n
"...
Freeing REx: "%n ^ ( [a-z]%n (?:%t(?# 1: cut or uncut )%n
"...
+Freeing REx: "%n ^ ( [a-z]%n (?>%t(?# 1: cut or uncut )%n
"...
+Freeing REx: "%n ^ ( [a-z]%n (?>%t(?# 1: cut or uncut )%n
"...
Freeing REx: "%n ^ ( [a-z]%n (?:%t(?# 1: cut or uncut )%n
"...
Freeing REx: "%n ^ ( [a-z]%n (?:%t(?# 1: cut or uncut )%n
"...
add frame start 1
@@ -426,16 +464,14 @@
before push pre-D: [start 1]
add frame post-D 3
before push post-D: [start 1, pre-D 2]
+remove frame post-D 3
add frame pre-D 4
-before push pre-D: [start 1, pre-D 2, post-D 3]
+before push pre-D: [start 1, pre-D 2]
add frame post-D 5
-before push post-D: [start 1, pre-D 2, post-D 3, pre-D 4]
-ok a9b8 (cut paren)
+before push post-D: [start 1, pre-D 2, pre-D 4]
+ok a9b8 (cut gosub)
final[start 1]
remove frame post-D 5
remove frame pre-D 4
-remove frame post-D 3
remove frame pre-D 2
-Freeing REx: "%n ^ ( [a-z]%n (?>%t(?# 1: cut or uncut )%n
"...
-Freeing REx: "%n ^ ( [a-z]%n (?>%t(?# 1: cut or uncut )%n
"...
remove frame start 1
|
Precisely the last line you quoted of mine: my expectation is that none of the localizations should be unwound unless we backtrack, and there is no backtracking going on here. In this bit in particular: the "remove frame" diagnostic shows that some level of localization of
I've used ALL occasionally, I haven't looked specifically at STATE. Hugo |
Migrated from rt.perl.org#132277 (status was 'new')
Searchable as RT132277$
The text was updated successfully, but these errors were encountered: