예제 #1
0
 /**
  * {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);
 }
예제 #2
0
파일: Plus.php 프로젝트: sekjun9878/phpsa
 /**
  * {expr} + {expr}
  *
  * @param \PhpParser\Node\Expr\BinaryOp\Plus $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:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                     /**
                      * php -r "var_dump(1 + 1);" int(2)
                      */
                     return new CompiledExpression(CompiledExpression::LNUMBER, $left->getValue() + $right->getValue());
                 case CompiledExpression::DNUMBER:
                     /**
                      * php -r "var_dump(1 + 1.0);" double(2)
                      */
                     return new CompiledExpression(CompiledExpression::DNUMBER, $left->getValue() + $right->getValue());
             }
             break;
         case CompiledExpression::DNUMBER:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                 case CompiledExpression::DNUMBER:
                     /**
                      * php -r "var_dump(1.0 + 1);"   double(2)
                      * php -r "var_dump(1.0 + 1.0);" double(2)
                      */
                     return new CompiledExpression(CompiledExpression::DNUMBER, $left->getValue() + $right->getValue());
             }
             break;
     }
     return new CompiledExpression(CompiledExpression::UNKNOWN);
 }
예제 #3
0
 /**
  * @param \PhpParser\Node\Expr\BinaryOp\Concat $expr
  * @param Context $context
  * @return CompiledExpression
  */
 protected function compile($expr, Context $context)
 {
     $compiler = new Expression($context);
     $leftExpression = $compiler->compile($expr->left);
     $rightExpression = $compiler->compile($expr->right);
     switch ($leftExpression->getType()) {
         case CompiledExpression::ARR:
             $context->notice('unsupported-operand-types', 'Unsupported operand types -{array}', $expr);
             break;
     }
     switch ($rightExpression->getType()) {
         case CompiledExpression::ARR:
             $context->notice('unsupported-operand-types', 'Unsupported operand types -{array}', $expr);
             break;
     }
     switch ($leftExpression->getType()) {
         case CompiledExpression::STRING:
         case CompiledExpression::NUMBER:
         case CompiledExpression::INTEGER:
         case CompiledExpression::DOUBLE:
             switch ($rightExpression->getType()) {
                 case CompiledExpression::STRING:
                 case CompiledExpression::NUMBER:
                 case CompiledExpression::INTEGER:
                 case CompiledExpression::DOUBLE:
                     return new CompiledExpression(CompiledExpression::STRING, $leftExpression->getValue() . $rightExpression->getValue());
                     break;
             }
             break;
     }
     return new CompiledExpression(CompiledExpression::NULL);
 }
예제 #4
0
/**
 * @param $stmt
 * @return Expression|Statement
 */
function nodeVisitorFactory($stmt, Context $context)
{
    if ($stmt instanceof Node\Stmt) {
        $visitor = new Statement($stmt, $context);
        return $visitor;
    }
    $visitor = new Expression($context);
    return $visitor->compile($stmt);
}
예제 #5
0
 /**
  * @param \PhpParser\Node\Expr\MethodCall $expr
  * @param Context $context
  * @return CompiledExpression
  */
 protected function compile($expr, Context $context)
 {
     if ($expr->var instanceof Variable) {
         $symbol = $context->getSymbol($expr->var->name);
         if ($symbol) {
             switch ($symbol->getType()) {
                 case CompiledExpression::OBJECT:
                 case CompiledExpression::DYNAMIC:
                     $symbol->incUse();
                     /** @var ClassDefinition $calledObject */
                     $calledObject = $symbol->getValue();
                     if ($calledObject instanceof ClassDefinition) {
                         $methodName = is_string($expr->name) ? $expr->name : false;
                         if ($expr->name instanceof Variable) {
                             /**
                              * @todo implement fetch from symbol table
                              */
                             //$methodName = $expr->name->name;
                         }
                         if ($methodName) {
                             if (!$calledObject->hasMethod($methodName, true)) {
                                 $context->notice('undefined-mcall', sprintf('Method %s() does not exist in %s scope', $methodName, $expr->var->name), $expr);
                                 //it's needed to exit
                                 return new CompiledExpression();
                             }
                             $method = $calledObject->getMethod($methodName);
                             if (!$method) {
                                 $context->debug('getMethod is not working');
                                 return new CompiledExpression();
                             }
                             if ($method->isStatic()) {
                                 $context->notice('undefined-mcall', sprintf('Method %s() is a static function but called like class method in $%s variable', $methodName, $expr->var->name), $expr);
                             }
                             return new CompiledExpression();
                         }
                         return new CompiledExpression();
                     }
                     /**
                      * It's a wrong type or value, maybe it's implemented and We need to fix it in another compilers
                      */
                     $context->debug('Unknown $calledObject - is ' . gettype($calledObject));
                     return new CompiledExpression();
             }
             $context->notice('variable-wrongtype.mcall', sprintf('Variable $%s is not object\\callable and cannot be called like this', $expr->var->name), $expr);
             return new CompiledExpression();
         } else {
             $context->notice('undefined-variable.mcall', sprintf('Variable $%s is not defined in this scope', $expr->var->name), $expr);
             return new CompiledExpression();
         }
     }
     $expression = new Expression($context);
     $expression->compile($expr->var);
     $context->debug('Unknown method call');
     return new CompiledExpression();
 }
