Eugen Konkov Eugen Konkov - 2 months ago 17
Perl Question

Why debugger stops on `use` statement?

When we enclose this code into braces:

#!/usr/bin/env perl

{
use warnings 'void';
1;
}


The debugger stops on
use warnings 'void'
statement:

main::(/home/kes/tmp/t3.pl:4): use warnings 'void';
DB<1> l 1-20
1 #!/usr/bin/env perl
2
3 {
4==> use warnings 'void';
5: 1;
6 }
7


But if we do not:

#!/usr/bin/env perl


use warnings 'void';
1;


The debugger does not stop on
use warnings 'void'
statement:

main::(/home/kes/tmp/t3.pl:5): 1;
DB<1> l 1-20
1 #!/usr/bin/env perl
2
3
4: use warnings 'void';
5==> 1;
6
7


But, as we can see,
line 4
still marked as breakable.

What are differences in these examples

and why debugger does not stop on
line 4
?

Answer

The use statement is never added to the compiled program because it is executed at compile-time.

$ perl -MO=Concise,-exec -e'use warnings qw( void ); f()'
1  <0> enter
2  <;> nextstate(main 2 -e:1) v:{
3  <0> pushmark s
4  <#> gv[*f] s/EARLYCV
5  <1> entersub[t2] vKS/TARG
6  <@> leave[1 ref] vKP/REFC
-e syntax OK

As such, the debugger is never actually stopping on the use statement. Let's look at the compiled form of both programs:

$ perl -MO=Concise
{
   use warnings qw( void );
   1;
}
^D
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -:2) v:{ ->3
5     <2> leaveloop vK/2 ->6
3        <{> enterloop(next->5 last->5 redo->4) v ->4
-        <@> lineseq vKP ->5
4           <;> nextstate(main 3 -:3) v:{ ->5
-           <0> ex-const v ->-
- syntax OK

$ perl -MO=Concise
use warnings qw( void );
1;
^D
3  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -:2) v:{ ->3
-     <0> ex-const v ->3
- syntax OK

nextstate ops set the line number for run-time warnings. (For example, -:2 means line 2 of the code read from STDIN.) The debugger is also using these to know where to break and to find the line in the source file of the current statement.

The second snippet has only one run-time statement, so it has a single nextstate op at which the debugger stop.

The first snippet, however, has two statements. A bare loop ({ ... }), and a constant. The bare loop creates a nextstate op with the line of the first non-whitespace character that follows the {, which happens to be the use warnings;. I'm not sure why it does this.