Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Perl 5.17 change to use re 'eval' breaks Acme::EyeDrops

by eyepopslikeamosquito (Canon)
on Apr 25, 2013 at 03:31 UTC ( #1030569=perlquestion: print w/ replies, xml ) Need Help??
eyepopslikeamosquito has asked for the wisdom of the Perl Monks concerning the following question:

Though running this program, v1.pl:

( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( '' ) ) ))) ) ) ) ) ) ))))) ) =~("\(". ( ( '?')).'{' . ( ( '`')|'%') .('['^ ( '-') ) . ( '`'|'!') . ('`'|"\,"). '"'.('['^"\+").( '['^')').('`'|(')')).( '`'|'.').('['^'/').(('{')^ '[').'\\'.'"'.('`'|"\(").( '`'|'%').('`'|',').("\`"| ',').('`'|'/').('{'^'['). ('['^',').('`'|'/').("\["^ ')').('`'|',').('`'|('$')). '\\'.'\\'.('`'|'.').'\\'.'"' .';'.('!'^'+').'"'.'}'.')');
works fine with perl 5.16, running it with perl 5.17.10 produces an error:
Eval-group not allowed at runtime, use re 'eval' in regex m/(?{eval"pr +int\"hello world\\n\"; "})/ at v1.pl line 25.

Note that the Acme::EyeDrops-generated string being eval'ed above is a constant expression, as can be seen by running:

perl -MO=Deparse v1.pl
which produces:
'' =~ /(?{eval"print \"hello world\\n\";\n"})/; v1.pl syntax OK
Note further that running the deparsed program above works fine in perl 5.17 without requiring a leading use re 'eval'.

Though v1.pl can be made to work with perl 5.17.10 by adding a leading:

use re 'eval';
this destroys the artistic effect of having no alphanumeric characters at all. :) Moreover, I wonder why this is necessary, given the string being eval'ed is a constant expression and given that the deparsed program does not require it.

This change in use re 'eval' behavior was presumably introduced by Dave Mitchell's "re_eval jumbo fix" (see also ticket #113682). Given my test program above does not use tieing or overloading and no variables are interpolated in the (constant) expression, I wonder if this is a Perl 5.17 bug -- or am I missing something?

Assuming that use re 'eval' is really required for Perl v5.17.1+, I will need to fix the Acme::EyeDrops test suite to pass with the upcoming perl 5.18. Though adding a leading:

use if $] >= 5.017, re => 'eval';
or:
use if $^V && $^V gt 5.17.0, re => 'eval';
both seem to work fine, which is preferred?

References

Comment on Perl 5.17 change to use re 'eval' breaks Acme::EyeDrops
Select or Download Code
Re: Perl 5.17 change to use re 'eval' breaks Acme::EyeDrops
by tobyink (Abbot) on Apr 25, 2013 at 06:44 UTC

    Maybe the resulting script should have the following header:

    # If you want your scripts to look like this, you should use Acme::EyeDrops 2.00;

    Acme::EyeDrops would then add a VERSION method (which will be automatically called by Perl at compile time) which could do something along the lines of:

    sub VERSION { my $proto = shift; if (@_ and $_[0] >= 2.00 and $] >= 5.017) { require re; re->import("eval"); } $proto->SUPER::VERSION(@_); }

    That is, if you need to add some code, then make it look like a badly line-wrapped comment.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Perl 5.17 change to use re 'eval' breaks Acme::EyeDrops
by dave_the_m (Parson) on Apr 25, 2013 at 08:44 UTC
    Shorn of its obfuscation, that code is equivalent to
    '' =~ '(?{eval"print\"hello world\\n\""})';
    Note that the pattern is within a string literal ('') rather than a pattern literal (//). The 5.17.x changes make it so that code blocks which don't need a 'use re eval' can appear only within pattern literals.

    Dave.

      Thank you for that information.

      code blocks which don't need a 'use re eval' can appear only within pattern literals

      Why?

      - tye        

        Because I've changed it so that re code blocks are parsed now by the main perl parser, not by the regex engine calling back into the parser; e.g. /foo(?{ $x + 1 })/ is now parsed in the same manner that "foo$bar[$x + 1]" always has been. If it misses the parser and gets picked up later by by the regex engine (e.g. due to code appearing from external sources at runtime), then the engine will insist that 'use re eval' is in scope.

        This fixes lots of the bugs in re eval lexical scoping, while only breaking the occasional edge case. And it creates a simple understandable rule for when 'use re eval' needs to be in effect.

        It also means that the following, which formerly required 'use re eval', no longer does:

        $foo = 'bar'; /(?{...})$foo/

        Dave.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1030569]
Approved by NetWallah
Front-paged by NetWallah
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2014-11-22 02:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (118 votes), past polls