Represents a class method
Esempio n. 1
0
 private function parseMethodParameters(ClassMethod $method)
 {
     $parameters = $method->getParameters();
     if (!$parameters) {
         return;
     }
     foreach ($method->getParameters() as $parameter) {
         if (isset($parameter['data-type'])) {
             if ($parameter['data-type'] == 'variable') {
                 $type = 'mixed';
             } else {
                 $type = $parameter['data-type'];
             }
         } elseif (isset($parameter['cast'])) {
             $type = $parameter['cast']['value'];
         } else {
             $type = 'mixed';
         }
         $this->parameters['$' . $parameter['name']] = array($type, '');
     }
 }
Esempio n. 2
0
 /**
  * @param ClassMethod $method
  * @param bool $isInterface
  * @param string $indent
  *
  * @return string
  */
 protected function buildMethod(ClassMethod $method, $isInterface, $indent)
 {
     $modifier = implode(' ', array_diff($method->getVisibility(), $this->ignoreModifiers));
     $methodParameters = $method->getParameters();
     $aliasManager = $method->getClassDefinition()->getAliasManager();
     $docBlock = new MethodDocBlock($method, $aliasManager, $indent);
     $parameters = array();
     if ($methodParameters) {
         foreach ($methodParameters->getParameters() as $parameter) {
             $paramStr = '';
             if (isset($parameter['cast'])) {
                 if ($aliasManager->isAlias($parameter['cast']['value'])) {
                     $cast = '\\' . $aliasManager->getAlias($parameter['cast']['value']);
                 } else {
                     $cast = $parameter['cast']['value'];
                 }
                 $paramStr .= $cast . ' ';
             }
             $paramStr .= '$' . $parameter['name'];
             if (isset($parameter['default'])) {
                 $paramStr .= ' = ' . $this->wrapPHPValue($parameter);
             }
             $parameters[] = $paramStr;
         }
     }
     $methodBody = $indent . $modifier . ' function ' . $method->getName() . '(' . implode(', ', $parameters) . ')';
     if ($isInterface || $method->isAbstract()) {
         $methodBody .= ';';
     } else {
         $methodBody .= ' {}';
     }
     return $docBlock . "\n" . $methodBody;
 }
Esempio n. 3
0
 /**
  * Generate internal method's based on the equivalent PHP methods,
  * allowing bypassing php userspace for internal method calls
  */
 public function setupOptimized(CompilationContext $compilationContext)
 {
     if (!$compilationContext->config->get('internal-call-transformation', 'optimizations')) {
         return;
     }
     $classDefinition = $this->getClassDefinition();
     /* Skip for closures */
     if ($this->getName() == '__invoke' || $classDefinition->isInterface()) {
         return;
     }
     if (!$this->isInternal() && !$classDefinition->isBundled()) {
         /* Not supported for now */
         if ($this->getNumberOfRequiredParameters() != $this->getNumberOfParameters()) {
             return $this;
         }
         if ($this->isConstructor()) {
             return $this;
         }
         $optimizedName = $this->getName() . '_zephir_internal_call';
         $visibility = array('internal');
         $statements = null;
         if ($this->statements) {
             $statements = new StatementsBlock(json_decode(json_encode($this->statements->getStatements()), true));
         }
         $optimizedMethod = new ClassMethod($classDefinition, $visibility, $optimizedName, $this->parameters, $statements, $this->docblock, null, $this->expression);
         $optimizedMethod->typeInference = $this->typeInference;
         $optimizedMethod->setReturnTypes($this->returnTypes);
         $classDefinition->addMethod($optimizedMethod);
     }
 }
Esempio n. 4
0
 /**
  * Returns the signature of an internal method
  */
 public function getInternalSignature(ClassMethod $method, CompilationContext $context)
 {
     if ($method->isInitializer() && !$method->isStatic()) {
         return 'static zend_object *' . $method->getName() . '(zend_class_entry *class_type TSRMLS_DC)';
     }
     if ($method->isInitializer() && $method->isStatic()) {
         return 'void ' . $method->getName() . '(TSRMLS_D)';
     }
     $signatureParameters = array();
     $parameters = $method->getParameters();
     if (is_object($parameters)) {
         foreach ($parameters->getParameters() as $parameter) {
             switch ($parameter['data-type']) {
                 case 'int':
                 case 'uint':
                 case 'long':
                 case 'double':
                 case 'bool':
                 case 'char':
                 case 'uchar':
                 case 'string':
                 case 'array':
                     $signatureParameters[] = 'zval *' . $parameter['name'] . '_param_ext';
                     break;
                 default:
                     $signatureParameters[] = 'zval *' . $parameter['name'] . '_ext ';
                     break;
             }
         }
     }
     if (count($signatureParameters)) {
         return 'void ' . $method->getInternalName() . '(int ht, zval *return_value, zval *this_ptr, int return_value_used, ' . join(', ', $signatureParameters) . ')';
     }
     return 'void ' . $method->getInternalName() . '(int ht, zval *return_value, zval *this_ptr, int return_value_used)';
 }
