/** * @param array $expression * @param CompilationContext $compilationContext * @param boolean $isFullString */ private function _getOptimizedConcat($expression, CompilationContext $compilationContext, &$isFullString) { $originalExpr = $expression; $isFullString = true; $parts = array(); while ($expression && isset($expression['left'])) { $parts[] = $expression['right']; if ($expression['left']['type'] == 'concat') { $expression = $expression['left']; } else { $parts[] = $expression['left']; $expression = null; } } if ($expression) { $parts[] = $expression['right']; $parts[] = $expression['left']; } $key = ''; $concatParts = array(); $parts = array_reverse($parts); foreach ($parts as $part) { $expr = new Expression($part); $expr->setStringOperation(true); switch ($part['type']) { case 'array-access': case 'property-access': $expr->setReadOnly(true); break; default: $expr->setReadOnly($this->_readOnly); break; } $compiledExpr = $expr->compile($compilationContext); switch ($compiledExpr->getType()) { case 'variable': $variable = $compilationContext->symbolTable->getVariableForRead($compiledExpr->getCode(), $compilationContext, $originalExpr); switch ($variable->getType()) { case 'variable': $key .= 'v'; $concatParts[] = $variable->getName(); $isFullString = false; break; case 'string': $key .= 'v'; $concatParts[] = $variable->getName(); break; case 'int': case 'long': $key .= 'v'; $tempVariable = $compilationContext->symbolTable->getTempLocalVariableForWrite('variable', $compilationContext, $originalExpr); $compilationContext->codePrinter->output('ZVAL_LONG(&' . $tempVariable->getName() . ', ' . $compiledExpr->getCode() . ');'); $concatParts[] = '&' . $tempVariable->getName(); break; default: throw new CompilerException("Variable type: " . $variable->getType() . " cannot be used in concat operation", $compiledExpr->getOriginal()); } break; case 'string': $key .= 's'; $concatParts[] = '"' . $compiledExpr->getCode() . '"'; break; default: throw new CompilerException("Variable type: " . $compiledExpr->getType() . " cannot be used in concat operation", $compiledExpr->getOriginal()); } } $compilationContext->stringsManager->addConcatKey($key); return array($key, join(', ', $concatParts)); }