Language-FormulaEngine
view release on metacpan or search on metacpan
lib/Language/FormulaEngine/Compiler.pm view on Meta::CPAN
# Else need to create a generator around a native perl function
$info->{native}
or die "Cannot compile function '$name'; no generator or native function given\n";
my $fqn= subname($info->{native}) || '';
# For security, make reasonably sure that perl will parse the subname as a function name.
# This regex is more restrictive than perl's actual allowed identifier names.
$fqn =~ /^[A-Za-z_][A-Za-z0-9_]*::([A-Za-z0-9_]+::)*\p{Word}+$/
or die "Can't compile function '$name'; native function does not have a valid fully qualified name '$fqn'\n";
# Create a generator that injects this function name
return sub {
$fqn . '(' . join(',', map $_[1]->perlgen($_), @{ $_[2]->parameters }) . ')'
};
}
sub perlgen_var_access {
my ($self, $varname)= @_;
return $self->_optimize_var_access
? '$vars->{'.$self->perlgen_string_literal(lc $varname).'}'
: '$namespace->get_value('.$self->perlgen_string_literal($varname).')';
}
sub perlgen_string_literal {
my ($self, $string)= @_;
$string =~ s/([\0-\x1F\x7f"\@\$\%\\])/ sprintf("\\x%02x", ord $1) /gex;
return qq{"$string"};
}
sub perlgen_literal {
my ($self, $string)= @_;
no warnings 'numeric';
return ($string+0) eq $string? $string+0 : $self->perlgen_string_literal($string);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Language::FormulaEngine::Compiler - Compile a parse tree into perl code
=head1 VERSION
version 0.08
=head1 DESCRIPTION
The Compiler object takes a parse tree and generates perl code from it, and also evals
that perl code into a compiled coderef. However, most of the code generation is handled
by the L<Language::FormulaEngine::Namespace> object. The namespace object must be
available during compilation. In the default scenario, the namespace object will be
consulted for default constants and "global" variables, and then the generated coderef
will accept additional variables to overlay on those global variables, but the Namespace
will still get to determine how to access that pool of combined variables at execution.
For alternative strategies, see the C<output_api> attribute below.
=head1 ATTRIBUTES
=head2 namespace
Instance of L<Language::FormulaEngine::Namespace> to use for looking up functions,
converting functions to perl code, and symbolic constants. This namespace object will
be referenced by the coderefs, and can act as a "global scope".
=head2 output_api
Determines the function signature of the coderef that will be generated. Currently supported
values are:
=over 25
=item C<"function_of_vars">
# generated coderef signature:
$value = $coderef->(%vars);
$value = $coderef->(\%vars);
The list or hashref of variables will get overlaid ontop of the set of variables of the
namespace (by creating a derived namespace), and the namespace C<get_value> method will
retrieve values from them.
=item C<"function_of_vars_no_default">
Same signature as "function_of_vars" but current C<< $namespace->variables >> are ignored
and either a new empty namespace is created each time, or (if C<optimize_var_access> is
active) no namespace will be used at all and vars will be read directly from a hashref.
=item C<"function_of_namespace">
# generated coderef signature:
$value= $coderef->();
$value= $coderef->($namespace);
$value= $coderef->(\%namespace_attributes);
This either uses the supplied namespace *instead* of the default, or merges attributes with
the default namespace via L<Language::FormulaEngine::Namespace/clone_and_merge>.
=back
=head2 optimize_var_access
By default, when a formula accesses a variable it will call L<Language::FormulaEngine::Namespace/get_value>
but for higher performance, you can have the formula directly access the variables hashref,
bypassing C<get_value>.
If this attribute is not set, the compilation will default to using the optimization if the
L</namespace> is using the default implementation of C<get_value> (i.e. has not been overridden
by a subclass) and the coderefs are a function of variables.
=head2 error
After a failed call to C<compile>, this attribute holds the error message.
( run in 0.414 second using v1.01-cache-2.11-cpan-e1769b4cff6 )