Пример #1
0
 /**
  * @param CompilationContext $compilationContext
  * @throws CompilerException
  */
 public function compile(CompilationContext $compilationContext)
 {
     $compilationContext->headersManager->add('kernel/exception');
     $codePrinter = $compilationContext->codePrinter;
     $statement = $this->_statement;
     $expr = $statement['expr'];
     /**
      * This optimizes throw new Exception("hello")
      */
     if (!$compilationContext->insideTryCatch) {
         if (isset($expr['class'])) {
             if (isset($expr['parameters']) && count($expr['parameters']) == 1) {
                 if ($expr['parameters'][0]['parameter']['type'] == 'string') {
                     $className = Utils::getFullName($expr['class'], $compilationContext->classDefinition->getNamespace(), $compilationContext->aliasManager);
                     if ($compilationContext->compiler->isClass($className)) {
                         $classDefinition = $compilationContext->compiler->getClassDefinition($className);
                         $message = $expr['parameters'][0]['parameter']['value'];
                         $codePrinter->output('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(' . $classDefinition->getClassEntry() . ', "' . Utils::addSlashes($message, true, Types::STRING) . '", "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ');');
                         $codePrinter->output('return;');
                         return;
                     } else {
                         if ($compilationContext->compiler->isInternalClass($className)) {
                             $classEntry = $compilationContext->classDefinition->getClassEntryByClassName($className, true);
                             if ($classEntry) {
                                 $message = $expr['parameters'][0]['parameter']['value'];
                                 $codePrinter->output('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(' . $classEntry . ', "' . Utils::addSlashes($message, true, Types::STRING) . '", "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ');');
                                 $codePrinter->output('return;');
                                 return;
                             }
                         }
                     }
                 }
             }
         }
     }
     $throwExpr = new Expression($expr);
     $resolvedExpr = $throwExpr->compile($compilationContext);
     if ($resolvedExpr->getType() != 'variable') {
         throw new CompilerException("Expression '" . $resolvedExpr->getType() . '" cannot be used as exception', $expr);
     }
     $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $expr);
     if ($variableVariable->getType() != 'variable') {
         throw new CompilerException("Variable '" . $variableVariable->getType() . "' cannot be used as exception", $expr);
     }
     $codePrinter->output('zephir_throw_exception_debug(' . $variableVariable->getName() . ', "' . Compiler::getShortUserPath($statement['expr']['file']) . '", ' . $statement['expr']['line'] . ' TSRMLS_CC);');
     if (!$compilationContext->insideTryCatch) {
         $codePrinter->output('ZEPHIR_MM_RESTORE();');
         $codePrinter->output('return;');
     } else {
         $codePrinter->output('goto try_end_' . $compilationContext->insideTryCatch . ';');
         $codePrinter->outputBlankLine();
     }
     if ($variableVariable->isTemporal()) {
         $variableVariable->setIdle(true);
     }
 }
Пример #2
0
 /**
  * Executes the command
  *
  * @param Config $config
  * @param Logger $logger
  */
 public function execute(Config $config, Logger $logger)
 {
     echo self::LOGO, PHP_EOL;
     echo "Zephir version ", Compiler::getCurrentVersion(), PHP_EOL, PHP_EOL;
     echo "Usage: ", PHP_EOL;
     echo "\tcommand [options]", PHP_EOL;
     echo PHP_EOL;
     echo "Available commands:", PHP_EOL;
     foreach (Bootstrap::getCommands() as $command) {
         echo sprintf("\t%-20s%s\n", $command->getUsage(), $command->getDescription());
     }
     echo PHP_EOL;
     echo "Options:", PHP_EOL;
     echo sprintf("\t%-20s%s\n", "-f([a-z0-9\\-]+)", "Enables compiler optimizations");
     echo sprintf("\t%-20s%s\n", "-fno-([a-z0-9\\-]+)", "Disables compiler optimizations");
     echo sprintf("\t%-20s%s\n", "-w([a-z0-9\\-]+)", "Turns a warning on");
     echo sprintf("\t%-20s%s\n", "-W([a-z0-9\\-]+)", "Turns a warning off");
     echo PHP_EOL;
 }
Пример #3
0
 /**
  * @param array $expression
  * @param Call $call
  * @param CompilationContext $context
  * @return bool|CompiledExpression|mixed
  */
 public function optimize(array $expression, Call $call, CompilationContext $context)
 {
     if (!isset($expression['parameters'])) {
         return false;
     }
     if (count($expression['parameters']) != 2) {
         return false;
     }
     if ($expression['parameters'][1]['parameter']['type'] == 'string') {
         $str = Utils::addSlashes($expression['parameters'][1]['parameter']['value']);
         unset($expression['parameters'][1]);
     }
     $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
     $context->headersManager->add('kernel/string');
     if (isset($str)) {
         return new CompiledExpression('bool', 'zephir_memnstr_str(' . $resolvedParams[0] . ', SL("' . $str . '"), "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ')', $expression);
     }
     return new CompiledExpression('bool', 'zephir_memnstr(' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ', "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ')', $expression);
 }