Esempio n. 5
0
 /**
  * Builds a class definition from reflection
  *
  * @param \ReflectionClass $class
  *
  * @return ClassDefinition
  */
 public static function buildFromReflection(\ReflectionClass $class)
 {
     $classDefinition = new ClassDefinition($class->getNamespaceName(), $class->getName());
     $methods = $class->getMethods();
     if (count($methods) > 0) {
         foreach ($methods as $method) {
             $parameters = array();
             foreach ($method->getParameters() as $row) {
                 $params = array('type' => 'parameter', 'name' => $row->getName(), 'const' => 0, 'data-type' => 'variable', 'mandatory' => !$row->isOptional());
                 if (!$params['mandatory']) {
                     try {
                         $params['default'] = $row->getDefaultValue();
                     } catch (\ReflectionException $e) {
                         // TODO: dummy default value
                         $params['default'] = true;
                     }
                 }
                 $parameters[] = $params;
             }
             $classMethod = new ClassMethod($classDefinition, array(), $method->getName(), new ClassMethodParameters($parameters));
             $classMethod->setIsStatic($method->isStatic());
             $classMethod->setIsBundled(true);
             $classDefinition->addMethod($classMethod);
         }
     }
     $constants = $class->getConstants();
     if (count($constants) > 0) {
         foreach ($constants as $constantName => $constantValue) {
             $type = self::_convertPhpConstantType(gettype($constantValue));
             $classConstant = new ClassConstant($constantName, array('value' => $constantValue, 'type' => $type), null);
             $classDefinition->addConstant($classConstant);
         }
     }
     $properties = $class->getProperties();
     if (count($properties) > 0) {
         foreach ($properties as $property) {
             $visibility = array();
             if ($property->isPublic()) {
                 $visibility[] = 'public';
             }
             if ($property->isPrivate()) {
                 $visibility[] = 'private';
             }
             if ($property->isProtected()) {
                 $visibility[] = 'protected';
             }
             if ($property->isStatic()) {
                 $visibility[] = 'static';
             }
             $classProperty = new ClassProperty($classDefinition, $visibility, $property->getName(), null, null, null);
             $classDefinition->addProperty($classProperty);
         }
     }
     $classDefinition->setIsBundled(true);
     return $classDefinition;
 }
