diff --git a/Library/Operators/BaseOperator.php b/Library/Operators/BaseOperator.php index 95543cd641..929fdae3bd 100755 --- a/Library/Operators/BaseOperator.php +++ b/Library/Operators/BaseOperator.php @@ -49,12 +49,45 @@ public function setExpectReturn($expecting, Variable $expectingVariable = null) $this->_expectingVariable = $expectingVariable; } + /** + * Returns the expected variable for assignment or creates a temporary variable to + * store the result. This method returns a variable that is always stored in the heap + * + * @param CompilationContext $compilationContext + * @param array $expression + * @param boolean $init + * @return Variable + */ + public function getExpectedNonLiteral(CompilationContext $compilationContext, $expression, $init = true) + { + $isExpecting = $this->_expecting; + $symbolVariable = $this->_expectingVariable; + + if ($isExpecting) { + if (is_object($symbolVariable)) { + if ($symbolVariable->getType() == 'variable' && !$symbolVariable->isLocalOnly()) { + if (!$init) { + return $symbolVariable; + } + $symbolVariable->initVariant($compilationContext); + } else { + $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression); + } + } else { + $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression); + } + } + return $symbolVariable; + } + /** * Returns the expected variable for assignment or creates a temporary variable to * store the result * * @param CompilationContext $compilationContext * @param array $expression + * @param boolean $init + * @return Variable */ public function getExpected(CompilationContext $compilationContext, $expression, $init = true) { diff --git a/Library/Operators/Other/NewInstanceOperator.php b/Library/Operators/Other/NewInstanceOperator.php index 9fc87e6dea..fd4f2eca0c 100644 --- a/Library/Operators/Other/NewInstanceOperator.php +++ b/Library/Operators/Other/NewInstanceOperator.php @@ -34,6 +34,7 @@ */ class NewInstanceOperator extends BaseOperator { + protected $_literalOnly = false; /** * Creates a new instance @@ -51,11 +52,16 @@ public function compile(array $expression, CompilationContext $compilationContex /** * Resolves the symbol that expects the value */ - $symbolVariable = $this->getExpected($compilationContext, $expression); + $this->_literalOnly = false; + $symbolVariable = $this->getExpectedNonLiteral($compilationContext, $expression); if (!$symbolVariable->isVariable()) { throw new CompilerException("Objects can only be instantiated into dynamic variables", $expression); } + if ($symbolVariable->isLocalOnly()) { + throw new CompilerException("Cannot use non-heap variable to store new instance", $expression); + } + if ($symbolVariable->hasDifferentDynamicType(array('unknown', 'undefined', 'object', 'null'))) { $compilationContext->logger->warning('Possible attempt to use non-object in "new" operator', 'non-valid-new', $expression); }