tod222 has asked for the wisdom of the Perl Monks concerning the following question:
I've written an application which implements a domain specific language (DSL). To keep the implementation simple, the DSL allows the use of Perl snippets which are fed to eval.
The Perl snippets can reference scalars (and in the future, arrays) which are declared in the DSL outside the snippet. (Note that the names of variables defined in the DSL may not begin with an underscore.)
I've come up with three different implementations.
I'm looking for comments and feedback on which is best, or suggestions for better alternatives. Note that there are really two separate issues here -- the main one of the best method for running the snippet, and the secondary one of the best method for converting the hash entries to scalars and back.
The 'no warnings' and 'no strict' statements are needed to hide error messages that are a side effect of the way Alias.pm is implemented.
Advantages: Easy to implement.
Disadvantages:
The code:
sub _onmatch_fail { my ( $self, $_codetext, $_valhref, $_taskname ) = @_; my $FAIL_MATCH = 0; # m +atch defaults to succeed my $_codetext = "# line 1 task[$_taskname]\n" . $_codetext; { use Alias qw(attr); attr $_valhref; no Alias; no warnings qw(once); no strict qw(vars); eval $_codetext; die $@ if $@; return $FAIL_MATCH; } }
Advantages:
Disadvantages:
The code:
package App::Tasker::Exec; sub _onmatch_fail { my ( $_codetext, $_valhref, $_taskname ) = @_; @_ = (); { my $FAIL_MATCH = 0; # match defaults to succeed my $evaltext = ''; my $epilog = ''; my $_newval = {}; while ( my ( $k, $v ) = each %$_valhref ) { $evaltext .= <<EOT; my \$$k = '$v'; EOT $epilog .= <<EOT; \$_newval->{'$k'} = \$$k; EOT } $evaltext .= "# line 1 task[$_taskname]\n" . $_codetext; $evaltext .= $epilog; eval $evaltext; die $@ if $@; for my $k ( keys %$_valhref ) { $_valhref->{$k} = $_newval->{$k}; } return $FAIL_MATCH; } }
Note that the use of a formerly undocumented argument to Safe.pm's reval method is needed to prevent it from using 'no strict'.
Advantages:
Disadvantages
The code:
package App::Tasker::SafeExec; sub _onmatch_fail { my ( $_codetext, $_valhref, $_taskname ) = @_; $_codetext .= "# line 1 task[$_taskname]\n" . $_codetext; { use Safe; my $_compartment = new Safe; our $FAIL_MATCH = 0; # match defaults to succeed my $_epilog = ''; my $_newval = {}; my $_evaltext = <<'EOT'; $_compartment->share('$FAIL_MATCH'); EOT while ( my ( $k, $v ) = each %$_valhref ) { $_evaltext .= <<EOT; our \$$k = '$v'; \$_compartment->share('\$$k'); EOT $_epilog .= <<EOT; \$_newval->{'$k'} = \$$k; EOT } $_evaltext .= <<'EOT'; $_compartment->reval($_codetext, 1); die $@ if $@; EOT $_evaltext .= $_epilog; eval $_evaltext; die $@ if $@; for my $k ( keys %$_valhref ) { $_valhref->{$k} = $_newval->{$k}; } return $FAIL_MATCH; } }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Best of three methods for evaling Perl snippets?
by kyle (Abbot) on Sep 04, 2008 at 02:57 UTC | |
by tod222 (Pilgrim) on Sep 04, 2008 at 19:05 UTC |