Пример #4
0
 /**
  * Compiles the file
  *
  * @param Compiler $compiler
  * @param StringsManager $stringsManager
  */
 public function compile(Compiler $compiler, StringsManager $stringsManager)
 {
     if (!$this->_ir) {
         throw new CompilerException('IR related to compiled file is missing');
     }
     /**
      * External classes should not be compiled as part of the extension
      */
     if ($this->_external) {
         return;
     }
     /**
      * Compilation context stores common objects required by compilation entities
      */
     $compilationContext = new CompilationContext();
     /**
      * Set global compiler in the compilation context
      */
     $compilationContext->compiler = $compiler;
     /**
      * Set global config in the compilation context
      */
     $compilationContext->config = $this->_config;
     /**
      * Set global logger in the compilation context
      */
     $compilationContext->logger = $this->_logger;
     /**
      * Set global strings manager
      */
     $compilationContext->stringsManager = $stringsManager;
     $compilationContext->backend = $compiler->backend;
     /**
      * Headers manager
      */
     $headersManager = new HeadersManager();
     $compilationContext->headersManager = $headersManager;
     /**
      * Main code-printer for the file
      */
     $codePrinter = new CodePrinter();
     $compilationContext->codePrinter = $codePrinter;
     /**
      * Alias manager
      */
     $compilationContext->aliasManager = $this->_aliasManager;
     $codePrinter->outputBlankLine();
     $class = false;
     $interface = false;
     foreach ($this->_ir as $topStatement) {
         switch ($topStatement['type']) {
             case 'class':
                 if ($interface || $class) {
                     throw new CompilerException("More than one class defined in the same file", $topStatement);
                 }
                 $class = true;
                 $this->compileClass($compilationContext, $this->_namespace, $topStatement);
                 break;
             case 'interface':
                 if ($interface || $class) {
                     throw new CompilerException("More than one class defined in the same file", $topStatement);
                 }
                 $class = true;
                 $this->compileClass($compilationContext, $this->_namespace, $topStatement);
                 break;
             case 'comment':
                 $this->compileComment($compilationContext, $topStatement);
                 break;
         }
     }
     /* ensure functions are handled last */
     foreach ($this->_functionDefinitions as $funcDef) {
         $this->compileFunction($compilationContext, $funcDef);
     }
     /* apply headers */
     $this->applyClassHeaders($compilationContext);
     $classDefinition = $this->_classDefinition;
     if (!$classDefinition) {
         $this->_ir = null;
         return;
     }
     $classDefinition->setOriginalNode($this->_originalNode);
     $completeName = $classDefinition->getCompleteName();
     $path = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($completeName));
     $filePath = 'ext/' . $path . '.zep.c';
     $filePathHeader = 'ext/' . $path . '.zep.h';
     if (strpos($path, DIRECTORY_SEPARATOR)) {
         $dirname = dirname($filePath);
         if (!is_dir($dirname)) {
             mkdir($dirname, 0755, true);
         }
     }
     if ($codePrinter) {
         /**
          * If the file does not exists we create it for the first time
          */
         if (!file_exists($filePath)) {
             file_put_contents($filePath, $codePrinter->getOutput());
             if ($compilationContext->headerPrinter) {
                 file_put_contents($filePathHeader, $compilationContext->headerPrinter->getOutput());
             }
         } else {
             $fileSystem = $compiler->getFileSystem();
             /**
              * Use md5 hash to avoid rewrite the file again and again when it hasn't changed
              * thus avoiding unnecessary recompilations
              */
             $output = $codePrinter->getOutput();
             $hash = $fileSystem->getHashFile('md5', $filePath, true);
             if (md5($output) != $hash) {
                 file_put_contents($filePath, $output);
             }
             if ($compilationContext->headerPrinter) {
                 $output = $compilationContext->headerPrinter->getOutput();
                 $hash = $fileSystem->getHashFile('md5', $filePathHeader, true);
                 if (md5($output) != $hash) {
                     file_put_contents($filePathHeader, $output);
                 }
             }
         }
     }
     /**
      * Add to file compiled
      */
     $this->_compiledFile = $path . '.c';
     $this->_ir = null;
 }
