Create a String expression from a Expression

@param expr
@return String expression
@throws TemplateException
549510
public static ExprInt toExprInt(Expression expr) {
	if (expr instanceof ExprInt) return (ExprInt) expr;
	if (expr instanceof Literal) {
	    Double dbl = ((Literal) expr).getDouble(null);
	    if (dbl != null) return expr.getFactory().createLitInteger((int) dbl.doubleValue(), expr.getStart(), expr.getEnd());
	}
	return new CastInt(expr);
    }
698324
public static <T> TemplateExpression<T> template(Class<? extends T> cl, Template template, Object... args) {
        return template(cl, template, ImmutableList.copyOf(args));
    }
996774
public static <T> JPQLQuery<T> select(Expression<T> expr) {
        return new JPASubQuery<Void>().select(expr);
    }
881311
private String processExpression(String expressionString) {
    expressionString = expressionString == null ? "" : expressionString.trim();
    if (expressionString.isEmpty()) {
      if (isAttributeBinding(currentAttribute)) {
        logger.error(
            "Empty expression in template property binding. If you want to pass an empty string then simply don't use binding: my-attribute=\"\"",
            currentAttribute.toString());
      } else if (isEventBinding(currentAttribute)) {
        logger.error("Empty expression in template event binding.",
            currentAttribute.toString());
      } else {
        return "";
      }
    }

    if (expressionString.startsWith("{")) {
      logger.error(
          "Object literal syntax are not supported yet in Vue GWT, please use map(e(\"key1\", myValue), e(\"key2\", myValue2 > 5)...) instead. The object returned by map() is a regular Javascript Object (JsObject) with the given key/values.",
          expressionString);
    }

    if (expressionString.startsWith("[")) {
      logger.error(
          "Array literal syntax are not supported yet in Vue GWT, please use array(myValue, myValue2 > 5...) instead. The object returned by array() is a regular Javascript Array (JsArray) with the given values.",
          expressionString);
    }

    if (shouldSkipExpressionProcessing(expressionString)) {
      return expressionString;
    }

    return processJavaExpression(expressionString).toTemplateString();
  }
281576
public function buildExpression(Expression $expr = null)
    {
        if (!$this->defaultExpression) {
            $this->defaultExpression = Expr::method('isEnabled', Expr::same(true))
                ->andMethod('getTypeName', Expr::same(DiscoveryUrlGenerator::BINDING_TYPE))
                ->andMethod('getBinding', Expr::method('getQuery', Expr::endsWith('{,/**/*}')));
        }

        if (!$expr) {
            return $this->defaultExpression;
        }

        $traverser = new ExpressionTraverser();
        $traverser->addVisitor($this);

        return $this->defaultExpression->andX($traverser->traverse($expr));
    }
13807
public static <T> SimpleExpression<T> asSimple(Expression<T> expr) {
        Expression<T> underlyingMixin = ExpressionUtils.extract(expr);
        if (underlyingMixin instanceof PathImpl) {
            return new SimplePath<T>((PathImpl<T>) underlyingMixin);
        } else if (underlyingMixin instanceof OperationImpl) {
            return new SimpleOperation<T>((OperationImpl<T>) underlyingMixin);
        } else if (underlyingMixin instanceof TemplateExpressionImpl) {
            return new SimpleTemplate<T>((TemplateExpressionImpl<T>) underlyingMixin);
        } else {
            return new SimpleExpression<T>(underlyingMixin) {

                private static final long serialVersionUID = -8712299418891960222L;

                @Override
                public <R, C> R accept(Visitor<R, C> v, C context) {
                    return this.mixin.accept(v, context);
                }

            };
        }
    }
421573
public static Expression fromExpr(JsExpr expr, Iterable<GoogRequire> requires) {
    return Leaf.create(expr, /* isCheap= */ false, requires);
  }
72314
public static DataExpr parseDataExpr(String expr) {
    try {
      return (DataExpr) parse(expr);
    } catch (ClassCastException e) {
      throw new IllegalArgumentException("invalid data expression: " + expr, e);
    }
  }
