The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Language::FormulaEngine::Compiler - Compile a parse tree into perl code

VERSION

version 0.08

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 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 output_api attribute below.

ATTRIBUTES

namespace

Instance of 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".

output_api

Determines the function signature of the coderef that will be generated. Currently supported values are:

"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 get_value method will retrieve values from them.

"function_of_vars_no_default"

Same signature as "function_of_vars" but current $namespace->variables are ignored and either a new empty namespace is created each time, or (if optimize_var_access is active) no namespace will be used at all and vars will be read directly from a hashref.

"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 "clone_and_merge" in Language::FormulaEngine::Namespace.

optimize_var_access

By default, when a formula accesses a variable it will call "get_value" in Language::FormulaEngine::Namespace but for higher performance, you can have the formula directly access the variables hashref, bypassing get_value.

If this attribute is not set, the compilation will default to using the optimization if the "namespace" is using the default implementation of get_value (i.e. has not been overridden by a subclass) and the coderefs are a function of variables.

error

After a failed call to compile, this attribute holds the error message.

code_body

After compilation, this attribute holds the perl source code that was generated prior to being wrapped with the coderef boilerplate.

METHODS

compile( $parse_tree, $subname )

Compile a parse tree, returning a coderef. Any references to functions will be immeditely looked up within the "namespace". Any references to constants in the "namespace" will be inlined into the generated perl. Any other symbol is assumed to be a variable, and will be looked up from the "namespace" at the time the formula is invoked.

See attribute output_api for the signature and behavior of this coderef.

Because the generated coderef contains a reference to the namespace, be sure never to store one of the coderefs into that namespace object, else you get a memory leak.

The second argument $subname is optional, but provided to help encourage use of "set_subname" in Sub::Util for generated code.

reset

Clear any temporary results from the last compilation. Returns $self.

generate_coderef_wrapper

  my $coderef= $compiler->generate_coderef_wrapper($perl_code, $subname);

Utility method used by "compile" that wraps a bit of perl code with the relevant boilerplate according to "output_api", and then evals the perl to create the coderef.

On a compile failure, this returns undef and puts the error message into "error".

perlgen

  $perl_code= $compiler->perlgen( $parse_node );

Generate perl source code for a parse node. This is a fragment, not a whole sub. The code should always be an expression which can be combined with other function calls.

perlgen_var_access

  $compiler->perlgen_var_access($varname);

Generate perl code to access a variable. Unless "optimize_var_access" is true, this becomes a call to $namespace->get_value($varname), and the namespace decides how to interpret the variable at execution time. If optimize_var_access is enabled, this returns a reference to the $vars hashref like $vars->{$varname}.

perlgen_string_literal

Generate a perl string literal. This wraps the string with double-quotes and escapes control characters and ["\\\@\$] using hex-escape notation. Hex escapes are chosen over simple backslash prefixes for extra security, in case of mistakes elsewhere in the generated code.

perlgen_literal

If the scalar can be exactly represented by a perl numeric literal, this returns that literal, else it wraps the string with qoutes using "perlgen_string_literal".

AUTHOR

Michael Conrad <mconrad@intellitree.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by Michael Conrad, IntelliTree Solutions llc.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.