Compile the extends statements into valid PHP.

@param  string  $expression
@return string
7664
protected function compileExtends($expression)
    {
        $expression = $this->stripParentheses($expression);

        $data = "<?php echo \$__env->make($expression, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";

        $this->footer[] = $data;

        return '';
    }
633721
public function compile($expression, CompilationContext $compilationContext)
    {
        $className = $expression['left']['value'];
        $compiler = $compilationContext->compiler;
        $property = $expression['right']['value'];

        /*
         * Fetch the class definition according to the class where the constant
         * is supposed to be declared
         */
        if (!\in_array($className, ['self', 'static', 'parent'])) {
            $className = $compilationContext->getFullName($className);
            if ($compiler->isClass($className)) {
                $classDefinition = $compiler->getClassDefinition($className);
            } else {
                if ($compiler->isBundledClass($className)) {
                    $classDefinition = $compiler->getInternalClassDefinition($className);
                } else {
                    throw new CompilerException("Cannot locate class '".$className."'", $expression['left']);
                }
            }
        } else {
            if (\in_array($className, ['self', 'static'])) {
                $classDefinition = $compilationContext->classDefinition;
            } else {
                if ('parent' == $className) {
                    $classDefinition = $compilationContext->classDefinition;
                    $extendsClass = $classDefinition->getExtendsClass();
                    if (!$extendsClass) {
                        throw new CompilerException('Cannot access static property "'.$property.'" on parent because class '.$classDefinition->getCompleteName().' does not extend any class', $expression);
                    } else {
                        $classDefinition = $classDefinition->getExtendsClassDefinition();
                    }
                }
            }
        }

        if (!$classDefinition->hasProperty($property)) {
            throw new CompilerException("Class '".$classDefinition->getCompleteName()."' does not have a property called: '".$property."'", $expression);
        }

        /** @var ClassProperty $propertyDefinition */
        $propertyDefinition = $classDefinition->getProperty($property);
        if (!$propertyDefinition->isStatic()) {
            throw new CompilerException("Cannot access non-static property '".$classDefinition->getCompleteName().'::'.$property."'", $expression);
        }

        if ($propertyDefinition->isPrivate()) {
            if ($classDefinition != $compilationContext->classDefinition) {
                throw new CompilerException("Cannot access private static property '".$classDefinition->getCompleteName().'::'.$property."' out of its declaring context", $expression);
            }
        }

        if ($propertyDefinition->isProtected()) {
            if ($classDefinition != $compilationContext->classDefinition && $classDefinition != $compilationContext->classDefinition->getExtendsClassDefinition()) {
                throw new CompilerException("Cannot access protected static property '".$classDefinition->getCompleteName().'::'.$property."' out of its declaring context", $expression);
            }
        }

        /*
         * Resolves the symbol that expects the value
         */
        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;
                if ('return_value' == $symbolVariable->getName()) {
                    $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
            }
        } else {
            $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedVariable('variable', $compilationContext);
        }

        /*
         * Variable that receives property accesses must be polymorphic
         */
        if (!$symbolVariable->isVariable()) {
            throw new CompilerException('Cannot use variable: '.$symbolVariable->getType().' to assign class constants', $expression);
        }

        $symbolVariable->setDynamicTypes('undefined');

        $compilationContext->headersManager->add('kernel/object');

        $readOnly = $this->readOnly;
        if (!$readOnly) {
            if ('return_value' != $symbolVariable->getName()) {
                $symbolVariable->observeVariant($compilationContext);
            }
        }
        $compilationContext->backend->fetchStaticProperty($symbolVariable, $classDefinition, $property, $this->readOnly, $compilationContext);

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
313008
private static function buildRegex(string $expression, bool $is_prefix = false) : string
    {
        $regex  = self::REGEX_DELIMITER . '^';
        $regex .= preg_replace(array_keys(self::$datatypes), self::$datatypes, $expression);
        $regex .= $is_prefix ? '(.*)' : '';
        $regex .= '$' . self::REGEX_DELIMITER;
        return $regex;
    }
1054947
protected function compileEcho($expression)
    {
        $regex = sprintf(
            '/((?:%s\s*(.+?)\s*%s))+/',
            $this->echo_tags[0],
            $this->echo_tags[1]
        );

        $output = preg_replace_callback($regex, function ($match) {
            array_shift($match);

            return '<?php echo htmlspecialchars('.$match[1].', ENT_QUOTES); ?>';
        }, $expression);

        return $output == $expression ? '' : $output;
    }