Esempio n. 6
0
 /**
  * Calls static methods on the 'self/static' context
  *
  * @param string $context SELF / STATIC
  * @param string $methodName
  * @param array $expression
  * @param Variable $symbolVariable
  * @param boolean $mustInit
  * @param boolean $isExpecting
  * @param ClassDefinition $classDefinition
  * @param CompilationContext $compilationContext
  * @param ClassMethod $method
  */
 protected function call($context, $methodName, array $expression, $symbolVariable, $mustInit, $isExpecting, ClassDefinition $classDefinition, CompilationContext $compilationContext, ClassMethod $method)
 {
     if (!in_array($context, array('SELF', 'STATIC'))) {
         $context = 'SELF';
     }
     $codePrinter = $compilationContext->codePrinter;
     /**
      * Call static methods must grown the stack
      */
     $compilationContext->symbolTable->mustGrownStack(true);
     if ($mustInit) {
         $symbolVariable->setMustInitNull(true);
         $symbolVariable->trackVariant($compilationContext);
     }
     /**
      * Check if the  method call can have an inline cache
      */
     $methodCache = $compilationContext->cacheManager->getStaticMethodCache();
     $cachePointer = $methodCache->get($compilationContext, isset($method) ? $method : null, false);
     if (isset($expression['parameters']) && count($expression['parameters'])) {
         $params = $this->getResolvedParams($expression['parameters'], $compilationContext, $expression);
     } else {
         $params = array();
     }
     $isInternal = false;
     if (isset($method)) {
         $isInternal = $method->isInternal();
     }
     if (!$isInternal) {
         if (!count($params)) {
             if ($isExpecting) {
                 if ($symbolVariable->getName() == 'return_value') {
                     $codePrinter->output('ZEPHIR_RETURN_CALL_' . $context . '("' . $methodName . '", ' . $cachePointer . ');');
                 } else {
                     $codePrinter->output('ZEPHIR_CALL_' . $context . '(&' . $symbolVariable->getName() . ', "' . $methodName . '", ' . $cachePointer . ');');
                 }
             } else {
                 $codePrinter->output('ZEPHIR_CALL_' . $context . '(NULL, "' . $methodName . '", ' . $cachePointer . ');');
             }
         } else {
             if ($isExpecting) {
                 if ($symbolVariable->getName() == 'return_value') {
                     $codePrinter->output('ZEPHIR_RETURN_CALL_' . $context . '("' . $methodName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');');
                 } else {
                     $codePrinter->output('ZEPHIR_CALL_' . $context . '(&' . $symbolVariable->getName() . ', "' . $methodName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');');
                 }
             } else {
                 $codePrinter->output('ZEPHIR_CALL_' . $context . '(NULL, "' . $methodName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');');
             }
         }
     } else {
         if (!count($params)) {
             if ($isExpecting) {
                 if ($symbolVariable->getName() == 'return_value') {
                     $codePrinter->output('ZEPHIR_RETURN_CALL_INTERNAL_METHOD_P0(EG(This), ' . $method->getInternalName() . ');');
                 } else {
                     $codePrinter->output('ZEPHIR_CALL_INTERNAL_METHOD_P0(&' . $symbolVariable->getName() . ', EG(This), ' . $method->getInternalName() . ');');
                 }
             } else {
                 $codePrinter->output('ZEPHIR_CALL_INTERNAL_METHOD_NORETURN_P0(EG(This), ' . $method->getInternalName() . ');');
             }
         } else {
             if ($isExpecting) {
                 if ($symbolVariable->getName() == 'return_value') {
                     $codePrinter->output('ZEPHIR_RETURN_CALL_INTERNAL_METHOD_P' . count($params) . '(EG(This), ' . $method->getInternalName() . ', ' . join(', ', $params) . ');');
                 } else {
                     $codePrinter->output('ZEPHIR_CALL_INTERNAL_METHOD_P' . count($params) . '(&' . $symbolVariable->getName() . ', EG(This), ' . $method->getInternalName() . ', ' . join(', ', $params) . ');');
                 }
             } else {
                 $codePrinter->output('ZEPHIR_CALL_INTERNAL_METHOD_NORETURN_P' . count($params) . '(EG(This), ' . $method->getInternalName() . ', ' . join(', ', $params) . ');');
             }
         }
     }
     /**
      * Temporary variables must be copied if they have more than one reference
      */
     foreach ($this->getMustCheckForCopyVariables() as $checkVariable) {
         $codePrinter->output('zephir_check_temp_parameter(' . $checkVariable . ');');
     }
     $this->addCallStatusOrJump($compilationContext);
 }
Esempio n. 7
0
 /**
  * @param ClassMethod $method
  *
  * @param bool        $isInterface
  *
  * @return string
  */
 protected function buildMethod(ClassMethod $method, $isInterface)
 {
     $modifier = implode(' ', array_diff($method->getVisibility(), $this->ignoreModifiers));
     $docBlock = new MethodDocBlock($method, 4);
     $parameters = array();
     $methodParameters = $method->getParameters();
     if ($methodParameters) {
         foreach ($methodParameters->getParameters() as $parameter) {
             $paramStr = '$' . $parameter['name'];
             if (isset($parameter['default'])) {
                 $paramStr .= ' = ' . $this->wrapPHPValue($parameter);
             }
             $parameters[] = $paramStr;
         }
     }
     $methodBody = "\t" . $modifier . ' function ' . $method->getName() . '(' . implode(', ', $parameters) . ')';
     if ($isInterface || $method->isAbstract()) {
         $methodBody .= ';';
     } else {
         $methodBody .= ' {}';
     }
     return $docBlock . "\n" . $methodBody;
 }