Eugen Konkov
Eugen Konkov

Reputation: 25153

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?

Upvotes: 1

Views: 48

Answers (1)

ikegami
ikegami

Reputation: 385897

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.

Upvotes: 4

Related Questions