1257686
protected function compileCustomDirective($expression)
    {
        $output = preg_replace_callback($this->getCustomDirectivePartern(), function ($match) {
            $name = $match[1];

            if (!isset($this->directives[$name])) {
                return null;
            }

            $directive = $this->directives[$name];

            if ($directive['broken']) {
                return $this->_____executeCustomDirectory(
                    $name,
                    isset($match[3]) ? $match[3] : null
                );
            }

            $params = isset($match[3]) ? $match[3] : 'null';

            return "<?php echo \$__tintin->getCompiler()->_____executeCustomDirectory(\"$name\", $params);";
        }, $expression);
        
        return is_null($output) ? $expression : $output;
    }
1045219
protected function compileExtendsStack($expression)
    {
        foreach (['Block', 'EndBlock', 'Include', 'Inject', 'Extends'] as $token) {
            $out = $this->{'compile'.$token}($expression);

            if (strlen($out) !== 0) {
                $expression = $out;
            }
        }

        return $expression;
    }
1314535
private function compileStatements($expr)
    {
        $pattern = '/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x';

        return preg_replace_callback($pattern, function ($match) {
            if (strpos($match[1], '@') !== false) {
                return substr($match[0], 1); // The expression begins with "@@". Don't compile the this part!
            }

            $method = 'compile' . ucfirst($match[1]);
            if (!method_exists($this, $method)) {
                return $match[0]; // The statement is not defined. Skip it!
            }

            if (isset($match[3])) {
                // e.g. @if (true)
                $result = $this->$method($match[3]); // $match[3] is the argument with parentheses; $match[4] is the argument without parentheses
            }
            else {
                // e.g. @endif
                $result = $this->$method(null) . $match[2]; // match[2] is the space between the statement and parentheses
            }

            return $result;
        }, $expr);
    }
757376
protected function compileInclude($expression)
    {
        $regex = "/\#include\s*\(((?:\n|\s|\t)*(?:.+?)(?:\n|\s|\t)*)\)/sm";

        $output = preg_replace_callback($regex, function ($match) {
            return "<?php echo \$__tintin->getStackManager()->includeFile({$match[1]}, ['__tintin' => \$__tintin]); ?>";
        }, $expression);

        return $output == $expression ? '' : $output;
    }
1360000
protected function compileInject($expression) {
        $segments = explode(',', preg_replace("/[\(\)\\\"\']/", '', $expression));

        return '<?php $'.trim($segments[0])." = app('".trim($segments[1])."'); ?>";
    }
146703
public function stripParentheses($expression)
    {
        if (Str::startsWith($expression, '(') && Str::endsWith($expression, ')')) {
            $expression = substr($expression, 1, -1);
        }

        return $expression;
    }
1212011
static private function translate ($expression)
  {
    list ($main, $op) = self::translateSimpleExpression ($expression);

    $exp = $main;
    if ($op == '|') {
      $filters = preg_split (self::PARSE_FILTER, $expression);
      if ($filters)
        foreach ($filters as $filter)
          $exp = self::translateFilter ($filter, $exp);
    }

    return $exp;
  }
1317923
public function compile($expression, CompilationContext $compilationContext)
    {
        $propertyAccess = $expression;

        $expr = new Expression($propertyAccess['left']);
        $exprVariable = $expr->compile($compilationContext);

        switch ($exprVariable->getType()) {
            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead($exprVariable->getCode(), $compilationContext, $expression);
                switch ($variableVariable->getType()) {
                    case 'variable':
                        break;
                    default:
                        throw new CompilerException('Variable type: '.$variableVariable->getType().' cannot be used as object', $propertyAccess['left']);
                }
                break;
            default:
                throw new CompilerException('Cannot use expression: '.$exprVariable->getType().' as an object', $propertyAccess['left']);
        }

        switch ($propertyAccess['right']['type']) {
            case 'variable':
                $propertyVariable = $compilationContext->symbolTable->getVariableForRead($propertyAccess['right']['value'], $compilationContext, $expression);
                break;
            case 'string':
                $propertyVariable = null;
                break;
            default:
                throw new CompilerException('Variable type: '.$propertyAccess['right']['type'].' cannot be used as object', $propertyAccess['left']);
        }

        /*
         * Resolves the symbol that expects the value
         */
        if ($this->expecting) {
            if ($this->expectingVariable) {
                $symbolVariable = $this->expectingVariable;
                if ('return_value' != $symbolVariable->getName()) {
                    $symbolVariable->observeVariant($compilationContext);
                } else {
                    $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
                }
            } else {
                $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
            }
        }

        /*
         * Variable that receives a property value must be polymorphic
         */
        if ($symbolVariable && !$symbolVariable->isVariable()) {
            throw new CompilerException('Cannot use variable: '.$symbolVariable->getType().' to assign property value', $expression);
        }

        /*
         * At this point, we don't know the exact dynamic type fetched from the property
         */
        $symbolVariable->setDynamicTypes('undefined');

        $compilationContext->headersManager->add('kernel/object');

        $property = $propertyVariable ? $propertyVariable : add_slashes($expression['right']['value']);
        $compilationContext->backend->fetchProperty($symbolVariable, $variableVariable, $property, false, $compilationContext, false);

        return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
    }
