Skip to content

Commit

Permalink
Merge pull request #2331 from zephir-lang/#2330-mixed-support
Browse files Browse the repository at this point in the history
#2330 - Improve `mixed` support
  • Loading branch information
Jeckerson authored Dec 19, 2021
2 parents 2d0d692 + c20f409 commit 1eae866
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 85 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org).
## [Unreleased]
### Fixed
- Fixed left `null` with `string` condition [#2299](https://github.com/zephir-lang/zephir/issues/2299)
- Improved support of `mixed` type [#2330](https://github.com/zephir-lang/zephir/issues/2330)

## [0.15.2] - 2021-10-24
### Fixed
Expand Down
22 changes: 11 additions & 11 deletions Library/Operators/Other/IssetOperator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Zephir\Operators\Other;

use ReflectionException;
use Zephir\CompilationContext;
use Zephir\CompiledExpression;
use Zephir\Exception;
Expand All @@ -21,7 +22,7 @@
use Zephir\Operators\AbstractOperator;

/**
* Checks if a array offset or a property is defined on a polymorphic variable
* Checks if an array offset or a property is defined on a polymorphic variable
*/
class IssetOperator extends AbstractOperator
{
Expand All @@ -34,14 +35,11 @@ class IssetOperator extends AbstractOperator
* @return CompiledExpression
*
* @throws Exception
* @throws ReflectionException
*/
public function compile(array $expression, CompilationContext $compilationContext): CompiledExpression
{
if ('list' === $expression['left']['type']) {
$left = $expression['left']['left'];
} else {
$left = $expression['left'];
}
$left = 'list' === $expression['left']['type'] ? $expression['left']['left'] : $expression['left'];

switch ($left['type']) {
case 'array-access':
Expand All @@ -52,7 +50,7 @@ public function compile(array $expression, CompilationContext $compilationContex
$exprVariable->setNoisy(false);

$exprCompiledVariable = $exprVariable->compile($compilationContext);
if ('variable' != $exprCompiledVariable->getType() && 'array' != $exprCompiledVariable->getType()) {
if (!in_array($exprCompiledVariable->getType(), ['variable', 'array'], true)) {
throw new CompilerException('Expression type: '.$exprCompiledVariable->getType().' cannot be used as array', $left['left']);
}

Expand All @@ -67,7 +65,7 @@ public function compile(array $expression, CompilationContext $compilationContex
break;
}

if ('variable' == $variable->getType()) {
if ('variable' === $variable->getType()) {
if ($variable->hasDifferentDynamicType(['undefined', 'array', 'null'])) {
$compilationContext->logger->warning(
'Possible attempt to use non array in isset operator',
Expand All @@ -88,6 +86,7 @@ public function compile(array $expression, CompilationContext $compilationContex
return $compilationContext->backend->arrayIsset($variable, $resolvedExpr, $left['right'], $compilationContext);

case 'variable':
case 'mixed':
$indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $left['right']);

return $compilationContext->backend->arrayIsset($variable, $indexVariable, $left['right'], $compilationContext);
Expand All @@ -106,12 +105,12 @@ public function compile(array $expression, CompilationContext $compilationContex
$exprVariable->setReadOnly(true);

$exprCompiledVariable = $exprVariable->compile($compilationContext);
if ('variable' != $exprCompiledVariable->getType()) {
if ('variable' !== $exprCompiledVariable->getType()) {
throw new CompilerException('Expression type: '.$exprCompiledVariable->getType().' cannot be used as object', $left['left']);
}

$variable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $left['left']);
if ('variable' != $variable->getType()) {
if ('variable' !== $variable->getType()) {
throw new CompilerException('Variable type: '.$variable->getType().' cannot be used as object', $left['left']);
}

Expand All @@ -123,7 +122,7 @@ public function compile(array $expression, CompilationContext $compilationContex
}
$variableCode = $compilationContext->backend->getVariableCode($variable);

if ('property-access' == $left['type']) {
if ('property-access' === $left['type']) {
return $compilationContext->backend->propertyIsset($variable, $left['right']['value'], $compilationContext);
}

Expand All @@ -137,6 +136,7 @@ public function compile(array $expression, CompilationContext $compilationContex
$indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $left['right']);
switch ($indexVariable->getType()) {
case 'variable':
case 'mixed':
case 'string':
$indexVariableCode = $compilationContext->backend->getVariableCode($indexVariable);

Expand Down
39 changes: 8 additions & 31 deletions Library/Passes/StaticTypeInference.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
use Zephir\StatementsBlock;

/**
* StaticTypeInference.
*
* This pass try to infer typing on dynamic variables so the compiler
* can replace them by low level types automatically
*/
class StaticTypeInference
{
protected $variables = [];
protected array $variables = [];

protected $infered = [];
protected array $infered = [];

/**
* Do the compilation pass.
Expand Down Expand Up @@ -156,6 +154,7 @@ public function markVariable($variable, $type)
break;

case 'variable':
case 'mixed':
$this->variables[$variable] = 'undefined';
break;

Expand Down Expand Up @@ -243,35 +242,23 @@ public function passCall(array $expression)
{
if (isset($expression['parameters'])) {
foreach ($expression['parameters'] as $parameter) {
if ('variable' == $parameter['parameter']['type']) {
//$this->markVariable($parameter['value']);
} else {
$this->passExpression($parameter['parameter']);
}
$this->passExpression($parameter['parameter']);
}
}
}

public function passArray(array $expression)
{
foreach ($expression['left'] as $item) {
if ('variable' == $item['value']['type']) {
//$this->markVariable($item['value']['value'], 'dynamical');
} else {
$this->passExpression($item['value']);
}
$this->passExpression($item['value']);
}
}

public function passNew(array $expression)
{
if (isset($expression['parameters'])) {
foreach ($expression['parameters'] as $parameter) {
if ('variable' == $parameter['parameter']['type']) {
//$this->markVariable($parameter['value'], 'dynamical');
} else {
$this->passExpression($parameter['parameter']);
}
$this->passExpression($parameter['parameter']);
}
}
}
Expand Down Expand Up @@ -561,30 +548,20 @@ public function passStatementBlock(array $statements)
}
break;

case 'throw':
case 'return':
if (isset($statement['expr'])) {
$this->passExpression($statement['expr']);
}
break;

case 'loop':
if (isset($statement['statements'])) {
$this->passStatementBlock($statement['statements']);
}
break;

case 'try-catch':
case 'loop':
if (isset($statement['statements'])) {
$this->passStatementBlock($statement['statements']);
}
break;

case 'throw':
if (isset($statement['expr'])) {
$this->passExpression($statement['expr']);
}
break;

case 'fetch':
$this->passExpression($statement['expr']);
break;
Expand Down
18 changes: 10 additions & 8 deletions Library/Statements/Let/ObjectDynamicProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Zephir\Statements\Let;

use Exception;
use Zephir\CompilationContext;
use Zephir\CompiledExpression;
use Zephir\Exception\CompilerException;
use Zephir\Variable as ZephirVariable;

/**
* ObjectDynamicProperty.
*
* Updates object properties dynamically
*/
class ObjectDynamicProperty
Expand All @@ -33,9 +34,9 @@ class ObjectDynamicProperty
* @param array $statement
*
* @throws CompilerException
* @throws \Exception
* @throws Exception
*/
public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
public function assign(string $variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
{
if (!$symbolVariable->isInitialized()) {
throw new CompilerException("Cannot mutate variable '".$variable."' because it is not initialized", $statement);
Expand All @@ -48,7 +49,7 @@ public function assign($variable, ZephirVariable $symbolVariable, CompiledExpres
$propertyName = $statement['property'];

$propertyVariable = $compilationContext->symbolTable->getVariableForRead($propertyName, $compilationContext, $statement);
if ($propertyVariable->isNotVariableAndString()) {
if ($propertyVariable->isNotVariableAndMixedAndString()) {
throw new CompilerException("Cannot use variable type '".$propertyVariable->getType()."' to update object property", $statement);
}

Expand All @@ -64,7 +65,7 @@ public function assign($variable, ZephirVariable $symbolVariable, CompiledExpres
throw new CompilerException('Cannot use non-initialized variable as an object', $statement);
}

/*
/**
* Trying to use a non-object dynamic variable as object
*/
if ($symbolVariable->hasDifferentDynamicType(['undefined', 'object', 'null'])) {
Expand Down Expand Up @@ -98,14 +99,14 @@ public function assign($variable, ZephirVariable $symbolVariable, CompiledExpres
break;

case 'bool':
$value = null;
if ('1' == $resolvedExpr->getBooleanCode()) {
$value = 'true';
} elseif ('0' == $resolvedExpr->getBooleanCode()) {
$value = 'false';
} else {
throw new \Exception('?');
throw new Exception('?');
}

$compilationContext->backend->updateProperty($symbolVariable, $propertyVariableName, $value, $compilationContext);
break;

Expand Down Expand Up @@ -143,6 +144,7 @@ public function assign($variable, ZephirVariable $symbolVariable, CompiledExpres
case 'string':
case 'variable':
case 'array':
case 'mixed':
$compilationContext->backend->updateProperty($symbolVariable, $propertyVariable, $resolvedExpr, $compilationContext);
if ($symbolVariable->isTemporal()) {
$symbolVariable->setIdle(true);
Expand Down
10 changes: 5 additions & 5 deletions Library/Statements/Let/ObjectDynamicStringProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Zephir\Statements\Let;

use Zephir\CompilationContext;
Expand All @@ -17,8 +19,6 @@
use Zephir\Variable as ZephirVariable;

/**
* ObjectDynamicProperty.
*
* Updates object properties dynamically
*/
class ObjectDynamicStringProperty
Expand All @@ -35,13 +35,13 @@ class ObjectDynamicStringProperty
* @throws CompilerException
* @throws \Exception
*/
public function assign($variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
public function assign(string $variable, ZephirVariable $symbolVariable, CompiledExpression $resolvedExpr, CompilationContext $compilationContext, array $statement)
{
if (!$symbolVariable->isInitialized()) {
throw new CompilerException("Cannot mutate variable '".$variable."' because it is not initialized", $statement);
}

if ('variable' != $symbolVariable->getType()) {
if ('variable' !== $symbolVariable->getType()) {
throw new CompilerException("Variable type '".$symbolVariable->getType()."' cannot be used as object", $statement);
}

Expand All @@ -63,7 +63,7 @@ public function assign($variable, ZephirVariable $symbolVariable, CompiledExpres
throw new CompilerException('Cannot use non-initialized variable as an object', $statement);
}

/*
/**
* Trying to use a non-object dynamic variable as object
*/
if ($symbolVariable->hasDifferentDynamicType(['undefined', 'object', 'null'])) {
Expand Down
5 changes: 3 additions & 2 deletions Library/Statements/Let/ObjectProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Zephir\Statements\Let;

use Zephir\CompilationContext as Context;
Expand All @@ -17,8 +19,6 @@
use Zephir\Variable as ZephirVariable;

/**
* ObjectProperty.
*
* Adds/Updates an array index
*/
class ObjectProperty
Expand Down Expand Up @@ -285,6 +285,7 @@ public function assign(
case 'array':
case 'string':
case 'variable':
case 'mixed':
$context->backend->updateProperty($symbolVariable, $propertyName, $variableVariable, $context);
if ($symbolVariable->isTemporal()) {
$symbolVariable->setIdle(true);
Expand Down
7 changes: 4 additions & 3 deletions Library/Statements/UnsetStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Zephir\Statements;

use ReflectionException;
use Zephir\CompilationContext;
use Zephir\Exception;
use Zephir\Exception\CompilerException;
Expand All @@ -29,6 +30,7 @@ class UnsetStatement extends StatementAbstract
* @param CompilationContext $compilationContext
*
* @throws Exception
* @throws ReflectionException
*/
public function compile(CompilationContext $compilationContext): void
{
Expand Down Expand Up @@ -61,6 +63,7 @@ public function compile(CompilationContext $compilationContext): void
break;

case 'property-access':
case 'property-dinamic-access':
$expr = new Expression($expression['left']);
$expr->setReadOnly(true);
$exprVar = $expr->compile($compilationContext);
Expand All @@ -72,9 +75,6 @@ public function compile(CompilationContext $compilationContext): void

return;

case 'property-dynamic-access':
//TODO: fix it

default:
throw new CompilerException('Cannot use expression type: '.$expression['type'].' in "unset"', $expression);
}
Expand All @@ -100,6 +100,7 @@ public function compile(CompilationContext $compilationContext): void
* @return CompilationContext
*
* @throws Exception
* @throws ReflectionException
*/
private function generateUnsetPropertyFromObject(array $expression, CompilationContext $compilationContext): CompilationContext
{
Expand Down
2 changes: 0 additions & 2 deletions Library/Types/ArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
use Zephir\Types;

/**
* ArrayType.
*
* Defines methods of the built-in array type
*/
class ArrayType extends AbstractType
Expand Down
Loading

0 comments on commit 1eae866

Please sign in to comment.