Пример #5
0
 public function forStatement(Variable $exprVariable, $keyVariable, $variable, $duplicateKey, $duplicateHash, $statement, $statementBlock, CompilationContext $compilationContext)
 {
     /**
      * Create a hash table and hash pointer temporary variables
      */
     //$arrayPointer = $compilationContext->symbolTable->addTemp('HashPosition', $compilationContext);
     //$arrayHash = $compilationContext->symbolTable->addTemp('HashTable', $compilationContext);
     /**
      * Create a temporary zval to fetch the items from the hash
      */
     $tempVariable = $compilationContext->symbolTable->addTemp('variable', $compilationContext);
     $tempVariable->setIsDoublePointer(true);
     $codePrinter = $compilationContext->codePrinter;
     $codePrinter->output('zephir_is_iterable(' . $this->getVariableCode($exprVariable) . ', ' . $duplicateHash . ', "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
     $macro = null;
     $reverse = $statement['reverse'] ? 'REVERSE_' : '';
     if (isset($keyVariable)) {
         $arrayNumKey = $compilationContext->symbolTable->addTemp('zend_ulong', $compilationContext);
         $arrayStrKey = $compilationContext->symbolTable->addTemp('zend_string', $compilationContext);
     }
     if (isset($keyVariable) && isset($variable)) {
         $macro = 'ZEND_HASH_' . $reverse . 'FOREACH_KEY_VAL';
         $codePrinter->output($macro . '(Z_ARRVAL_P(' . $this->getVariableCode($exprVariable) . '), ' . $arrayNumKey->getName() . ', ' . $arrayStrKey->getName() . ', ' . $tempVariable->getName() . ')');
     } else {
         if (isset($keyVariable)) {
             $macro = 'ZEND_HASH_' . $reverse . 'FOREACH_KEY';
             $codePrinter->output($macro . '(Z_ARRVAL_P(' . $this->getVariableCode($exprVariable) . '), ' . $arrayNumKey->getName() . ', ' . $arrayStrKey->getName() . ')');
         } else {
             $macro = 'ZEND_HASH_' . $reverse . 'FOREACH_VAL';
             $codePrinter->output($macro . '(Z_ARRVAL_P(' . $this->getVariableCode($exprVariable) . '), ' . $tempVariable->getName() . ')');
         }
     }
     $codePrinter->output('{');
     if (isset($keyVariable)) {
         $codePrinter->increaseLevel();
         if ($duplicateKey) {
             $compilationContext->symbolTable->mustGrownStack(true);
             $keyVariable->initVariant($compilationContext);
         }
         $codePrinter->output('if (' . $arrayStrKey->getName() . ' != NULL) { ');
         $codePrinter->increaseLevel();
         if ($duplicateKey) {
             $codePrinter->output('ZVAL_STR_COPY(' . $this->getVariableCode($keyVariable) . ', ' . $arrayStrKey->getName() . ');');
         } else {
             $codePrinter->output('ZVAL_STR(' . $this->getVariableCode($keyVariable) . ', ' . $arrayStrKey->getName() . ');');
         }
         $codePrinter->decreaseLevel();
         $codePrinter->output('} else {');
         $codePrinter->increaseLevel();
         $codePrinter->output('ZVAL_LONG(' . $this->getVariableCode($keyVariable) . ', ' . $arrayNumKey->getName() . ');');
         $codePrinter->decreaseLevel();
         $codePrinter->output('}');
         $codePrinter->decreaseLevel();
     }
     if (isset($variable)) {
         $compilationContext->symbolTable->mustGrownStack(true);
         $codePrinter->increaseLevel();
         $variable->initVariant($compilationContext);
         $codePrinter->output('ZVAL_COPY(' . $this->getVariableCode($variable) . ', ' . $this->getVariableCode($tempVariable) . ');');
         $codePrinter->decreaseLevel();
     }
     /**
      * Compile statements in the 'for' block
      */
     if (isset($statement['statements'])) {
         $statementBlock->isLoop(true);
         if (isset($statement['key'])) {
             $statementBlock->getMutateGatherer()->increaseMutations($statement['key']);
         }
         $statementBlock->getMutateGatherer()->increaseMutations($statement['value']);
         $statementBlock->compile($compilationContext);
     }
     $codePrinter->output('} ZEND_HASH_FOREACH_END();');
     /* Since we do not observe, still do cleanup */
     if (isset($variable)) {
         $variable->initVariant($compilationContext);
     }
     if (isset($keyVariable)) {
         $keyVariable->initVariant($compilationContext);
     }
 }
Пример #6
0
 /**
  * Compiles an array initialization
  *
  * @param array $expression
  * @param CompilationContext $compilationContext
  * @return CompiledExpression
  */
 public function compile($expression, CompilationContext $compilationContext)
 {
     /**
      * Resolves the symbol that expects the value
      */
     if ($this->_expecting) {
         if ($this->_expectingVariable) {
             $symbolVariable = $this->_expectingVariable;
             $symbolVariable->initVariant($compilationContext);
             if ($symbolVariable->getType() != 'variable' && $symbolVariable->getType() != 'array') {
                 throw new CompilerException("Cannot use variable type: " . $symbolVariable->getType() . " as an array", $expression);
             }
         } else {
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('array', $compilationContext, $expression);
         }
     } else {
         $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('array', $compilationContext, $expression);
     }
     /*+
      * Mark the variable as an array
      */
     $symbolVariable->setDynamicTypes('array');
     $codePrinter = $compilationContext->codePrinter;
     /**
      * This calculates a prime number bigger than the current array size to possibly
      * reduce hash collisions when adding new members to the array
      */
     $arrayLength = intval(count($expression['left']) * 1.25);
     if (!function_exists('gmp_nextprime')) {
         $codePrinter->output('array_init_size(' . $symbolVariable->getName() . ', ' . ($arrayLength + 1) . ');');
     } else {
         $codePrinter->output('array_init_size(' . $symbolVariable->getName() . ', ' . gmp_strval(gmp_nextprime($arrayLength)) . ');');
     }
     foreach ($expression['left'] as $item) {
         if (isset($item['key'])) {
             $key = null;
             $exprKey = new Expression($item['key']);
             $resolvedExprKey = $exprKey->compile($compilationContext);
             switch ($resolvedExprKey->getType()) {
                 case 'string':
                     $expr = new Expression($item['value']);
                     $resolvedExpr = $expr->compile($compilationContext);
                     switch ($resolvedExpr->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                             $codePrinter->output('add_assoc_long_ex(' . $symbolVariable->getName() . ', SS("' . $resolvedExprKey->getCode() . '"), ' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'double':
                             $codePrinter->output('add_assoc_double_ex(' . $symbolVariable->getName() . ', SS("' . $resolvedExprKey->getCode() . '"), ' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'bool':
                             $compilationContext->headersManager->add('kernel/array');
                             if ($resolvedExpr->getCode() == 'true') {
                                 $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', SL("' . $resolvedExprKey->getCode() . '"), &ZEPHIR_GLOBAL(global_true), PH_COPY | PH_SEPARATE);');
                             } else {
                                 $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', SL("' . $resolvedExprKey->getCode() . '"), &ZEPHIR_GLOBAL(global_false), PH_COPY | PH_SEPARATE);');
                             }
                             break;
                         case 'string':
                             $codePrinter->output('add_assoc_stringl_ex(' . $symbolVariable->getName() . ', SS("' . $resolvedExprKey->getCode() . '"), SL("' . $resolvedExpr->getCode() . '"), 1);');
                             break;
                         case 'null':
                             $compilationContext->headersManager->add('kernel/array');
                             $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', SL("' . $resolvedExprKey->getCode() . '"), &ZEPHIR_GLOBAL(global_null), PH_COPY | PH_SEPARATE);');
                             break;
                         case 'array':
                             $compilationContext->headersManager->add('kernel/array');
                             $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                             $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', SL("' . $resolvedExprKey->getCode() . '"), &' . $valueVariable->getName() . ', PH_COPY | PH_SEPARATE);');
                             if ($valueVariable->isTemporal()) {
                                 $valueVariable->setIdle(true);
                             }
                             break;
                         case 'variable':
                             $compilationContext->headersManager->add('kernel/array');
                             $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                             $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', SL("' . $resolvedExprKey->getCode() . '"), &' . $valueVariable->getName() . ', PH_COPY | PH_SEPARATE);');
                             if ($valueVariable->isTemporal()) {
                                 $valueVariable->setIdle(true);
                             }
                             break;
                         default:
                             throw new CompilerException("Invalid value type: " . $resolvedExpr->getType(), $item['value']);
                     }
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     $expr = new Expression($item['value']);
                     $resolvedExpr = $expr->compile($compilationContext);
                     switch ($resolvedExpr->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                             $codePrinter->output('add_index_long(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'bool':
                             $compilationContext->headersManager->add('kernel/array');
                             $codePrinter->output('add_index_bool(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                             if ($resolvedExpr->getCode() == 'true') {
                                 $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &ZEPHIR_GLOBAL(global_true), PH_COPY, "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ');');
                             } else {
                                 $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &ZEPHIR_GLOBAL(global_false), PH_COPY, "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ');');
                             }
                             break;
                         case 'double':
                             $codePrinter->output('add_index_double(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getCode() . ');');
                             break;
                         case 'null':
                             $compilationContext->headersManager->add('kernel/array');
                             $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &ZEPHIR_GLOBAL(global_null), PH_COPY, "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ');');
                             break;
                         case 'string':
                             $codePrinter->output('add_index_stringl(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', SL("' . $resolvedExpr->getCode() . '"), 1);');
                             break;
                         case 'array':
                             $compilationContext->headersManager->add('kernel/array');
                             $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                             $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &' . $valueVariable->getName() . ', PH_COPY, "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ');');
                             if ($valueVariable->isTemporal()) {
                                 $valueVariable->setIdle(true);
                             }
                             break;
                         case 'variable':
                             $compilationContext->headersManager->add('kernel/array');
                             $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                             $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &' . $valueVariable->getName() . ', PH_COPY, "' . Compiler::getShortUserPath($expression['file']) . '", ' . $expression['line'] . ');');
                             if ($valueVariable->isTemporal()) {
                                 $valueVariable->setIdle(true);
                             }
                             break;
                         default:
                             throw new CompilerException("Invalid value type: " . $item['value']['type'], $item['value']);
                     }
                     break;
                 case 'variable':
                     $variableVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExprKey->getCode(), $compilationContext, $item['key']);
                     switch ($variableVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                         case 'ulong':
                             $expr = new Expression($item['value']);
                             $resolvedExpr = $expr->compile($compilationContext);
                             switch ($resolvedExpr->getType()) {
                                 case 'int':
                                 case 'uint':
                                 case 'long':
                                 case 'ulong':
                                     $codePrinter->output('add_index_double(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getCode() . ');');
                                     break;
                                 case 'bool':
                                     $codePrinter->output('add_index_bool(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                                     break;
                                 case 'double':
                                     $codePrinter->output('add_index_double(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', ' . $resolvedExpr->getCode() . ');');
                                     break;
                                 case 'null':
                                     $codePrinter->output('add_index_null(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ');');
                                     break;
                                 case 'string':
                                     $codePrinter->output('add_index_stringl(' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', SL("' . $resolvedExpr->getCode() . '"), 1);');
                                     break;
                                 case 'variable':
                                     $compilationContext->headersManager->add('kernel/array');
                                     $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                     $codePrinter->output('zephir_array_update_long(&' . $symbolVariable->getName() . ', ' . $resolvedExprKey->getCode() . ', &' . $valueVariable->getName() . ', PH_COPY, "' . Compiler::getShortUserPath($item['file']) . '", ' . $item['line'] . ');');
                                     if ($valueVariable->isTemporal()) {
                                         $valueVariable->setIdle(true);
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Invalid value type: " . $item['value']['type'], $item['value']);
                             }
                             break;
                         case 'string':
                             $expr = new Expression($item['value']);
                             $resolvedExpr = $expr->compile($compilationContext);
                             switch ($resolvedExpr->getType()) {
                                 case 'int':
                                 case 'uint':
                                 case 'long':
                                 case 'ulong':
                                     $codePrinter->output('add_assoc_long_ex(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . '), ' . $resolvedExpr->getCode() . ');');
                                     break;
                                 case 'double':
                                     $codePrinter->output('add_assoc_double_ex(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . '), ' . $resolvedExpr->getCode() . ');');
                                     break;
                                 case 'bool':
                                     $codePrinter->output('add_assoc_bool_ex(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . '), ' . $resolvedExpr->getBooleanCode() . ');');
                                     break;
                                 case 'string':
                                     $codePrinter->output('add_assoc_stringl_ex(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . ') + 1, SL("' . $resolvedExpr->getCode() . '"), 1);');
                                     break;
                                 case 'null':
                                     $codePrinter->output('add_assoc_null_ex(' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . ') + 1);');
                                     break;
                                 case 'variable':
                                     $compilationContext->headersManager->add('kernel/array');
                                     $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                     $codePrinter->output('zephir_array_update_string(&' . $symbolVariable->getName() . ', Z_STRVAL_P(' . $resolvedExprKey->getCode() . '), Z_STRLEN_P(' . $item['key']['value'] . '), &' . $valueVariable->getName() . ', PH_COPY);');
                                     if ($valueVariable->isTemporal()) {
                                         $valueVariable->setIdle(true);
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Invalid value type: " . $resolvedExpr->getType(), $item['value']);
                             }
                             break;
                         case 'variable':
                             $expr = new Expression($item['value']);
                             $resolvedExpr = $expr->compile($compilationContext);
                             switch ($resolvedExpr->getType()) {
                                 case 'null':
                                 case 'bool':
                                     $compilationContext->headersManager->add('kernel/array');
                                     $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                     $codePrinter->output('zephir_array_update_zval(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', &' . $valueVariable->getName() . ', PH_COPY);');
                                     if ($valueVariable->isTemporal()) {
                                         $valueVariable->setIdle(true);
                                     }
                                     break;
                                 case 'variable':
                                     $compilationContext->headersManager->add('kernel/array');
                                     $valueVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
                                     $codePrinter->output('zephir_array_update_zval(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', &' . $valueVariable->getName() . ', PH_COPY);');
                                     if ($valueVariable->isTemporal()) {
                                         $valueVariable->setIdle(true);
                                     }
                                     break;
                                 default:
                                     throw new CompilerException("Invalid value type: " . $item['value']['type'], $item['value']);
                             }
                             break;
                         default:
                             throw new CompilerException("Cannot use variable type: " . $variableVariable->getType() . " as array index", $item['key']);
                     }
                     break;
                 default:
                     throw new CompilerException("Invalid key type: " . $resolvedExprKey->getType(), $item['key']);
             }
         } else {
             $expr = new Expression($item['value']);
             $resolvedExpr = $expr->compile($compilationContext);
             $itemVariable = $this->getArrayValue($resolvedExpr, $compilationContext);
             $compilationContext->headersManager->add('kernel/array');
             $codePrinter->output('zephir_array_fast_append(' . $symbolVariable->getName() . ', ' . $itemVariable->getName() . ');');
             if ($itemVariable->isTemporal()) {
                 $itemVariable->setIdle(true);
             }
         }
     }
     return new CompiledExpression('array', $symbolVariable->getRealName(), $expression);
 }
