Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding the "eval" in perl

Tags:

perl

Having the following:

use 5.014;
use warnings;
BEGIN {
    use subs qw(int);
    sub int {
        print STDERR "\tthe int got: $_[0]\n";
        my $res =  CORE::int($_[0]);
        print STDERR "\tCORE::int: $res\n";
        return $res;
    }
}

my $x;
$x = 1.1 ; say "result of int($x) is: ", int($x);
$x = 6.6 ; say "result of int($x) is: ", int($x);

it prints

    the int got: 1.1
    CORE::int: 1
result of int(1.1) is: 1
    the int got: 6.6
    CORE::int: 6
result of int(6.6) is: 6

The int function is overridden by my own function, which does some debug-prints, and returns the result of the original (CORE) implementation.

Looking for the same for the eval. But, probably because the eval isn't a function like the int the override as above doesn't works for the eval.

Is it possible to achieve this somewhat? E.g. want override the eval (the eval "$string") with my own eval as above, e.g.:

  • should print the got string
  • and should call the core implementation of the eval

EDIT: According to comments the above isn't possible for the eval. So:

In short: want debug print of all eval "$strings" in my program, before evaluation. It is possible somewhat?

like image 809
kobame Avatar asked Jul 09 '15 15:07

kobame


1 Answers

eval can't be overridden in the same fashion as int since its interface can't be prototyped.

$ perl -E'say prototype("CORE::".$ARGV[0]) // "[undef]"' int
_

$ perl -E'say prototype("CORE::".$ARGV[0]) // "[undef]"' eval
[undef]

But there's some good news! Someone had similar needs to yours, solved it by manipulating the opcode, and published a solution to CPAN in the form of overload::eval for everyone to use.

The documentation claims to only affect eval in the lexical scope of the use, but there's a hidden flag $overload::eval::GLOBAL = 1; that makes it affect all calls to eval EXPR.

like image 193
ikegami Avatar answered Nov 12 '22 11:11

ikegami