Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 524 forks source link

[doc] perl -c vs. "outside" #22143

Open jidanni opened 2 weeks ago

jidanni commented 2 weeks ago

man perlrun says

  -c   causes Perl to check the  syntax  of  the  program  and  then  exit
       without  executing  it.   Actually,  it  will  execute any "BEGIN",
       "UNITCHECK", or "CHECK" blocks and any "use" statements: these  are
       considered  as  occurring  outside  the  execution of your program.
       "INIT" and "END" blocks, however, will be skipped.

It seems the word "outside" needs to be changed to "inside", for the above paragraph to make sense.

Anyway, some people would just like to check the syntax of the single file in front of them, without needing to comment out any "use", or providing paths.

Just like if their program said open(my $fh, "<", "input.txt"), when not having such a input.txt ready yet. It shouldn't affect the syntax check.

So maybe an option could be added for that.

Grinnz commented 2 weeks ago

"outside" is correct, the compilation is considered outside the execution, though this may better be replaced with "before". Syntax cannot be checked without executing these blocks and use statements, because these things can and commonly do modify the parser (the simplest example is "use strict").

mauke commented 2 weeks ago

Conceptually, Perl programs have a compilation phase (where source code is parsed and translated to an internal representation) and a run-time phase (where the internal representation is executed). In practice, perl always performs these two steps together, one directly after the other, so for the most part, you don't have to care. But technically the steps are:

The -c switch stops after compile time ends, so all the runtime parts are skipped.

Not executing use would break a lot of code. Not just in obvious cases like use strict or use feature (which have a big impact on how the following code is parsed), but also seemingly harmless cases like:

use Scalar::Util qw(looks_like_number);
if (looks_like_number "31.42-1") {
    print "yay\n";
}

This code just imports and calls a subroutine. But without executing the use statement, we get:

String found where operator expected (Do you need to predeclare "looks_like_number"?) at - line 2, near "looks_like_number "31.42e-1""
syntax error at - line 2, near "looks_like_number "31.42e-1""
Execution of - aborted due to compilation errors.
jidanni commented 2 weeks ago

Okay okay okay. So let's just concentrate on that word "outside". Seems like it's just checking the things outside the program and not the things inside or something.

If we change it to "before" then where should we put the word "after" etc.?

I think somebody needs to do a professional redo on that paragraph. Not some amateur like me.

guest20 commented 2 weeks ago

@jidanni

I think it's also worth nothing that you can't just "focus on this one word in a sentence", you need to look at 'em all, and form a kind of parse tree, and then extract the meaning from that.

I'd like to propose that we just concentrate on "statements [that] are considered as occurring outside the execution of your program".

If you include those other words into your reading it becomes clearer that it's not checking the parts "considered as occurring outside the execution of your program", it's executing the parts "considered as occurring outside the execution of your program".

</@ mention>

To me it seems like an explanation of why these blocks need to be run/skipped is more than one can readily boil down into a single sentence, so it might be worth not including it in a summary/usage message and just describing the behaviour direclty:

 -c   causes Perl to check the  syntax  of  the  program  and  then  exit without  executing  it. 
      Security note: -c will run some code blocks (BEGIN/use/require/CHECK/etc)
                     and skip others (END/INIT). 
                     see L<perlrun/why-minus-c-runs-some-stuff> for more.
jidanni commented 2 weeks ago

Hey that's a good idea. Just tell what it is going to do. No need to get into deep logic about it. OK, please make the edit. Thanks!