956851
public function postProcessExpression(Expression $expression)
    {
        if ($this->hasHash($expression->hashCode())) {
            $alias = $this->getAlias($expression->hashCode());
            $alias = new Expr\Column($alias);
            $alias->setBuilder($this);
            $expression = new Expr\Raw(sprintf('%s AS %s', $expression->toSQL(), $alias->toSQL()));
        }
        
        return $expression;
    }
1097992
protected function compileBlock($expression)
    {
        $output = preg_replace_callback(
            "/\n*\#block\s*\((.+?)(?:,(.+?))?\)\n*/m",
            function ($match) {
                array_shift($match);

                $content = null;

                if (count($match) == 2) {
                    $content = $match[1];
                }

                if (is_null($content)) {
                    return "<?php \$__tintin->getStackManager()->startStack({$match[0]}); ?>";
                } else {
                    return "<?php \$__tintin->getStackManager()->startStack({$match[0]}, $content); ?>";
                }
            },
            $expression
        );

        return $output == $expression ? '' : $output;
    }
18440
public function getDSQLExpression($expression)
    {
        $expr = $this->expr;
        if (is_callable($expr)) {
            $c = $this->expr;
            $expr = $c($this->owner, $expression);
        }

        if (is_string($expr)) {
            // If our Model has expr() method (inherited from Persistence\SQL) then use it
            if ($this->owner->hasMethod('expr')) {
                return $this->owner->expr('([])', [$this->owner->expr($expr)]);
            }

            // Otherwise call it from expression itself
            return $expression->expr('([])', [$expression->expr($expr)]);
        }

        return $expr;
    }
243655
protected function compileExpression()
    {
        $parts = [$this->getMode()];

        foreach ($this->targetSize as $value) {

            if (is_numeric($value)) {
                $parts[] = (string) $value;
            }
        }

        foreach ($this->arguments as $i => $arg) {

            if (is_numeric($arg) || ($i === 1 and $this->isColor($arg))) {
                $parts[] = trim((string) $arg);
            }
        }

        $source = $this->source;
        $params = implode('/', $parts);
        $filter = $this->compileFilterExpression();

        return compact('source', 'params', 'filter');
    }
60436
public function compile($expression, CompilationContext $compilationContext)
    {
        /**
         * Resolve the left part of the expression.
         */
        $expr = new Expression($expression['left']);
        $expr->setReadOnly(true);
        $exprVariable = $expr->compile($compilationContext);

        /*
         * Only dynamic variables can be used as arrays
         */
        switch ($exprVariable->getType()) {
            case 'variable':
                $variableVariable = $compilationContext->symbolTable->getVariableForRead($exprVariable->getCode(), $compilationContext, $expression);
                switch ($variableVariable->getType()) {
                    case 'variable':
                    case 'array':
                    case 'string':
                        break;

                    default:
                        throw new CompilerException('Variable type: '.$variableVariable->getType().' cannot be used as array', $expression['left']);
                }
                break;

            default:
                throw new CompilerException('Cannot use expression: '.$exprVariable->getType().' as an array', $expression['left']);
        }

        /*
         * Resolve the dimension according to variable's type
         */
        switch ($variableVariable->getType()) {
            case 'variable':
                return $this->_accessDimensionArray($expression, $variableVariable, $compilationContext);

            case 'array':
                return $this->_accessDimensionArray($expression, $variableVariable, $compilationContext);

            case 'string':
                return $this->_accessStringOffset($expression, $variableVariable, $compilationContext);
        }
    }