181499
public function compile(Expression $expr, CompilationContext $compilationContext)
    {
        $expression = $expr->getExpression();

        $exprVariable = new Expression($expression['variable']);
        $exprVariable->setReadOnly(true);
        $exprCompiledVariable = $exprVariable->compile($compilationContext);

        $builtInType = false;
        switch ($exprCompiledVariable->getType()) {
            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead(
                    $exprCompiledVariable->getCode(),
                    $compilationContext,
                    $expression
                );
                switch ($variableVariable->getType()) {
                    case 'variable':
                        $caller = $variableVariable;
                        break;
                    default:
                        /* Check if there is a built-in type optimizer available */
                        $builtInTypeClass = 'Zephir\Types\\'.ucfirst($variableVariable->getType()).'Type';
                        if (class_exists($builtInTypeClass)) {
                            /**
                             * @var \Zephir\Types\AbstractType
                             */
                            $builtInType = new $builtInTypeClass();
                            $caller = $exprCompiledVariable;
                        } else {
                            throw new CompilerException(
                                'Methods cannot be called on variable type: '.$variableVariable->getType(),
                                $expression
                            );
                        }
                }
                break;
            default:
                /* Check if there is a built-in type optimizer available */
                $builtInTypeClass = 'Zephir\Types\\'.ucfirst($exprCompiledVariable->getType()).'Type';
                if (class_exists($builtInTypeClass)) {
                    $builtInType = new $builtInTypeClass();
                    $caller = $exprCompiledVariable;
                } else {
                    throw new CompilerException(
                        'Cannot use expression: '.$exprCompiledVariable->getType().' as method caller',
                        $expression['variable']
                    );
                }
        }

        $codePrinter = $compilationContext->codePrinter;

        $type = $expression['call-type'];

        /*
         * In normal method calls and dynamic string method calls we just use the name given by the user
         */
        if (self::CALL_NORMAL == $type || self::CALL_DYNAMIC_STRING == $type) {
            $methodName = strtolower($expression['name']);
        } else {
            $variableMethod = $compilationContext->symbolTable->getVariableForRead(
                $expression['name'],
                $compilationContext,
                $expression
            );

            if (\is_object($builtInType)) {
                throw new CompilerException(
                    'Dynamic method invocation for type: '.$variableMethod->getType().' is not supported',
                    $expression
                );
            }

            if ($variableMethod->isNotVariableAndString()) {
                throw new CompilerException(
                    'Cannot use variable type: '.$variableMethod->getType().' as dynamic method name',
                    $expression
                );
            }
        }

        $symbolVariable = null;

        /**
         * Create temporary variable if needed.
         */
        $mustInit = false;
        $isExpecting = $expr->isExpectingReturn();
        if ($isExpecting) {
            $symbolVariable = $expr->getExpectingVariable();
            if (\is_object($symbolVariable)) {
                $readDetector = new ReadDetector($expression);
                if ($caller == $symbolVariable || $readDetector->detect($symbolVariable->getName(), $expression)) {
                    $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserveOrNullify(
                        'variable',
                        $compilationContext,
                        $expression
                    );
                } else {
                    $mustInit = true;
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserveOrNullify(
                    'variable',
                    $compilationContext,
                    $expression
                );
            }
        }

        /*
         * Method calls only return zvals so we need to validate the target variable is also a zval
         */
        if (!$builtInType) {
            if ($isExpecting) {
                if (!$symbolVariable->isVariable()) {
                    throw new CompilerException(
                        'Returned values by functions can only be assigned to variant variables',
                        $expression
                    );
                }

                /*
                 * At this point, we don't know the exact dynamic type returned by the method call
                 */
                $symbolVariable->setDynamicTypes('undefined');
            }
        } else {
            return $builtInType->invokeMethod($methodName, $caller, $compilationContext, $this, $expression);
        }

        $check = true;
        if (isset($expression['check'])) {
            $check = $expression['check'];
        }

        /*
         * Try to check if the method exist in the callee, only when method call is self::CALL_NORMAL
         */
        if (self::CALL_NORMAL == $type) {
            if ('this' == $variableVariable->getRealName()) {
                $classDefinition = $compilationContext->classDefinition;
                if (!$classDefinition->hasMethod($methodName)) {
                    if ($check) {
                        $found = false;

                        if ($classDefinition->isAbstract()) {
                            $interfaces = $classDefinition->getImplementedInterfaces();
                        } else {
                            $interfaces = null;
                        }

                        if (\is_array($interfaces)) {
                            $compiler = $compilationContext->compiler;
                            foreach ($interfaces as $interface) {
                                $classInterfaceDefinition = $compiler->getClassDefinition($interface);

                                if (!$classInterfaceDefinition) {
                                    $classInterfaceDefinition = $compiler->getInternalClassDefinition($interface);
                                    if (!$classInterfaceDefinition) {
                                        throw new CompilerException(
                                            "Couldn't locate internal or external interface: ".$interface,
                                            $expression
                                        );
                                    }
                                }

                                if ($classInterfaceDefinition->hasMethod($methodName)) {
                                    $found = true;
                                    $classMethod = $classInterfaceDefinition->getMethod($methodName);
                                    break;
                                }
                            }
                        }

                        if (!$found) {
                            $possibleMethod = $classDefinition->getPossibleMethodName($expression['name']);
                            if ($possibleMethod && $expression['name'] != $possibleMethod) {
                                throw new CompilerException(
                                    sprintf(
                                        "Class '%s' does not implement method: '%s'. Did you mean '%s'?",
                                        $classDefinition->getCompleteName(),
                                        $expression['name'],
                                        $possibleMethod
                                    ),
                                    $expression
                                );
                            }

                            throw new CompilerException(
                                sprintf(
                                    "Class '%s' does not implement method: '%s'",
                                    $classDefinition->getCompleteName(),
                                    $expression['name']
                                ),
                                $expression
                            );
                        }
                    }
                } else {
                    if ($check) {
                        $classMethod = $classDefinition->getMethod($methodName);
                    }
                }

                if ($check) {
                    /*
                     * Private methods must be called in their declaration scope
                     */
                    if ($classMethod->isPrivate()) {
                        if ($classMethod->getClassDefinition() !== $classDefinition) {
                            throw new CompilerException(
                                "Cannot call private method '".$expression['name']."' out of its scope",
                                $expression
                            );
                        }
                    }

                    /*
                     * Try to produce an exception if method is called with a wrong number of parameters
                     */
                    if (isset($expression['parameters'])) {
                        $callNumberParameters = \count($expression['parameters']);
                    } else {
                        $callNumberParameters = 0;
                    }

                    $expectedNumberParameters = $classMethod->getNumberOfRequiredParameters();
                    if (!$expectedNumberParameters && $callNumberParameters > 0) {
                        $numberParameters = $classMethod->getNumberOfParameters();
                        if ($callNumberParameters > $numberParameters) {
                            throw new CompilerException(
                                sprintf(
                                    "Method '%s::%s' called with a wrong number of parameters, ".
                                    'the method has: %d, passed: %d',
                                    $classDefinition->getCompleteName(),
                                    $expression['name'],
                                    $expectedNumberParameters,
                                    $callNumberParameters
                                ),
                                $expression
                            );
                        }
                    }

                    if ($callNumberParameters < $expectedNumberParameters) {
                        throw new CompilerException(
                            sprintf(
                                "Method '%s::%s' called with a wrong number of parameters, ".
                                'the method has: %d, passed: %d',
                                $classDefinition->getCompleteName(),
                                $expression['name'],
                                $expectedNumberParameters,
                                $callNumberParameters
                            ),
                            $expression
                        );
                    }

                    $method = $classMethod;
                }
            } else {
                /*
                 * Variables whose dynamic type is 'object' can be used
                 * to determine method existence in compile time
                 */
                if ($check && $variableVariable->hasAnyDynamicType('object')) {
                    $classTypes = $variableVariable->getClassTypes();

                    if (\count($classTypes)) {
                        $numberImplemented = 0;
                        $compiler = $compilationContext->compiler;
                        foreach ($classTypes as $classType) {
                            if ($compiler->isClass($classType) ||
                                $compiler->isInterface($classType) ||
                                $compiler->isBundledClass($classType) ||
                                $compiler->isBundledInterface($classType)
                            ) {
                                if ($compiler->isClass($classType) || $compiler->isInterface($classType)) {
                                    $classDefinition = $compiler->getClassDefinition($classType);
                                } else {
                                    $classDefinition = $compiler->getInternalClassDefinition($classType);
                                }

                                if (!$classDefinition) {
                                    throw new CompilerException(
                                        'Cannot locate class definition for class '.$classType,
                                        $expression
                                    );
                                }

                                if (!$classDefinition->hasMethod($methodName)) {
                                    if (!$classDefinition->isInterface()) {
                                        if (1 == \count($classTypes)) {
                                            throw new CompilerException(
                                                sprintf(
                                                    "Class '%s' does not implement method: '%s'",
                                                    $classType,
                                                    $expression['name']
                                                ),
                                                $expression
                                            );
                                        }
                                    }
                                    continue;
                                }

                                $method = $classDefinition->getMethod($methodName);

                                /*
                                 * Private methods must be called in their declaration scope
                                 */
                                if ($method->isPrivate()) {
                                    if ($method->getClassDefinition() != $classDefinition) {
                                        throw new CompilerException(
                                            sprintf(
                                                "Cannot call private method '%s' out of its scope",
                                                $expression['name']
                                            ),
                                            $expression
                                        );
                                    }
                                }

                                /*
                                 * Check visibility for protected methods
                                 */
                                if ($method->isProtected() &&
                                    $method->getClassDefinition() != $classDefinition &&
                                    $method->getClassDefinition() != $classDefinition->getExtendsClass()
                                ) {
                                    throw new CompilerException(
                                        sprintf(
                                            "Cannot call protected method '%s' out of its scope",
                                            $expression['name']
                                        ),
                                        $expression
                                    );
                                }

                                /*
                                 * Try to produce an exception if a method is called with a wrong number of parameters
                                 * We only check extension parameters if methods are extension methods
                                 * Internal methods may have invalid Reflection information
                                 */
                                if ($method instanceof ClassMethod && !$method->isBundled()) {
                                    if (isset($expression['parameters'])) {
                                        $callNumberParameters = \count($expression['parameters']);
                                    } else {
                                        $callNumberParameters = 0;
                                    }

                                    $classMethod = $classDefinition->getMethod($methodName);
                                    $expectedNumberParameters = $classMethod->getNumberOfRequiredParameters();

                                    if (!$expectedNumberParameters && $callNumberParameters > 0) {
                                        $numberParameters = $classMethod->getNumberOfParameters();
                                        if ($callNumberParameters > $numberParameters) {
                                            $className = $classDefinition->getCompleteName();
                                            throw new CompilerException(
                                                sprintf(
                                                    "Method '%s::%s' called with a wrong number of parameters, ".
                                                    'the method has: %d, passed: %s',
                                                    $className,
                                                    $expression['name'],
                                                    $expectedNumberParameters,
                                                    $callNumberParameters
                                                ),
                                                $expression
                                            );
                                        }
                                    }

                                    if ($callNumberParameters < $expectedNumberParameters) {
                                        throw new CompilerException(
                                            sprintf(
                                                "Method '%s::%s' called with a wrong number of parameters, ".
                                                'the method has: %d, passed: %d',
                                                $classDefinition->getCompleteName(),
                                                $expression['name'],
                                                $expectedNumberParameters,
                                                $callNumberParameters
                                            ),
                                            $expression
                                        );
                                    }
                                }

                                /*
                                 * The method is checked in the first class that implements the method
                                 * We could probably have collisions here
                                 */
                                ++$numberImplemented;
                                break;
                            } else {
                                ++$numberImplemented;
                                $compilationContext->logger->warning(
                                    'Class "'.$classType.'" does not exist at compile time',
                                    ['nonexistent-class', $expression]
                                );
                            }
                        }

                        if (0 == $numberImplemented) {
                            if (!$classDefinition->isInterface()) {
                                if (\count($classTypes) > 1) {
                                    throw new CompilerException(
                                        sprintf(
                                            "None of classes: '%s' implement method: '%s'",
                                            implode(' or ', $classTypes),
                                            $expression['name']
                                        ),
                                        $expression
                                    );
                                } else {
                                    throw new CompilerException(
                                        sprintf(
                                            "Class '%s' does not implement method: '%s'",
                                            $classTypes[0],
                                            $expression['name']
                                        ),
                                        $expression
                                    );
                                }
                            } else {
                                // @TODO, raise an exception here?
                            }
                        }
                    }
                }
            }
        }

        if (isset($method)) {
            $this->reflection = $method;
        }

        /*
         * Transfer the return type-hint to the returned variable
         */
        if ($isExpecting) {
            if (isset($method)) {
                if ($method instanceof ClassMethod) {
                    if ($method->isVoid()) {
                        throw new CompilerException(
                            sprintf(
                                "Method '%s::%s' is marked as '%s' and it does not return anything",
                                $classDefinition->getCompleteName(),
                                $expression['name'],
                                Types::T_VOID
                            ),
                            $expression
                        );
                    }

                    $returnClassTypes = $method->getReturnClassTypes();

                    if (null !== $returnClassTypes) {
                        $symbolVariable->setDynamicTypes('object');
                        foreach ($returnClassTypes as &$returnClassType) {
                            $returnClassType = $compilationContext->getFullName($returnClassType);
                        }
                        $symbolVariable->setClassTypes($returnClassTypes);
                    }

                    $returnTypes = $method->getReturnTypes();
                    if (null !== $returnTypes) {
                        foreach ($returnTypes as $dataType => $returnType) {
                            $symbolVariable->setDynamicTypes($dataType);
                        }
                    }
                }
            }
        }

        /*
         * Some parameters in internal methods receive parameters as references
         */
        if (isset($expression['parameters'])) {
            $references = [];
            if (self::CALL_NORMAL == $type || self::CALL_DYNAMIC_STRING == $type) {
                if (isset($method)) {
                    if ($method instanceof \ReflectionMethod) {
                        $position = 0;
                        foreach ($method->getParameters() as $parameter) {
                            if ($parameter->isPassedByReference()) {
                                $references[$position] = true;
                            }
                            ++$position;
                        }
                    }
                }
            }
        }

        /*
         * Include fcall header
         */
        $compilationContext->headersManager->add('kernel/fcall');

        /*
         * Call methods must grown the stack
         */
        $compilationContext->symbolTable->mustGrownStack(true);

        /*
         * Mark references
         */
        $params = [];
        if (isset($expression['parameters'])) {
            $params = $this->getResolvedParams(
                $expression['parameters'],
                $compilationContext,
                $expression,
                isset($method) ? $method : null
            );

            if (\count($references)) {
                foreach ($params as $position => $param) {
                    if (isset($references[$position])) {
                        $compilationContext->codePrinter->output('Z_SET_ISREF_P('.$param.');');
                    }
                }
            }

            // We check here if a correct parameter type is passed to the called method
            if (self::CALL_NORMAL == $type) {
                if (isset($method) && $method instanceof ClassMethod && isset($expression['parameters'])) {
                    $resolvedTypes = $this->getResolvedTypes();
                    $resolvedDynamicTypes = $this->getResolvedDynamicTypes();

                    foreach ($method->getParameters() as $n => $parameter) {
                        if (isset($parameter['data-type'])) {
                            if (!isset($resolvedTypes[$n])) {
                                continue;
                            }

                            /*
                             * If the passed parameter is different to the expected type we show a warning
                             */
                            if ($resolvedTypes[$n] != $parameter['data-type']) {
                                $template = sprintf(
                                    'Passing possible incorrect type for parameter: %s::%s(%s), '.
                                    'passing: %s, expecting: %s',
                                    $classDefinition->getCompleteName(),
                                    $method->getName(),
                                    $parameter['name'],
                                    $resolvedTypes[$n],
                                    $parameter['data-type']
                                );

                                switch ($resolvedTypes[$n]) {
                                    case 'bool':
                                    case 'boolean':
                                        switch ($parameter['data-type']) {
                                            /* compatible types */
                                            case 'bool':
                                            case 'boolean':
                                            case 'variable':
                                                break;

                                            default:
                                                $compilationContext->logger->warning(
                                                    $template,
                                                    ['possible-wrong-parameter', $expression]
                                                );
                                                break;
                                        }
                                        break;

                                    case 'array':
                                        switch ($parameter['data-type']) {
                                            /* compatible types */
                                            case 'array':
                                            case 'variable':
                                                break;

                                            case 'callable':
                                                /*
                                                 * Array can be a callable type, example: [$this, "method"]
                                                 *
                                                 * @todo we need to check this array if can...
                                                 */
                                                break;

                                            default:
                                                $compilationContext->logger->warning(
                                                    $template,
                                                    ['possible-wrong-parameter', $expression]
                                                );
                                                break;
                                        }
                                        break;

                                    case 'callable':
                                        switch ($parameter['data-type']) {
                                            /* compatible types */
                                            case 'callable':
                                            case 'variable':
                                                break;

                                            default:
                                                $compilationContext->logger->warning(
                                                    $template,
                                                    ['possible-wrong-parameter', $expression]
                                                );
                                                break;
                                        }
                                        break;

                                    case 'string':
                                        switch ($parameter['data-type']) {
                                            /* compatible types */
                                            case 'string':
                                            case 'variable':
                                                break;

                                            default:
                                                $compilationContext->logger->warning(
                                                    $template,
                                                    ['possible-wrong-parameter', $expression]
                                                );
                                                break;
                                        }
                                        break;

                                    /*
                                     * Passing polymorphic variables to static typed parameters
                                     * could lead to potential unexpected type coercions
                                     */
                                    case 'variable':
                                        if ($resolvedDynamicTypes[$n] != $parameter['data-type']) {
                                            if ('undefined' == $resolvedDynamicTypes[$n]) {
                                                $compilationContext->logger->warning(
                                                    sprintf(
                                                        'Passing possible incorrect type for parameter: %s::%s(%s), '.
                                                        'passing: undefined, expecting: %s',
                                                        $classDefinition->getCompleteName(),
                                                        $method->getName(),
                                                        $parameter['name'],
                                                        $parameter['data-type']
                                                    ),
                                                    ['possible-wrong-parameter-undefined', $expression]
                                                );
                                            }
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }

        // Add the last call status to the current symbol table
        $this->addCallStatusFlag($compilationContext);

        // Initialize non-temporary variables
        if ($mustInit) {
            $symbolVariable->setMustInitNull(true);
            $symbolVariable->trackVariant($compilationContext);
        }

        // Generate the code according to the call type
        if (self::CALL_NORMAL == $type || self::CALL_DYNAMIC_STRING == $type) {
            $realMethod = $this->getRealCalledMethod($compilationContext, $variableVariable, $methodName);

            $isInternal = false;
            if (\is_object($realMethod[1])) {
                $realMethod[1] = $realMethod[1]->getOptimizedMethod();
                $method = $realMethod[1];
                $isInternal = $realMethod[1]->isInternal();
                if ($isInternal && $realMethod[0] > 1) {
                    throw new CompilerException(
                        "Cannot resolve method: '".$expression['name']."' in polymorphic variable",
                        $expression
                    );
                }
            }

            if (!$isInternal) {
                // Check if the method call can have an inline cache
                $methodCache = $compilationContext->cacheManager->getMethodCache();

                $cachePointer = $methodCache->get(
                    $compilationContext,
                    $methodName,
                    $variableVariable
                );

                $compilationContext->backend->callMethod(
                    $isExpecting ? $symbolVariable : null,
                    $variableVariable,
                    $methodName,
                    $cachePointer,
                    \count($params) ? $params : null,
                    $compilationContext
                );
            } else {
                //TODO: also move to backend
                if ($isExpecting) {
                    $symbolCode = $compilationContext->backend->getVariableCodePointer($symbolVariable);
                }
                $variableCode = $compilationContext->backend->getVariableCode($variableVariable);
                $paramCount = \count($params);
                $paramsStr = $paramCount ? ', '.implode(', ', $params) : '';

                if ($isExpecting) {
                    if ('return_value' == $symbolVariable->getName()) {
                        $macro = $compilationContext->backend->getFcallManager()->getMacro(false, true, $paramCount);
                        $codePrinter->output($macro.'('.$variableCode.', '.$method->getInternalName().$paramsStr.');');
                    } else {
                        $macro = $compilationContext->backend->getFcallManager()->getMacro(false, 2, $paramCount);
                        $codePrinter->output(
                            $macro.'('.$symbolCode.', '.$variableCode.', '.$method->getInternalName().$paramsStr.');'
                        );
                    }
                } else {
                    $macro = $compilationContext->backend->getFcallManager()->getMacro(false, false, $paramCount);
                    $codePrinter->output($macro.'('.$variableCode.', '.$method->getInternalName().$paramsStr.');');
                }
            }
        } else {
            if (self::CALL_DYNAMIC == $type) {
                switch ($variableMethod->getType()) {
                    case 'string':
                    case 'variable':
                        break;
                    default:
                        throw new Exception(
                            sprintf('Cannot use variable type: %s as method caller', $variableMethod->getType())
                        );
                }

                $cachePointer = 'NULL, 0';

                $compilationContext->backend->callMethod(
                    $isExpecting ? $symbolVariable : null,
                    $variableVariable,
                    $variableMethod,
                    $cachePointer,
                    \count($params) ? $params : null,
                    $compilationContext
                );
            }
        }

        // Temporary variables must be copied if they have more than one reference
        foreach ($this->getMustCheckForCopyVariables() as $checkVariable) {
            $codePrinter->output('zephir_check_temp_parameter('.$checkVariable.');');
        }

        // We can mark temporary variables generated as idle
        foreach ($this->getTemporalVariables() as $tempVariable) {
            $tempVariable->setIdle(true);
        }

        // Release parameters marked as references
        if (isset($expression['parameters'])) {
            if (\count($references)) {
                foreach ($params as $position => $param) {
                    if (isset($references[$position])) {
                        $compilationContext->codePrinter->output('Z_UNSET_ISREF_P('.$param.');');
                    }
                }
            }
        }

        $this->addCallStatusOrJump($compilationContext);

        if ($isExpecting) {
            return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
        }

        return new CompiledExpression('null', null, $expression);
    }
115075
public static <T> Expression<T> list(Class<T> clazz, Expression<?>... exprs) {
        return list(clazz, ImmutableList.copyOf(exprs));
    }
883508
protected Expression assignOp(Data data) throws TemplateException {

	Expression expr = conditionalOp(data);
	if (data.srcCode.forwardIfCurrent('=')) {

	    comments(data);
	    if (data.mode == STATIC) expr = new DynAssign(expr, assignOp(data));
	    else {
		if (expr instanceof Variable) {
		    Expression value = assignOp(data);
		    expr = new Assign((Variable) expr, value, data.srcCode.getPosition());
		}
		else if (expr instanceof Null) {
		    Variable var = ((Null) expr).toVariable();
		    Expression value = assignOp(data);
		    expr = new Assign(var, value, data.srcCode.getPosition());
		}
		else if (expr instanceof NullConstant) {
		    Variable var = ((NullConstant) expr).toVariable();
		    Expression value = assignOp(data);
		    expr = new Assign(var, value, data.srcCode.getPosition());
		}
		else throw new TemplateException(data.srcCode, "invalid assignment left-hand side (" + expr.getClass().getName() + ")");
	    }
	}

	// patch for test()(); only works at the end of an expression!
	comments(data);
	while (data.srcCode.isCurrent('(')) {
	    comments(data);
	    Call call = new Call(expr);
	    getFunctionMemberAttrs(data, null, false, call, null);
	    call.setEnd(data.srcCode.getPosition());
	    comments(data);
	    expr = call;
	}
	return expr;
    }
1251566
public static ValueExpression eval( CssFormatter formatter, Expression expr ) {
        expr = expr.unpack( formatter ); // unpack to increase the chance to find a ValueExpression
        if( expr.getClass() == ValueExpression.class ) {
            return (ValueExpression)expr;
        }
        ValueExpression valueEx = new ValueExpression( expr, expr.stringValue( formatter ) );
        valueEx.type = expr.getDataType( formatter );
        valueEx.unit = expr.unit( formatter );
        switch( valueEx.type ) {
            case STRING:
            case BOOLEAN:
                break; //string is already set
            case LIST:
                Operation op = valueEx.op = new Operation( expr, ' ' );
                ArrayList<Expression> operants = expr.listValue( formatter ).getOperands();
                for( int j = 0; j < operants.size(); j++ ) {
                    op.addOperand( ValueExpression.eval( formatter, operants.get( j ) ) );
                }
                break;
            default:
                valueEx.value = expr.doubleValue( formatter );
        }
        return valueEx;
    }
813127
public static <T extends Comparable<?>> DateExpression<T> asDate(Expression<T> expr) {
        Expression<T> underlyingMixin = ExpressionUtils.extract(expr);
        if (underlyingMixin instanceof PathImpl) {
            return new DatePath<T>((PathImpl<T>) underlyingMixin);
        } else if (underlyingMixin instanceof OperationImpl) {
            return new DateOperation<T>((OperationImpl<T>) underlyingMixin);
        } else if (underlyingMixin instanceof TemplateExpressionImpl) {
            return new DateTemplate<T>((TemplateExpressionImpl<T>) underlyingMixin);
        } else {
            return new DateExpression<T>(underlyingMixin) {

                private static final long serialVersionUID = 389920618099394430L;

                @Override
                public <R, C> R accept(Visitor<R, C> v, C context) {
                    return this.mixin.accept(v, context);
                }

            };
        }

    }
24507
public TemplateInstanceExecution templateInstanceExecution(String sourceName, ExpressionEngine expressionEngine) {
        // Transforms each parameter in a name/value pair, using only the source name as input
        Map<String, String> sourceNameInput = Collections.singletonMap("sourceName", sourceName);
        Map<String, String> parameterMap = Maps.transformValues(
                Maps.uniqueIndex(
                        parameters,
                        TemplateParameter::getName
                ),
                parameter -> expressionEngine.render(parameter.getExpression(), sourceNameInput)
        );
        // Concatenates the maps
        Map<String, String> inputMap = new HashMap<>(sourceNameInput);
        inputMap.putAll(parameterMap);
        // Resolves the final expression
        return new TemplateInstanceExecution(
                value -> expressionEngine.render(value, inputMap),
                parameterMap
        );
    }
1084914
public static Expression compile(String exp) {
        if (Miscellaneous.isEmpty(exp) || exp.equals(".")) {
            exp = "$";
        }
        Queue<String> queue = new LinkedList<String>();
        List<String> tokens = parseTokens(exp);
        boolean isInBracket = false;
        int numInBracket = 0;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tokens.size(); i++) {
            String token = tokens.get(i);
            if (token.equals("[")) {
                if (isInBracket) {
                    throw new IllegalArgumentException("Error parsing expression '" + exp + "': Nested [ found");
                }
                isInBracket = true;
                numInBracket = 0;
                sb.append(token);
            } else if (token.equals("]")) {
                if (!isInBracket) {
                    throw new IllegalArgumentException("Error parsing expression '" + exp + "': Unbalanced ] found");
                }
                isInBracket = false;
                sb.append(token);
                queue.add(sb.toString());
                sb = new StringBuilder();
            } else {
                if (isInBracket) {
                    if (numInBracket > 0) {
                        throw new IllegalArgumentException("Error parsing expression '" + exp + "': Multiple tokens found inside a bracket");
                    }
                    sb.append(token);
                    numInBracket++;
                } else {
                    queue.add(token);
                }
            }
            if (i == tokens.size() - 1) {
                if (isInBracket) {
                    throw new IllegalArgumentException("Error parsing expression '" + exp + "': Unbalanced [ found");
                }
            }
        }
        return new Expression(queue, exp);
    }
518142
@SuppressWarnings("unchecked")
    @Deprecated
    public static <T> TemplateExpression<T> template(Class<? extends T> cl, Template template, ImmutableList<?> args) {
        if (cl.equals(Boolean.class)) {
            return (TemplateExpression<T>) new PredicateTemplate(template, args);
        } else {
            return new TemplateExpressionImpl<T>(cl, template, args);
        }
    }
1111393
public static StringExpression groupConcat(Expression<String> expr) {
        return Expressions.stringOperation(SQLOps.GROUP_CONCAT, expr);
    }