Skip to content

Commit

Permalink
Add type hints for scalar arguments and return values in Zend3
Browse files Browse the repository at this point in the history
Fixes #1656
  • Loading branch information
danhunsaker authored and sergeyklay committed Aug 5, 2018
1 parent d7afdc0 commit e4f92f9
Show file tree
Hide file tree
Showing 23 changed files with 1,367 additions and 122 deletions.
112 changes: 100 additions & 12 deletions Library/ClassDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -1294,32 +1294,120 @@ public function compile(CompilationContext $compilationContext)
*/
foreach ($methods as $method) {
$parameters = $method->getParameters();
if ($method->hasParameters()) {
$codePrinter->output('ZEND_BEGIN_ARG_INFO_EX(arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', 0, 0, ' . $method->getNumberOfRequiredParameters() . ')');
$argInfoName = 'arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName());

if ($this->compiler->backend->isZE3() && $method->hasReturnTypes()) {
if (array_key_exists('object', $method->getReturnTypes())) {
$class = 'NULL';

if (count($method->getReturnClassTypes()) == 1) {
$class = Utils::escapeClassName($compilationContext->getFullName(key($method->getReturnClassTypes())));
}

$codePrinter->output('#ifdef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX');
$codePrinter->output(
'ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(' . $argInfoName . ', 0, ' .
$method->getNumberOfRequiredParameters() . ', ' .
$class . ', ' . ($method->areReturnTypesNullCompatible() ? 1 : 0) . ')'
);
$codePrinter->output('#else');
$codePrinter->output(
'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(' . $argInfoName . ', 0, ' .
$method->getNumberOfRequiredParameters() . ', ' .
'NULL, "' . $class . '", ' . ($method->areReturnTypesNullCompatible() ? 1 : 0) . ')'
);
$codePrinter->output('#endif');
} else {
$type = 'IS_NULL';

if ($method->areReturnTypesIntCompatible()) {
$type = 'IS_LONG';
}
if ($method->areReturnTypesDoubleCompatible()) {
$type = 'IS_DOUBLE';
}
if ($method->areReturnTypesBoolCompatible()) {
$type = '_IS_BOOL';
}
if ($method->areReturnTypesStringCompatible()) {
$type = 'IS_STRING';
}

$codePrinter->output('#ifdef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX');
$codePrinter->output(
'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(' . $argInfoName . ', 0, ' .
$method->getNumberOfRequiredParameters() . ', ' .
$type . ', ' . ($method->areReturnTypesNullCompatible() ? 1 : 0) . ')'
);
$codePrinter->output('#else');
$codePrinter->output(
'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(' . $argInfoName . ', 0, ' .
$method->getNumberOfRequiredParameters() . ', ' .
$type . ', NULL, ' . ($method->areReturnTypesNullCompatible() ? 1 : 0) . ')'
);
$codePrinter->output('#endif');
}

if ($parameters == null || !count($parameters->getParameters())) {
$codePrinter->output('ZEND_END_ARG_INFO()');
$codePrinter->outputBlankLine();
}
} elseif ($parameters != null && count($parameters->getParameters())) {
$codePrinter->output(
'ZEND_BEGIN_ARG_INFO_EX(' . $argInfoName . ', 0, 0, ' .
$method->getNumberOfRequiredParameters() . ')'
);
}

if ($parameters != null && count($parameters->getParameters())) {
foreach ($parameters->getParameters() as $parameter) {
switch ($parameter['data-type']) {
case 'array':
$codePrinter->output("\t" . 'ZEND_ARG_ARRAY_INFO(0, ' . $parameter['name'] . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
switch (($this->compiler->backend->isZE3() ? '3:' : '2:') . $parameter['data-type']) {
case '2:array':
case '3:array':
$codePrinter->output("\t" . 'ZEND_ARG_ARRAY_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

case 'variable':
case '2:variable':
case '3:variable':
if (isset($parameter['cast'])) {
switch ($parameter['cast']['type']) {
case 'variable':
$value = $parameter['cast']['value'];
$codePrinter->output("\t" . 'ZEND_ARG_OBJ_INFO(0, ' . $parameter['name'] . ', ' . Utils::escapeClassName($compilationContext->getFullName($value)) . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
$codePrinter->output("\t" . 'ZEND_ARG_OBJ_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', ' . Utils::escapeClassName($compilationContext->getFullName($value)) . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

default:
throw new Exception('Unexpected exception');
}
} else {
$codePrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
$codePrinter->output("\t" . 'ZEND_ARG_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ')');
}
break;

case '3:bool':
case '3:boolean':
$codePrinter->output("\t" . 'ZEND_ARG_TYPE_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', ' . ($this->compiler->backend->isZE3() ? '_IS_BOOL' : 'IS_BOOL') . ', ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

case '3:uchar':
case '3:int':
case '3:uint':
case '3:long':
case '3:ulong':
$codePrinter->output("\t" . 'ZEND_ARG_TYPE_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', IS_LONG, ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

case '3:double':
$codePrinter->output("\t" . 'ZEND_ARG_TYPE_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', IS_DOUBLE, ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

case '3:char':
case '3:string':
$codePrinter->output("\t" . 'ZEND_ARG_TYPE_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ', IS_STRING, ' . (isset($parameter['default']) ? 1 : 0) . ')');
break;

default:
$codePrinter->output("\t" . 'ZEND_ARG_INFO(0, ' . $parameter['name'] . ')');
$codePrinter->output("\t" . 'ZEND_ARG_INFO(' . (isset($parameter['reference']) ? $parameter['reference'] : 0) . ', ' . $parameter['name'] . ')');
break;
}
}
Expand All @@ -1333,21 +1421,21 @@ public function compile(CompilationContext $compilationContext)
foreach ($methods as $method) {
if ($this->getType() == 'class') {
if (!$method->isInternal()) {
if ($method->hasParameters()) {
if (($this->compiler->backend->isZE3() && $method->hasReturnTypes()) || $method->hasParameters()) {
$codePrinter->output("\t" . 'PHP_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', ' . $method->getModifiers() . ')');
} else {
$codePrinter->output("\t" . 'PHP_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', NULL, ' . $method->getModifiers() . ')');
}
}
} else {
if ($method->isStatic()) {
if ($method->hasParameters()) {
if (($this->compiler->backend->isZE3() && $method->hasReturnTypes()) || $method->hasParameters()) {
$codePrinter->output("\t" . 'ZEND_FENTRY(' . $method->getName() . ', NULL, arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ', ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)');
} else {
$codePrinter->output("\t" . 'ZEND_FENTRY(' . $method->getName() . ', NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)');
}
} else {
if ($method->hasParameters()) {
if (($this->compiler->backend->isZE3() && $method->hasReturnTypes()) || $method->hasParameters()) {
$codePrinter->output("\t" . 'PHP_ABSTRACT_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', arginfo_' . strtolower($this->getCNamespace() . '_' . $this->getName() . '_' . $method->getName()) . ')');
} else {
$codePrinter->output("\t" . 'PHP_ABSTRACT_ME(' . $this->getCNamespace() . '_' . $this->getName() . ', ' . $method->getName() . ', NULL)');
Expand Down
Loading

0 comments on commit e4f92f9

Please sign in to comment.