Example #1
0
    /**
     * Creates a new compiled evaluator from the supplied expressions.
     *
     * @param Expression[]       $expressions
     * @param IEvaluationContext $context
     *
     * @return CompiledEvaluator
     */
    public static function fromExpressions(array $expressions, IEvaluationContext $context = null)
    {
        $evaluator = new self($context);
        $namespace = $evaluator->context->getNamespace();
        $contextParameterName = self::CONTEXT_PARAMETER_NAME;
        $variableTable = $evaluator->context->getVariableTable();
        //Replace any non value types with references in the variable table.
        $expressions = (new DynamicExpressionWalker([ValueExpression::getType() => function (ValueExpression $expression) use($evaluator, $variableTable, &$name) {
            $value = $expression->getValue();
            if (!ValueExpression::isValueType($value)) {
                $name = $name !== null ? $name : 0;
                do {
                    $name++;
                } while (isset($variableTable['o' . $name]));
                $name = 'o' . $name;
                $evaluator->extraVariables[$name] = $value;
                return Expression::variable(Expression::value($name));
            }
            return $expression;
        }]))->walkAll($expressions);
        $bodyCode = '';
        foreach ($evaluator->extraVariables + $variableTable as $variable => $value) {
            $variableName = Expression::value($variable);
            $variableCode = Expression::variable($variableName)->compile();
            $bodyCode .= "{$variableCode} =& \${$contextParameterName}" . '[' . $variableName->compile() . '];';
        }
        $bodyCode .= "unset(\${$contextParameterName});";
        $bodyCode .= implode(';', Expression::compileAll($expressions)) . ';';
        $evaluator->code = <<<PHP
namespace {$namespace} {
    return function (\${$contextParameterName}) {
        {$bodyCode}
    };
}
PHP;
        $evaluator->initializeEvaluator();
        return $evaluator;
    }