/** * {expr}++ * * @param \PhpParser\Node\Expr\PostDec $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { if ($expr->var instanceof \PHPParser\Node\Expr\Variable) { $variableName = $expr->var->name; if ($variableName instanceof Name) { $variableName = $variableName->parts[0]; } $variable = $context->getSymbol($variableName); if ($variable) { $variable->incUse(); switch ($variable->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: $variable->dec(); return CompiledExpression::fromZvalValue($variable->getValue()); } $context->notice('postdec.variable.wrong-type', 'You are trying to use post derement operator on variable $' . $variableName . ' with type: ' . $variable->getTypeName(), $expr); } else { $context->notice('postdec.undefined-variable', 'You are trying to use post derement operator on undefined variable: ' . $variableName, $expr); } return new CompiledExpression(CompiledExpression::UNKNOWN); } $expression = new Expression($context); $compiledExpression = $expression->compile($expr->var); switch ($compiledExpression->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: $value = $compiledExpression->getValue(); return CompiledExpression::fromZvalValue($value++); } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * isset({expr]}) * * @param \PhpParser\Node\Expr\Isset_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $result = false; foreach ($expr->vars as $var) { if ($var instanceof VariableNode) { $varName = $var->name; if ($varName instanceof Name) { $varName = $varName->parts[0]; } $variable = $context->getSymbol($varName); if ($variable) { $variable->incUse(); if ($variable->getValue() !== null) { $result = true; continue; // this variable is set, continue } } return CompiledExpression::fromZvalValue(false); // one of the vars is not set } } return CompiledExpression::fromZvalValue($result); // if all are set return true, else false }
public function testFromZvalNull() { $result = CompiledExpression::fromZvalValue(null); $this->assertInstanceOfCompiledExpression($result); $this->assertSame(CompiledExpression::NULL, $result->getType()); $this->assertSame(null, $result->getValue()); }
/** * {expr} / {expr} * * @param \PhpParser\Node\Expr\BinaryOp\Div $expr * @param Context $context * @return CompiledExpression */ public function compile($expr, Context $context) { $expression = new Expression($context); $left = $expression->compile($expr->left); $expression = new Expression($context); $right = $expression->compile($expr->right); switch ($left->getType()) { case CompiledExpression::DNUMBER: if ($left->isEquals(0)) { $context->notice('division-zero', sprintf('You trying to use division from %s/{expr}', $left->getValue()), $expr); return new CompiledExpression(CompiledExpression::DNUMBER, 0.0); } break; case CompiledExpression::LNUMBER: case CompiledExpression::BOOLEAN: if ($left->isEquals(0)) { $context->notice('division-zero', sprintf('You trying to use division from %s/{expr}', $left->getValue()), $expr); switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::BOOLEAN: return new CompiledExpression(CompiledExpression::LNUMBER, 0); case CompiledExpression::DNUMBER: return new CompiledExpression(CompiledExpression::DNUMBER, 0.0); } } break; } switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: if ($right->isEquals(0)) { $context->notice('division-zero', sprintf('You trying to use division on {expr}/%s', $right->getValue()), $expr); return new CompiledExpression(CompiledExpression::UNKNOWN); } } switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: switch ($right->getType()) { case CompiledExpression::BOOLEAN: /** * Boolean is true via isEquals(0) check is not passed before * {int}/1 = {int} * {double}/1 = {double} */ $context->notice('division-on-true', 'You trying to use stupid division {expr}/true ~ {expr}/1 = {expr}', $expr); //no break //no break case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: return CompiledExpression::fromZvalValue($left->getValue() / $right->getValue()); } break; } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * include {expr}, require {expr} * * @param \PhpParser\Node\Expr\Include_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiled = $context->getExpressionCompiler()->compile($expr->expr); if ($compiled->isString()) { return CompiledExpression::fromZvalValue(1); } return CompiledExpression::fromZvalValue(false); }
/** * !{expr} * * @param \PhpParser\Node\Expr\BooleanNot $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiledExpression = $context->getExpressionCompiler()->compile($expr->expr); if ($compiledExpression->isTypeKnown()) { return CompiledExpression::fromZvalValue(!$compiledExpression->getValue()); } return new CompiledExpression(); }
/** * It's used in conditions * {left-expr} !== {right-expr} * * @param \PhpParser\Node\Expr\BinaryOp\NotIdentical $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $left = $context->getExpressionCompiler()->compile($expr->left); $right = $context->getExpressionCompiler()->compile($expr->right); if ($left->isTypeKnown() && $right->isTypeKnown()) { return CompiledExpression::fromZvalValue($left->getValue() !== $right->getValue()); } return new CompiledExpression(); }
/** * ~{expr} * * @param \PhpParser\Node\Expr\BitwiseNot $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiledExpression = $context->getExpressionCompiler()->compile($expr->expr); switch ($compiledExpression->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::STRING: return CompiledExpression::fromZvalValue(~$compiledExpression->getValue()); } return new CompiledExpression(); }
/** * ({expr}) ? {expr} : {expr} * * @param \PhpParser\Node\Expr\Ternary $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $condition = $context->getExpressionCompiler()->compile($expr->cond); $left = $context->getExpressionCompiler()->compile($expr->if); $right = $context->getExpressionCompiler()->compile($expr->else); if ($condition->getValue() == true) { return CompiledExpression::fromZvalValue($left->getValue()); } else { return CompiledExpression::fromZvalValue($right->getValue()); } }
/** * ~{expr} * * @param \PhpParser\Node\Expr\BitwiseNot $expr * @param Context $context * @return CompiledExpression */ public function compile($expr, Context $context) { $expression = new Expression($context); $compiledExpression = $expression->compile($expr->expr); switch ($compiledExpression->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: return CompiledExpression::fromZvalValue(~$compiledExpression->getValue()); } return new CompiledExpression(); }
/** * -{expr} * * @param \PhpParser\Node\Expr\UnaryMinus $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $left = $context->getExpressionCompiler()->compile($expr->expr); switch ($left->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::NUMBER: case CompiledExpression::BOOLEAN: case CompiledExpression::STRING: case CompiledExpression::NULL: return CompiledExpression::fromZvalValue(-(int) $left->getValue()); } return new CompiledExpression(); }
/** * -{expr} * * @param \PhpParser\Node\Expr\UnaryMinus $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $expression = new Expression($context); $left = $expression->compile($expr->expr); switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: case CompiledExpression::STRING: case CompiledExpression::NULL: return CompiledExpression::fromZvalValue(-$left->getValue()); case CompiledExpression::ARR: $context->notice('unsupported-operand-types', 'Unsupported operand types -{array}', $expr); } return new CompiledExpression(); }
/** * $array[1], $array[$var], $array["string"] * * @param \PhpParser\Node\Expr\ArrayDimFetch $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiler = $context->getExpressionCompiler(); $var = $compiler->compile($expr->var); $dim = $compiler->compile($expr->dim); if (!$var->isArray()) { $context->notice('language_error', "It's not possible to fetch an array element on a non array", $expr); return new CompiledExpression(); } if (!in_array($dim->getValue(), $var->getValue())) { $context->notice('language_error', "The array does not contain this value", $expr); return new CompiledExpression(); } $resultArray = $var->getValue(); return CompiledExpression::fromZvalValue($resultArray[$dim->getValue()]); }
/** * empty({expr]}) * * @param \PhpParser\Node\Expr\Empty_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { if ($expr->expr instanceof VariableNode) { $varName = $expr->expr->name; if ($varName instanceof Name) { $varName = $varName->parts[0]; } $variable = $context->getSymbol($varName); if ($variable) { $variable->incUse(); if ($variable->getValue() !== null && $variable->getValue() != false) { return CompiledExpression::fromZvalValue(true); } } } return CompiledExpression::fromZvalValue(false); }
/** * {expr} | {expr} * * @param \PhpParser\Node\Expr\BinaryOp\BitwiseOr $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $left = $context->getExpressionCompiler()->compile($expr->left); $right = $context->getExpressionCompiler()->compile($expr->right); switch ($left->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::BOOLEAN: switch ($right->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::BOOLEAN: return CompiledExpression::fromZvalValue($left->getValue() | $right->getValue()); } } return new CompiledExpression(); }
/** * {expr} ?? {expr} * * @param \PhpParser\Node\Expr\BinaryOp\Coalesce $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { if ($expr->left instanceof Variable) { $varName = $expr->left->name; if ($varName instanceof Name) { $varName = $varName->parts[0]; } $variable = $context->getSymbol($varName); if ($variable) { $variable->incUse(); if ($variable->getValue() !== null) { $leftCompiled = $context->getExpressionCompiler()->compile($expr->left); return CompiledExpression::fromZvalValue($leftCompiled->getValue()); } } } $rightCompiled = $context->getExpressionCompiler()->compile($expr->right); return CompiledExpression::fromZvalValue($rightCompiled->getValue()); }
/** * {left-expr} **= {right-expr} * * @param \PhpParser\Node\Expr\AssignOp\Pow $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $left = $context->getExpressionCompiler()->compile($expr->var); $expExpression = $context->getExpressionCompiler()->compile($expr->expr); switch ($left->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::NUMBER: case CompiledExpression::BOOLEAN: switch ($expExpression->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::NUMBER: case CompiledExpression::BOOLEAN: return CompiledExpression::fromZvalValue(pow($left->getValue(), $expExpression->getValue())); } } return new CompiledExpression(); }
/** * {expr} | {expr} * * @param \PhpParser\Node\Expr\BinaryOp\BitwiseOr $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $expression = new Expression($context); $left = $expression->compile($expr->left); $expression = new Expression($context); $right = $expression->compile($expr->right); switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: return CompiledExpression::fromZvalValue($left->getValue() | $right->getValue()); } break; } return new CompiledExpression(); }
protected function compileVariableDeclaration(CompiledExpression $variableName, CompiledExpression $value, Context $context) { switch ($variableName->getType()) { case CompiledExpression::STRING: break; default: $context->debug('Unexpected type of Variable name after compile'); return new CompiledExpression(); } $symbol = $context->getSymbol($variableName->getValue()); if ($symbol) { $symbol->modify($value->getType(), $value->getValue()); $context->modifyReferencedVariables($symbol, $value->getType(), $value->getValue()); } else { $symbol = new \PHPSA\Variable($variableName->getValue(), $value->getValue(), $value->getType(), $context->getCurrentBranch()); $context->addVariable($symbol); } $symbol->incSets(); }
/** * {expr} % {expr} * * @param \PhpParser\Node\Expr\BinaryOp\Mod $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $left = $context->getExpressionCompiler()->compile($expr->left); $right = $context->getExpressionCompiler()->compile($expr->right); if ($right->isEquals(0)) { $context->notice('language_error', 'You are trying to divide by 0.', $expr); return new CompiledExpression(); } switch ($left->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::BOOLEAN: switch ($right->getType()) { case CompiledExpression::BOOLEAN: case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: return CompiledExpression::fromZvalValue($left->getValue() % $right->getValue()); } } return new CompiledExpression(); }
/** * {expr}++ * * @param \PhpParser\Node\Expr\PostDec $expr * @param Context $context * @return CompiledExpression */ public function compile($expr, Context $context) { if ($expr->var instanceof \PHPParser\Node\Expr\Variable) { $name = $expr->var->name; $variable = $context->getSymbol($name); if ($variable) { $variable->inc(); $variable->incUse(); return CompiledExpression::fromZvalValue($variable->getValue()); } } $expression = new Expression($context); $compiledExpression = $expression->compile($expr->var); switch ($compiledExpression->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: $value = $compiledExpression->getValue(); return CompiledExpression::fromZvalValue($value++); } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * {expr} % {expr} * * @param \PhpParser\Node\Expr\BinaryOp\Mod $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $expression = new Expression($context); $left = $expression->compile($expr->left); $expression = new Expression($context); $right = $expression->compile($expr->right); switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::BOOLEAN: case CompiledExpression::DNUMBER: if ($left->isEquals(0)) { $context->notice('division-zero', 'You trying to use division from ' . $left->getValue() . '%{expr}', $expr); } break; } switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: if ($right->isEquals(0)) { $context->notice('division-zero', 'You trying to use division on {expr}%' . $right->getValue(), $expr); return new CompiledExpression(CompiledExpression::UNKNOWN); } break; } switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: switch ($right->getType()) { case CompiledExpression::BOOLEAN: case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: return CompiledExpression::fromZvalValue($left->getValue() % $right->getValue()); } break; } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * {expr} || {expr} * * @param \PhpParser\Node\Expr\BinaryOp\BooleanOr $expr * @param Context $context * @return CompiledExpression */ public function compile($expr, Context $context) { $expression = new Expression($context); $left = $expression->compile($expr->left); $expression = new Expression($context); $right = $expression->compile($expr->right); switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::STRING: case CompiledExpression::BOOLEAN: case CompiledExpression::NULL: switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::STRING: case CompiledExpression::BOOLEAN: case CompiledExpression::NULL: return CompiledExpression::fromZvalValue($left->getValue() || $right->getValue()); } break; } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * {expr}-- * * @param \PhpParser\Node\Expr\PostDec $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { if ($expr->var instanceof \PHPParser\Node\Expr\Variable) { $variableName = $expr->var->name; if ($variableName instanceof Name) { $variableName = $variableName->parts[0]; } $variable = $context->getSymbol($variableName); if ($variable) { $variable->incUse(); switch ($variable->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::NUMBER: $variable->dec(); return CompiledExpression::fromZvalValue($variable->getValue()); } $context->notice('language_error', 'You are trying to use post decrement operator on variable $' . $variableName . ' with type: ' . $variable->getTypeName(), $expr); } else { $context->notice('language_error', 'You are trying to use post decrement operator on undefined variable: ' . $variableName, $expr); } } return new CompiledExpression(); }
/** * {expr} / {expr} * * @param Node\Expr\BinaryOp\Div $expr * @return CompiledExpression|\RuntimeException */ protected function passBinaryOpDiv(Node\Expr\BinaryOp\Div $expr) { $expression = new Expression($this->context); $left = $expression->compile($expr->left); switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: if ($left->isEquals(0)) { $this->context->notice('division-zero', sprintf('You trying to use division from %s/{expr}', $left->getValue()), $expr); /** * Micro optimization -> 0/{expr} -> 0 */ return new CompiledExpression(CompiledExpression::LNUMBER, 0); } break; } $expression = new Expression($this->context); $right = $expression->compile($expr->right); switch ($right->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: case CompiledExpression::BOOLEAN: if ($right->isEquals(0)) { $this->context->notice('division-zero', sprintf('You trying to use division on {expr}/%s', $right->getValue()), $expr); return new CompiledExpression(CompiledExpression::UNKNOWN); } break; } switch ($left->getType()) { case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: switch ($right->getType()) { case CompiledExpression::BOOLEAN: /** * Boolean is true via isEquals(0) check is not passed before * {int}/1 = {int} * {double}/1 = {double} */ $this->context->notice('division-on-true', sprintf('You trying to use stupid division {expr}/true ~ {expr}/1 = {expr}', $right->getValue()), $expr); return new CompiledExpression($left->getType(), $left->getValue()); break; case CompiledExpression::LNUMBER: case CompiledExpression::DNUMBER: return CompiledExpression::fromZvalValue($left->getValue() / $right->getValue()); break; } break; } return new CompiledExpression(CompiledExpression::UNKNOWN); }
/** * @param Node\Name $expr * @return CompiledExpression */ public function getNodeName(Node\Name $expr) { $nodeString = $expr->toString(); if ($nodeString === 'null') { return new CompiledExpression(CompiledExpression::NULL); } if (in_array($nodeString, ['parent'], true)) { /** @var ClassDefinition $scope */ $scope = $this->context->scope; assert($scope instanceof ClassDefinition); if ($scope->getExtendsClass()) { $definition = $scope->getExtendsClassDefinition(); if ($definition) { return new CompiledExpression(CompiledExpression::OBJECT, $definition); } } else { $this->context->notice('language_error', 'Cannot access parent:: when current class scope has no parent', $expr); } } if (in_array($nodeString, ['self', 'static'], true)) { return CompiledExpression::fromZvalValue($this->context->scope); } if (defined($nodeString)) { return CompiledExpression::fromZvalValue(constant($expr)); } return new CompiledExpression(CompiledExpression::STRING, $expr->toString()); }
public function testIsArrayWhenFalse() { $compiledExpression = new CompiledExpression(CompiledExpression::BOOLEAN); parent::assertFalse($compiledExpression->isArray()); }
/** * clone {expr} * * @param \PhpParser\Node\Expr\Clone_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiled = $context->getExpressionCompiler()->compile($expr->expr); return CompiledExpression::fromZvalValue($compiled->getValue()); }
/** * `{expr}` * * @param \PhpParser\Node\Expr\ShellExec $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { return CompiledExpression::fromZvalValue(null); }