예제 #6
0
파일: DoSt.php 프로젝트: sekjun9878/phpsa
 /**
  * @param \PhpParser\Node\Stmt\Do_ $stmt
  * @param Context $context
  * @return CompiledExpression
  */
 public function compile($stmt, Context $context)
 {
     $expression = new Expression($context);
     $expression->compile($stmt->cond);
     if (count($stmt->stmts) > 0) {
         foreach ($stmt->stmts as $statement) {
             \PHPSA\nodeVisitorFactory($statement, $context);
         }
     } else {
         $context->notice('not-implemented-body', 'Missing body', $stmt);
     }
 }
예제 #7
0
 /**
  * ~{expr}
  *
  * @param \PhpParser\Node\Expr\BitwiseNot $expr
  * @param Context $context
  * @return CompiledExpression
  */
 protected 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();
 }
예제 #8
0
 /**
  * -{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();
 }
예제 #9
0
파일: Div.php 프로젝트: sekjun9878/phpsa
 /**
  * {expr} / {expr}
  *
  * @param \PhpParser\Node\Expr\BinaryOp\Div $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::DNUMBER:
         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);
             }
             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);
 }
예제 #10
0
 /**
  * {expr} $operator {expr}
  *
  * @param \PhpParser\Node\Expr\BinaryOp $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:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                 case CompiledExpression::DNUMBER:
                     return new CompiledExpression(CompiledExpression::BOOLEAN, $this->compare($left->getValue(), $right->getValue()));
             }
             break;
     }
     return new CompiledExpression();
 }
예제 #11
0
 /**
  * @param \PhpParser\Node\Stmt\Foreach_ $stmt
  * @param Context $context
  * @return CompiledExpression
  */
 public function compile($stmt, Context $context)
 {
     $expression = new Expression($context);
     $expression->compile($stmt->expr);
     if ($stmt->keyVar) {
         $keyExpression = new Expression($context);
         $keyExpression->declareVariable($stmt->keyVar);
     }
     if ($stmt->valueVar) {
         $valueExpression = new Expression($context);
         $valueExpression->declareVariable($stmt->valueVar);
     }
     if (count($stmt->stmts) > 0) {
         foreach ($stmt->stmts as $statement) {
             \PHPSA\nodeVisitorFactory($statement, $context);
         }
     } else {
         return $context->notice('not-implemented-body', 'Missing body', $stmt);
     }
 }
