/** * {expr} + {expr} * * @param \PhpParser\Node\Expr\BinaryOp\Plus $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: switch ($right->getType()) { case CompiledExpression::INTEGER: /** * php -r "var_dump(1 + 1);" int(2) */ return new CompiledExpression(CompiledExpression::INTEGER, $left->getValue() + $right->getValue()); case CompiledExpression::DOUBLE: /** * php -r "var_dump(1 + 1.0);" double(2) */ return new CompiledExpression(CompiledExpression::DOUBLE, $left->getValue() + $right->getValue()); } break; case CompiledExpression::DOUBLE: switch ($right->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: /** * php -r "var_dump(1.0 + 1);" double(2) * php -r "var_dump(1.0 + 1.0);" double(2) */ return new CompiledExpression(CompiledExpression::DOUBLE, $left->getValue() + $right->getValue()); } } return new CompiledExpression(); }
/** * yield {value}, yield {key} => {value} * * @param \PhpParser\Node\Expr\Yield_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $key = $context->getExpressionCompiler()->compile($expr->key); $value = $context->getExpressionCompiler()->compile($expr->value); // @TODO implement yield 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}) ? {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()); } }
/** * @param \PhpParser\Node\Stmt\Foreach_ $stmt * @param Context $context * @return null|boolean */ public function compile($stmt, Context $context) { $context->getExpressionCompiler()->compile($stmt->expr); if ($stmt->keyVar) { $context->getExpressionCompiler()->declareVariable($stmt->keyVar, null, CompiledExpression::MIXED); } if ($stmt->valueVar) { $context->getExpressionCompiler()->declareVariable($stmt->valueVar, null, CompiledExpression::MIXED); } foreach ($stmt->stmts as $statement) { \PHPSA\nodeVisitorFactory($statement, $context); } }
/** * @param \PhpParser\Node\Stmt\For_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { foreach ($stmt->init as $init) { $context->getExpressionCompiler()->compile($init); } foreach ($stmt->cond as $cond) { $context->getExpressionCompiler()->compile($cond); } foreach ($stmt->loop as $loop) { $context->getExpressionCompiler()->compile($loop); } foreach ($stmt->stmts as $statement) { \PHPSA\nodeVisitorFactory($statement, $context); } }
/** * It's used in conditions * {left-expr} <=> {right-expr} * * @param \PhpParser\Node\Expr\BinaryOp\Spaceship $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()) { if ($left->getValue() == $right->getValue()) { return new CompiledExpression(CompiledExpression::INTEGER, 0); } elseif ($left->getValue() < $right->getValue()) { return new CompiledExpression(CompiledExpression::INTEGER, -1); } elseif ($left->getValue() > $right->getValue()) { return new CompiledExpression(CompiledExpression::INTEGER, 1); } } return new CompiledExpression(); }
/** * @param \PhpParser\Node\Stmt\Const_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $compiler = $context->getExpressionCompiler(); foreach ($stmt->consts as $const) { $compiler->compile($const->value); } }
/** * $a &= $b; * * @param \PhpParser\Node\Expr\AssignRef $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiler = $context->getExpressionCompiler(); if ($expr->var instanceof VariableNode) { $name = $expr->var->name; $compiledExpression = $compiler->compile($expr->expr); $symbol = $context->getSymbol($name); if ($symbol) { $symbol->modify($compiledExpression->getType(), $compiledExpression->getValue()); } else { $symbol = new \PHPSA\Variable($name, $compiledExpression->getValue(), $compiledExpression->getType(), $context->getCurrentBranch()); $context->addVariable($symbol); } if ($expr->expr instanceof VariableNode) { $rightVarName = $expr->expr->name; $rightSymbol = $context->getSymbol($rightVarName); if ($rightSymbol) { $rightSymbol->incUse(); $symbol->setReferencedTo($rightSymbol); } else { $context->debug('Cannot fetch variable by name: ' . $rightVarName); } } $symbol->incSets(); return $compiledExpression; } $context->debug('Unknown how to pass symbol by ref'); return new CompiledExpression(); }
/** * @param \PhpParser\Node\Stmt\Static_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $compiler = $context->getExpressionCompiler(); foreach ($stmt->vars as $var) { $compiler->compile($var->default); } }
/** * classname->property * * @param \PhpParser\Node\Expr\PropertyFetch $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiler = $context->getExpressionCompiler(); $propertNameCE = $compiler->compile($expr->name); $scopeExpression = $compiler->compile($expr->var); if ($scopeExpression->isObject()) { $scopeExpressionValue = $scopeExpression->getValue(); if ($scopeExpressionValue instanceof ClassDefinition) { $propertyName = $propertNameCE->isString() ? $propertNameCE->getValue() : false; if ($propertyName) { if ($scopeExpressionValue->hasProperty($propertyName, true)) { $property = $scopeExpressionValue->getProperty($propertyName, true); return $compiler->compile($property); } else { $context->notice('language_error', sprintf('Property %s does not exist in %s scope', $propertyName, $scopeExpressionValue->getName()), $expr); } } } return new CompiledExpression(); } elseif ($scopeExpression->canBeObject()) { return new CompiledExpression(); } $context->notice('language_error', "It's not possible to fetch a property on a non-object", $expr, Check::CHECK_BETA); return new CompiledExpression(); }
/** * @param \PhpParser\Node\Stmt\Do_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $context->getExpressionCompiler()->compile($stmt->cond); foreach ($stmt->stmts as $statement) { \PHPSA\nodeVisitorFactory($statement, $context); } }
/** * [] array() * * @param \PhpParser\Node\Expr\Array_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiler = $context->getExpressionCompiler(); if ($expr->items === []) { return new CompiledExpression(CompiledExpression::ARR, []); } $resultArray = []; foreach ($expr->items as $item) { $compiledValueResult = $compiler->compile($item->value); if ($item->key) { $compiledKeyResult = $compiler->compile($item->key); switch ($compiledKeyResult->getType()) { case CompiledExpression::INTEGER: case CompiledExpression::DOUBLE: case CompiledExpression::BOOLEAN: case CompiledExpression::NULL: case CompiledExpression::STRING: $resultArray[$compiledKeyResult->getValue()] = $compiledValueResult->getValue(); } } else { $resultArray[] = $compiledValueResult->getValue(); } } return new CompiledExpression(CompiledExpression::ARR, $resultArray); }
/** * @param Expr $expr * @param Context $context * @return bool */ public function pass(Expr $expr, Context $context) { $castType = CompiledExpression::UNKNOWN; switch (get_class($expr)) { case Expr\Cast\Array_::class: $castType = CompiledExpression::ARR; break; case Expr\Cast\Bool_::class: $castType = CompiledExpression::BOOLEAN; break; case Expr\Cast\Int_::class: $castType = CompiledExpression::INTEGER; break; case Expr\Cast\Double::class: $castType = CompiledExpression::DOUBLE; break; case Expr\Cast\Object_::class: $castType = CompiledExpression::OBJECT; break; case Expr\Cast\String_::class: $castType = CompiledExpression::STRING; break; } $compiledExpression = $context->getExpressionCompiler()->compile($expr->expr); $exprType = $compiledExpression->getType(); $typeName = $compiledExpression->getTypeName(); if ($castType === $exprType) { $context->notice('stupid.cast', sprintf("You are trying to cast '%s' to '%s'", $typeName, $typeName), $expr); return true; } elseif (get_class($expr) == Expr\Cast\Unset_::class && $exprType === CompiledExpression::NULL) { $context->notice('stupid.cast', "You are trying to cast 'null' to 'unset' (null)", $expr); return true; } return false; }
/** * @param \PhpParser\Node\Stmt\Echo_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $compiler = $context->getExpressionCompiler(); foreach ($stmt->exprs as $expr) { $compiler->compile($expr); } }
/** * 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); }
/** * @param \PhpParser\Node\Expr\FuncCall $expr * @return CompiledExpression[] */ protected function parseArgs($expr, Context $context) { $arguments = []; foreach ($expr->args as $argument) { $arguments[] = $context->getExpressionCompiler()->compile($argument->value); } return $arguments; }
/** * {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(); }
/** * @param $stmt * @return Expression|Statement */ function nodeVisitorFactory($stmt, Context $context) { if ($stmt instanceof Node\Stmt) { $visitor = new Statement($stmt, $context); return $visitor; } return $context->getExpressionCompiler()->compile($stmt); }
/** * (int) {$expr} * * @param \PhpParser\Node\Expr\Cast\Int_ $expr * @param Context $context * @return CompiledExpression */ protected function compile($expr, Context $context) { $compiledExpression = $context->getExpressionCompiler()->compile($expr->expr); if ($compiledExpression->isTypeKnown()) { return new CompiledExpression(CompiledExpression::INTEGER, (int) $compiledExpression->getValue()); } return new CompiledExpression(); }
/** * {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\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()); }
/** * @param \PhpParser\Node\Arg[] $arguments * @param Context $context * @return CompiledExpression[] */ protected function parseArgs(array $arguments, Context $context) { $compiled = []; if ($arguments) { foreach ($arguments as $argument) { $compiled[] = $context->getExpressionCompiler()->compile($argument->value); } } return $compiled; }
/** * @param \PhpParser\Node\Stmt\Break_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $compiler = $context->getExpressionCompiler(); if ($stmt->num !== null) { $compiled = $compiler->compile($stmt->num); if (!$stmt->num instanceof LNumber || $compiled->getValue() == 0) { $context->notice('language_error', 'Break only supports positive integers.', $stmt); } } }
/** * @param \PhpParser\Node\Stmt\Declare_ $stmt * @param Context $context * @return CompiledExpression */ public function compile($stmt, Context $context) { $compiler = $context->getExpressionCompiler(); foreach ($stmt->declares as $declare) { $compiler->compile($declare->value); } foreach ($stmt->stmts as $stmt) { \PHPSA\nodeVisitorFactory($stmt, $context); } }
/** * @param $stmt * @param Context $context * @return bool */ public function pass($stmt, Context $context) { if ($stmt->default instanceof Node\Expr) { $compiled = $context->getExpressionCompiler()->compile($stmt->default); if ($compiled->getType() == CompiledExpression::NULL) { $context->notice('property_definition_default_value', 'null is default and is not needed.', $stmt); return true; } } return false; }
/** * ~{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(); }
/** * @param Expr $expr * @param Context $context * @return bool */ public function pass(Expr $expr, Context $context) { $compiler = $context->getExpressionCompiler(); $left = $compiler->compile($expr->left); $right = $compiler->compile($expr->right); if ($left->isArray() || $right->isArray()) { $context->notice('compare_with_array', "You are comparing an array. Did you want to use count()?", $expr); return true; } return false; }
/** * @param FuncCall $funcCall * @param Context $context * @return string|bool */ public function resolveFunctionName(FuncCall $funcCall, Context $context) { $funcNameCompiledExpression = $context->getExpressionCompiler()->compile($funcCall->name); if ($funcNameCompiledExpression->isString() && $funcNameCompiledExpression->isCorrectValue()) { return $funcNameCompiledExpression->getValue(); } else { if (!$funcNameCompiledExpression->isCallable()) { $context->debug('Unexpected function name type ' . $funcNameCompiledExpression->getTypeName(), $funcCall->name); } } return false; }
/** * {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(); }