Пример #7
0
 public function forStatement(Variable $exprVariable, $keyVariable, $variable, $duplicateKey, $duplicateHash, $statement, $statementBlock, CompilationContext $compilationContext)
 {
     /**
      * Create a hash table and hash pointer temporary variables
      */
     $arrayPointer = $compilationContext->symbolTable->addTemp('HashPosition', $compilationContext);
     $arrayHash = $compilationContext->symbolTable->addTemp('HashTable', $compilationContext);
     /**
      * Create a temporary zval to fetch the items from the hash
      */
     $tempVariable = $compilationContext->symbolTable->addTemp('variable', $compilationContext);
     $tempVariable->setIsDoublePointer(true);
     $codePrinter = $compilationContext->codePrinter;
     $reverse = $statement['reverse'] ? 1 : 0;
     $codePrinter->output('zephir_is_iterable(' . $this->getVariableCode($exprVariable) . ', &' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ', ' . $duplicateHash . ', ' . $reverse . ', "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
     $codePrinter->output('for (');
     $codePrinter->output('  ; zephir_hash_get_current_data_ex(' . $arrayHash->getName() . ', (void**) &' . $tempVariable->getName() . ', &' . $arrayPointer->getName() . ') == SUCCESS');
     if ($reverse) {
         $codePrinter->output('  ; zephir_hash_move_backwards_ex(' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ')');
     } else {
         $codePrinter->output('  ; zephir_hash_move_forward_ex(' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ')');
     }
     $codePrinter->output(') {');
     if (isset($keyVariable)) {
         if ($duplicateKey) {
             $compilationContext->symbolTable->mustGrownStack(true);
             $codePrinter->output("\t" . 'ZEPHIR_GET_HMKEY(' . $keyVariable->getName() . ', ' . $arrayHash->getName() . ', ' . $arrayPointer->getName() . ');');
         } else {
             $codePrinter->output("\t" . 'ZEPHIR_GET_HKEY(' . $keyVariable->getName() . ', ' . $arrayHash->getName() . ', ' . $arrayPointer->getName() . ');');
         }
     }
     if (isset($variable)) {
         $compilationContext->symbolTable->mustGrownStack(true);
         $codePrinter->output("\t" . 'ZEPHIR_GET_HVALUE(' . $variable->getName() . ', ' . $tempVariable->getName() . ');');
     }
     /**
      * Compile statements in the 'for' block
      */
     if (isset($statement['statements'])) {
         $statementBlock->isLoop(true);
         if (isset($statement['key'])) {
             $statementBlock->getMutateGatherer()->increaseMutations($statement['key']);
         }
         $statementBlock->getMutateGatherer()->increaseMutations($statement['value']);
         $statementBlock->compile($compilationContext);
     }
     $codePrinter->output('}');
     /* Make sure to free the duplicated hash table */
     if ($duplicateHash) {
         $codePrinter->output('zend_hash_destroy(' . $arrayHash->getName() . ');');
         $codePrinter->output('FREE_HASHTABLE(' . $arrayHash->getName() . ');');
     }
 }
Пример #8
0
 /**
  * @param array $expression
  * @param Variable $variableVariable
  * @param CompilationContext $compilationContext
  */
 protected function _accessDimensionArray($expression, Variable $variableVariable, CompilationContext $compilationContext)
 {
     $arrayAccess = $expression;
     if ($variableVariable->getType() == 'variable') {
         if ($variableVariable->hasAnyDynamicType('unknown')) {
             throw new CompilerException("Cannot use non-initialized variable as an array", $arrayAccess['left']);
         }
         /**
          * Trying to use a non-object dynamic variable as object
          */
         if ($variableVariable->hasDifferentDynamicType(array('undefined', 'array', 'null'))) {
             $compilationContext->logger->warning('Possible attempt to access array-index on a non-array dynamic variable', 'non-array-access', $arrayAccess['left']);
         }
     }
     $codePrinter = $compilationContext->codePrinter;
     /**
      * Resolves the symbol that expects the value
      */
     $readOnly = false;
     $symbolVariable = $this->_expectingVariable;
     if ($this->_readOnly) {
         if ($this->_expecting && $this->_expectingVariable) {
             /**
              * If a variable is assigned once in the method, we try to promote it
              * to a read only variable
              */
             if ($symbolVariable->getName() != 'return_value') {
                 $line = $compilationContext->symbolTable->getLastCallLine();
                 if ($line === false || $line > 0 && $line < $expression['line']) {
                     $numberMutations = $compilationContext->symbolTable->getExpectedMutations($symbolVariable->getName());
                     if ($numberMutations == 1) {
                         if ($symbolVariable->getNumberMutations() == $numberMutations) {
                             $symbolVariable->setMemoryTracked(false);
                             $readOnly = true;
                         }
                     }
                 }
             }
             /**
              * Variable is not read-only or it wasn't promoted
              */
             if (!$readOnly) {
                 if ($symbolVariable->getName() != 'return_value') {
                     $symbolVariable->observeVariant($compilationContext);
                     $this->_readOnly = false;
                 } else {
                     $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedUninitializedVariable('variable', $compilationContext, $expression);
                 }
             }
         } else {
             $symbolVariable = $compilationContext->symbolTable->getTempNonTrackedUninitializedVariable('variable', $compilationContext, $expression);
         }
     } else {
         if ($this->_expecting && $this->_expectingVariable) {
             /**
              * If a variable is assigned once in the method, we try to promote it
              * to a read only variable
              */
             if ($symbolVariable->getName() != 'return_value') {
                 $line = $compilationContext->symbolTable->getLastCallLine();
                 if ($line === false || $line > 0 && $line < $expression['line']) {
                     $numberMutations = $compilationContext->symbolTable->getExpectedMutations($symbolVariable->getName());
                     if ($numberMutations == 1) {
                         if ($symbolVariable->getNumberMutations() == $numberMutations) {
                             $symbolVariable->setMemoryTracked(false);
                             $readOnly = true;
                         }
                     }
                 }
             }
             /**
              * Variable is not read-only or it wasn't promoted
              */
             if (!$readOnly) {
                 if ($symbolVariable->getName() != 'return_value') {
                     $symbolVariable->observeVariant($compilationContext);
                     $this->_readOnly = false;
                 } else {
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
                 }
             }
         } else {
             $symbolVariable = $compilationContext->symbolTable->getTempVariableForObserve('variable', $compilationContext, $expression);
         }
     }
     /**
      * Variable that receives property accesses must be polimorphic
      */
     if ($symbolVariable->getType() != 'variable') {
         throw new CompilerException("Cannot use variable: " . $symbolVariable->getType() . " to assign array index", $expression);
     }
     /**
      * At this point, we don't know the type fetched from the index
      */
     $symbolVariable->setDynamicTypes('undefined');
     if ($this->_readOnly || $readOnly) {
         if ($this->_noisy) {
             $flags = 'PH_NOISY | PH_READONLY';
         } else {
             $flags = 'PH_READONLY';
         }
     } else {
         if ($this->_noisy) {
             $flags = 'PH_NOISY';
         } else {
             $flags = '0';
         }
     }
     /**
      * Right part of expression is the index
      */
     $expr = new Expression($arrayAccess['right']);
     $exprIndex = $expr->compile($compilationContext);
     switch ($exprIndex->getType()) {
         case 'int':
         case 'uint':
         case 'long':
             $compilationContext->headersManager->add('kernel/array');
             $codePrinter->output('zephir_array_fetch_long(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', ' . $exprIndex->getCode() . ', ' . $flags . ', "' . Compiler::getShortUserPath($arrayAccess['file']) . '", ' . $arrayAccess['line'] . ' TSRMLS_CC);');
             break;
         case 'string':
             $compilationContext->headersManager->add('kernel/array');
             $codePrinter->output('zephir_array_fetch_string(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', SL("' . $exprIndex->getCode() . '"), ' . $flags . ', "' . Compiler::getShortUserPath($arrayAccess['file']) . '", ' . $arrayAccess['line'] . ' TSRMLS_CC);');
             break;
         case 'variable':
             $variableIndex = $compilationContext->symbolTable->getVariableForRead($exprIndex->getCode(), $compilationContext, $expression);
             switch ($variableIndex->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                     $compilationContext->headersManager->add('kernel/array');
                     $codePrinter->output('zephir_array_fetch_long(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', ' . $variableIndex->getName() . ', ' . $flags . ', "' . Compiler::getShortUserPath($arrayAccess['file']) . '", ' . $arrayAccess['line'] . ' TSRMLS_CC);');
                     break;
                 case 'string':
                 case 'variable':
                     $compilationContext->headersManager->add('kernel/array');
                     if ($variableIndex->isLocalOnly()) {
                         $codePrinter->output('zephir_array_fetch(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', &' . $variableIndex->getName() . ', ' . $flags . ', "' . Compiler::getShortUserPath($arrayAccess['file']) . '", ' . $arrayAccess['line'] . ' TSRMLS_CC);');
                     } else {
                         $codePrinter->output('zephir_array_fetch(&' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', ' . $variableIndex->getName() . ', ' . $flags . ', "' . Compiler::getShortUserPath($arrayAccess['file']) . '", ' . $arrayAccess['line'] . ' TSRMLS_CC);');
                     }
                     break;
                 default:
                     throw new CompilerException("Variable type: " . $variableIndex->getType() . " cannot be used as array index without cast", $arrayAccess['right']);
             }
             break;
         default:
             throw new CompilerException("Cannot use expression: " . $exprIndex->getType() . " as array index without cast", $arrayAccess['right']);
     }
     return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
 }
Пример #9
0
 /**
  * Compiles traversing of hash values
  * - Evaluated expression must be a zval
  * - Every key must be a zval
  * - Every value must be a zval
  *
  * @param array $expression
  * @param CompilationContext $compilationContext
  * @param Variable $exprVariable
  */
 public function compileHashTraverse($expression, $compilationContext, $exprVariable)
 {
     $codePrinter = $compilationContext->codePrinter;
     /**
      * Initialize 'key' variable
      */
     if (isset($this->_statement['key'])) {
         $keyVariable = $compilationContext->symbolTable->getVariableForWrite($this->_statement['key'], $compilationContext, $this->_statement['expr']);
         if ($keyVariable->getType() != 'variable') {
             throw new CompilerException("Cannot use variable: " . $this->_statement['key'] . " type: " . $keyVariable->getType() . " as key in hash traversal", $this->_statement['expr']);
         }
         $keyVariable->setMustInitNull(true);
         $keyVariable->setIsInitialized(true, $compilationContext, $this->_statement);
         $keyVariable->setDynamicTypes('undefined');
     }
     /**
      * Initialize 'value' variable
      */
     if (isset($this->_statement['value'])) {
         $variable = $compilationContext->symbolTable->getVariableForWrite($this->_statement['value'], $compilationContext, $this->_statement['expr']);
         if ($variable->getType() != 'variable') {
             throw new CompilerException("Cannot use variable: " . $this->_statement['value'] . " type: " . $variable->getType() . " as value in hash traversal", $this->_statement['expr']);
         }
         $variable->setMustInitNull(true);
         $variable->setIsInitialized(true, $compilationContext, $this->_statement);
         $variable->setDynamicTypes('undefined');
     }
     /**
      * Variables are initialized in a different way inside cycle
      */
     $compilationContext->insideCycle++;
     /**
      * Create a hash table and hash pointer temporary variables
      */
     $arrayPointer = $compilationContext->symbolTable->addTemp('HashPosition', $compilationContext);
     $arrayHash = $compilationContext->symbolTable->addTemp('HashTable', $compilationContext);
     /**
      * Create a temporary zval to fetch the items from the hash
      */
     $tempVariable = $compilationContext->symbolTable->addTemp('variable', $compilationContext);
     $tempVariable->setIsDoublePointer(true);
     $compilationContext->headersManager->add('kernel/hash');
     /**
      * We have to check if hashes are modified within the for's block
      */
     $duplicateHash = '0';
     if (isset($this->_statement['statements'])) {
         $detector = new ForValueUseDetector();
         if ($detector->detect($exprVariable->getName(), $this->_statement['statements'])) {
             $duplicateHash = '1';
         }
     }
     $codePrinter->output('zephir_is_iterable(' . $expression->getCode() . ', &' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ', ' . $duplicateHash . ', ' . $this->_statement['reverse'] . ', "' . Compiler::getShortUserPath($this->_statement['file']) . '", ' . $this->_statement['line'] . ');');
     $codePrinter->output('for (');
     $codePrinter->output('  ; zephir_hash_get_current_data_ex(' . $arrayHash->getName() . ', (void**) &' . $tempVariable->getName() . ', &' . $arrayPointer->getName() . ') == SUCCESS');
     if ($this->_statement['reverse']) {
         $codePrinter->output('  ; zephir_hash_move_backwards_ex(' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ')');
     } else {
         $codePrinter->output('  ; zephir_hash_move_forward_ex(' . $arrayHash->getName() . ', &' . $arrayPointer->getName() . ')');
     }
     $codePrinter->output(') {');
     if (isset($this->_statement['key'])) {
         $compilationContext->symbolTable->mustGrownStack(true);
         $codePrinter->output("\t" . 'ZEPHIR_GET_HMKEY(' . $this->_statement['key'] . ', ' . $arrayHash->getName() . ', ' . $arrayPointer->getName() . ');');
     }
     if (isset($this->_statement['value'])) {
         $compilationContext->symbolTable->mustGrownStack(true);
         $codePrinter->output("\t" . 'ZEPHIR_GET_HVALUE(' . $this->_statement['value'] . ', ' . $tempVariable->getName() . ');');
     }
     /**
      * Compile statements in the 'for' block
      */
     if (isset($this->_statement['statements'])) {
         $st = new StatementsBlock($this->_statement['statements']);
         $st->compile($compilationContext);
     }
     /**
      * Restore the cycle counter
      */
     $compilationContext->insideCycle--;
     $codePrinter->output('}');
 }
Пример #10
0
 /**
  * Compiles foo[y] = {expr} (one offset)
  *
  * @param string $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param array $statement
  */
 protected function _assignArrayIndexSingle($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
 {
     $expression = new Expression($statement['index-expr'][0]);
     $exprIndex = $expression->compile($compilationContext);
     switch ($exprIndex->getType()) {
         case 'int':
         case 'uint':
         case 'long':
         case 'ulong':
         case 'string':
         case 'variable':
             break;
         default:
             throw new CompilerException("Index: " . $exprIndex->getType() . " cannot be used as array offset in assignment without cast", $statement['index-expr'][0]);
     }
     $codePrinter = $compilationContext->codePrinter;
     /**
      * Create a temporal zval (if needed)
      */
     $symbolVariable = $this->_getResolvedArrayItem($resolvedExpr, $compilationContext);
     $flags = 'PH_COPY | PH_SEPARATE';
     $isGlobalVariable = $compilationContext->symbolTable->isSuperGlobal($variable);
     $compilationContext->headersManager->add('kernel/array');
     if ($isGlobalVariable) {
         $variableTempSeparated = $compilationContext->symbolTable->getTempLocalVariableForWrite('int', $compilationContext);
         $codePrinter->output($variableTempSeparated->getName() . ' = zephir_maybe_separate_zval(&' . $variable . ');');
     }
     switch ($exprIndex->getType()) {
         case 'int':
         case 'uint':
         case 'long':
         case 'ulong':
             $codePrinter->output('zephir_array_update_long(&' . $variable . ', ' . $exprIndex->getCode() . ', &' . $symbolVariable->getName() . ', ' . $flags . ', "' . Compiler::getShortUserPath($statement['index-expr'][0]['file']) . '", ' . $statement['index-expr'][0]['line'] . ');');
             break;
         case 'string':
             $codePrinter->output('zephir_array_update_string(&' . $variable . ', SL("' . $exprIndex->getCode() . '"), &' . $symbolVariable->getName() . ', ' . $flags . ');');
             break;
         case 'variable':
             $variableIndex = $compilationContext->symbolTable->getVariableForRead($exprIndex->getCode(), $compilationContext, $statement);
             $variableIndexName = ($variableIndex->isLocalOnly() ? '&' : '') . $variableIndex->getName();
             switch ($variableIndex->getType()) {
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'ulong':
                     $codePrinter->output('zephir_array_update_long(&' . $variable . ', ' . $variableIndexName . ', &' . $symbolVariable->getName() . ', ' . $flags . ', "' . Compiler::getShortUserPath($statement['index-expr'][0]['file']) . '", ' . $statement['index-expr'][0]['line'] . ');');
                     break;
                 case 'string':
                     $codePrinter->output('zephir_array_update_zval(&' . $variable . ', ' . $variableIndexName . ', &' . $symbolVariable->getName() . ', ' . $flags . ');');
                     break;
                 case 'variable':
                     $codePrinter->output('zephir_array_update_zval(&' . $variable . ', ' . $variableIndexName . ', &' . $symbolVariable->getName() . ', ' . $flags . ');');
                     break;
                 default:
                     throw new CompilerException("Variable: " . $variableIndex->getType() . " cannot be used as array index", $statement);
             }
             break;
         default:
             throw new CompilerException("Value: " . $exprIndex->getType() . " cannot be used as array index", $statement);
     }
     if ($isGlobalVariable) {
         $codePrinter->output('if (' . $variableTempSeparated->getName() . ') {');
         $codePrinter->output("\t" . 'ZEND_SET_SYMBOL(&EG(symbol_table), "' . $variable . '", ' . $variable . ');');
         $codePrinter->output('}');
     }
 }
Пример #11
0
 /**
  * Compiles foo[] = {expr}
  *
  * @param $variable
  * @param ZephirVariable $symbolVariable
  * @param CompiledExpression $resolvedExpr
  * @param CompilationContext $compilationContext
  * @param $statement
  * @throws CompilerException
  */
 public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, $statement)
 {
     if (!$symbolVariable->isInitialized()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is not initialized", $statement);
     }
     if ($symbolVariable->isReadOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is read only", $statement);
     }
     if ($symbolVariable->isLocalOnly()) {
         throw new CompilerException("Cannot mutate variable '" . $variable . "' because it is local only", $statement);
     }
     if ($symbolVariable->getType() != 'variable') {
         throw new CompilerException("Cannot use variable type: '" . $symbolVariable->getType() . "' as array", $statement);
     }
     if ($symbolVariable->hasDifferentDynamicType(array('undefined', 'array'))) {
         $compilationContext->logger->warning('Possible attempt to append elements on a non-array dynamic variable', 'non-array-append', $statement);
     }
     $codePrinter = $compilationContext->codePrinter;
     $compilationContext->headersManager->add('kernel/array');
     $type = $symbolVariable->getType();
     switch ($type) {
         case 'variable':
             switch ($resolvedExpr->getType()) {
                 case 'null':
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ZEPHIR_GLOBAL(global_null), PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     break;
                 case 'int':
                 case 'uint':
                 case 'long':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'double':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'bool':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $resolvedExpr->getBooleanCode() . ');');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'ulong':
                 case 'string':
                     $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                     $codePrinter->output('ZVAL_STRING(' . $symbolVariable->getName() . ', "' . Utils::addSlashes($resolvedExpr->getCode(), true) . '", 1);');
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     $symbolVariable->setIdle(true);
                     break;
                 case 'array':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                     break;
                 case 'variable':
                     $exprVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $statement);
                     switch ($exprVariable->getType()) {
                         case 'int':
                         case 'uint':
                         case 'long':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_LONG(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'double':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_DOUBLE(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'bool':
                             $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $statement);
                             $codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getName() . ', ' . $exprVariable->getName() . ');');
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $symbolVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             $symbolVariable->setIdle(true);
                             break;
                         case 'variable':
                         case 'string':
                         case 'array':
                             $codePrinter->output('zephir_array_append(&' . $variable . ', ' . $exprVariable->getName() . ', PH_SEPARATE, "' . Compiler::getShortUserPath($statement['file']) . '", ' . $statement['line'] . ');');
                             break;
                         default:
                             throw new CompilerException("Unknown type " . $exprVariable->getType(), $statement);
                     }
                     break;
                 default:
                     throw new CompilerException("Unknown type " . $resolvedExpr->getType(), $statement);
             }
             break;
         default:
             throw new CompilerException("Unknown type", $statement);
     }
 }