예제 #12
0
파일: Mod.php 프로젝트: sekjun9878/phpsa
 /**
  * {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);
 }
예제 #13
0
 /**
  * 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)
 {
     $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:
         case CompiledExpression::NUMBER:
         case CompiledExpression::NULL:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                 case CompiledExpression::DNUMBER:
                 case CompiledExpression::BOOLEAN:
                 case CompiledExpression::NUMBER:
                 case CompiledExpression::NULL:
                     return new CompiledExpression(CompiledExpression::BOOLEAN, $left->getValue() !== $right->getValue());
             }
     }
     return new CompiledExpression(CompiledExpression::UNKNOWN);
 }
예제 #14
0
파일: Minus.php 프로젝트: sekjun9878/phpsa
 /**
  * {expr} - {expr}
  *
  * @param \PhpParser\Node\Expr\BinaryOp\Minus $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:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                     return new CompiledExpression(CompiledExpression::LNUMBER, $left->getValue() - $right->getValue());
             }
             break;
         case CompiledExpression::DNUMBER:
             switch ($right->getType()) {
                 case CompiledExpression::LNUMBER:
                 case CompiledExpression::DNUMBER:
                     return new CompiledExpression(CompiledExpression::DNUMBER, $left->getValue() - $right->getValue());
             }
             break;
     }
     return new CompiledExpression(CompiledExpression::UNKNOWN);
 }
예제 #15
0
 /**
  * @param \PhpParser\Node\Stmt\Return_ $stmt
  * @param Context $context
  * @return CompiledExpression
  */
 public function compile($stmt, Context $context)
 {
     $expression = new Expression($context);
     $compiledExpression = $expression->compile($stmt->expr);
     switch ($compiledExpression->getType()) {
         case CompiledExpression::VOID:
             $context->notice('return.void', 'You are trying to return void', $stmt);
             break;
     }
     if ($context->scopePointer) {
         /**
          * If it is a Class's method we need to work on return types, return possible values
          */
         if ($context->scopePointer->isClassMethod()) {
             /** @var ClassMethod $classMethod */
             $classMethod = $context->scopePointer->getObject();
             $classMethod->addNewType($compiledExpression->getType());
             if ($compiledExpression->isCorrectValue()) {
                 $classMethod->addReturnPossibleValue($compiledExpression->getValue());
             }
         }
     }
 }
예제 #16
0
파일: IfSt.php 프로젝트: sekjun9878/phpsa
 /**
  * @param \PhpParser\Node\Stmt\If_ $ifStatement
  * @param Context $context
  * @return CompiledExpression
  */
 public function compile($ifStatement, Context $context)
 {
     $expression = new Expression($context);
     $expression->compile($ifStatement->cond);
     if (count($ifStatement->stmts) > 0) {
         foreach ($ifStatement->stmts as $stmt) {
             \PHPSA\nodeVisitorFactory($stmt, $context);
         }
     } else {
         $context->notice('not-implemented-body', 'Missing body', $ifStatement);
     }
     if (count($ifStatement->elseifs) > 0) {
         foreach ($ifStatement->elseifs as $elseIfStatement) {
             $expression = new Expression($context);
             $expression->compile($elseIfStatement->cond);
             if (count($elseIfStatement->stmts) > 0) {
                 foreach ($elseIfStatement->stmts as $stmt) {
                     \PHPSA\nodeVisitorFactory($stmt, $context);
                 }
             } else {
                 $context->notice('not-implemented-body', 'Missing body', $elseIfStatement);
             }
         }
     } else {
         //@todo implement
     }
     if ($ifStatement->else) {
         if (count($ifStatement->else->stmts) > 0) {
             foreach ($ifStatement->else->stmts as $stmt) {
                 \PHPSA\nodeVisitorFactory($stmt, $context);
             }
         } else {
             $context->notice('not-implemented-body', 'Missing body', $ifStatement->else);
         }
     }
 }
예제 #17
0
 /**
  * Convert const fetch expr to CompiledExpression
  *
  * @param Node\Expr\ConstFetch $expr
  * @return CompiledExpression
  */
 protected function constFetch(Node\Expr\ConstFetch $expr)
 {
     if ($expr->name instanceof Node\Name) {
         if ($expr->name->parts[0] === 'true') {
             return new CompiledExpression(CompiledExpression::BOOLEAN, true);
         }
         if ($expr->name->parts[0] === 'false') {
             return new CompiledExpression(CompiledExpression::BOOLEAN, false);
         }
     }
     /**
      * @todo Implement check
      */
     $expression = new Expression($this->context);
     $compiledExpr = $expression->compile($expr->name);
     return $compiledExpr;
 }
예제 #18
0
 /**
  * @param \PhpParser\Node\Expr\FuncCall $expr
  * @return CompiledExpression[]
  */
 protected function parseArgs($expr, Context $context)
 {
     $arguments = array();
     foreach ($expr->args as $argument) {
         $expression = new Expression($context);
         $arguments[] = $expression->compile($argument->value);
     }
     return $arguments;
 }
예제 #19
0
 /**
  * @param object $expr
  * @param Context|null $expr
  * @return \PHPSA\CompiledExpression
  */
 protected function compileExpression($expr, Context $context = null)
 {
     $visitor = new Expression(is_null($context) ? $this->getContext() : $context);
     return $visitor->compile($expr);
 }