Can Perl be “statically” parsed?

后端 未结 5 1966
醉梦人生
醉梦人生 2020-12-30 10:42

An article called \"Perl cannot be parsed, a formal proof\" is doing the rounds. So, does Perl decide the meaning of its parsed code at \"run-time\" or \"compile-time\"?

5条回答
  •  萌比男神i
    2020-12-30 11:19

    Perl has a compile phase, but it's different than most normal compile phases when it comes to code. Perl's lexer turns the code into tokens, then a parser analyzes tokens to form an op tree. However, BEGIN {} blocks can interrupt this process and allow you to execute code. When doing a use. All BEGIN blocks execute before anything else, giving you a way to set up modules and namespaces. During the overall "compile" of a script, you most likely will use Perl to determine how the Perl module should look when it's done. sub, bare, implies adding it to the glob for the package, but you don't have to. For example, this is a (albeit, odd) way of setting up methods in a module:

    package Foo;
    
    use strict;
    use warnings;
    use List::Util qw/shuffle/;
    
    my @names = qw(foo bar baz bill barn);
    my @subs = (
        sub { print "baz!" },
        sub { die; },
        sub { return sub { die } },
    );
    @names = shuffle @names;
    foreach my $index (0..$#subs) {
       no strict 'refs';
       *{$names[$index]} = $subs[$index];
    }
    
    1;
    

    You have to interpret this to even know what it does! It's not very useful, but it's not something you can determine ahead of time. But it's 100% valid perl. Even though this feature can be abused, it can also do great tasks, like build complicated subs that all look very similar, programatically. It also makes it hard to know, for certain, what everything does.

    That's not to say that a perl script can't be 'compiled' - in perl, compiling is merely determining, what right then, the module should look like. You can do that with a

    perl -c myscript.pl
    

    and it will tell you whether or not it can get to the point where it will start executing the main module. You just can't merely know from looking at it 'statically'.

    However, as PPI demonstrates, we can get close. Really close. Close enough to do very interesting things, like (almost static) code analysis.

    "Run Time", then, becomes what happens after all the BEGIN blocks have executed. (This is a simplification; there is a lot more to this. See perlmod for more.) It's still perl code being run, but it's a separate phase of execution, done after all the higher priority blocks have run.

    chromatic has some detailed posts on his Modern::Perl blog:

    • How a Perl 5 Program Works
    • On Parsing Perl 5

提交回复
热议问题