Пример #12
0
 /**
  * Throws an exception escaping the data
  *
  * @param CodePrinter $printer
  * @param string $class
  * @param string $message
  * @param array $expression
  */
 private function throwStringException(CodePrinter $printer, $class, $message, $expression)
 {
     $message = Utils::addSlashes($message);
     $path = Compiler::getShortUserPath($expression['file']);
     $printer->output(sprintf('ZEPHIR_THROW_EXCEPTION_DEBUG_STR(%s, "%s", "%s", %s);', $class, $message, $path, $expression['line']));
     $printer->output('return;');
 }
Пример #13
0
 /**
  * Returns the class definition related to the extended class
  *
  * @return ClassDefinition
  */
 public function getExtendsClassDefinition()
 {
     if (!$this->extendsClassDefinition && $this->extendsClass) {
         if ($this->compiler) {
             $this->setExtendsClassDefinition($this->compiler->getClassDefinition($this->extendsClass));
         }
     }
     return $this->extendsClassDefinition;
 }
Пример #14
0
 /**
  * This function does not perform operations in the temporary
  * directory but it caches the results to avoid reprocessing
  *
  * @param string $algorithm
  * @param string $path
  * @param boolean $cache
  * @return string
  */
 public function getHashFile($algorithm, $path, $cache = false)
 {
     if ($cache == false) {
         return hash_file($algorithm, $path);
     } else {
         $changed = false;
         $cacheFile = $this->basePath . Compiler::getCurrentVersion() . DIRECTORY_SEPARATOR . str_replace(array(DIRECTORY_SEPARATOR, ':', '/'), '_', $path) . '.md5';
         if (!file_exists($cacheFile)) {
             $hash = hash_file($algorithm, $path);
             file_put_contents($cacheFile, $hash);
             $changed = true;
         } else {
             if (filemtime($path) > filemtime($cacheFile)) {
                 $hash = hash_file($algorithm, $path);
                 file_put_contents($cacheFile, $hash);
                 $changed = true;
             }
         }
         if (!$changed) {
             return file_get_contents($cacheFile);
         }
         return $hash;
     }
 }
Пример #15
0
 /**
  * Executes the command
  * @param Config $config
  * @param Logger $logger
  */
 public function execute(Config $config, Logger $logger)
 {
     echo Compiler::getCurrentVersion(), PHP_EOL;
 }