Resolves PHP or Zephir constants into C-Code
Beispiel #1
0
 /**
  * Process the value of the class constant if needed
  *
  * @param compilationContext $compilationContext
  */
 public function processValue($compilationContext)
 {
     if ($this->value['type'] == 'constant') {
         $constant = new Constants();
         $compiledExpression = $constant->compile($this->value, $compilationContext);
         $this->value = array('type' => $compiledExpression->getType(), 'value' => $compiledExpression->getCode());
         return;
     }
     if ($this->value['type'] == 'static-constant-access') {
         $expression = new Expression($this->value);
         $compiledExpression = $expression->compile($compilationContext);
         $this->value = array('type' => $compiledExpression->getType(), 'value' => $compiledExpression->getCode());
         return;
     }
 }
Beispiel #2
0
 /**
  * Produce the code to register a class constant
  *
  * @param CompilationContext $compilationContext
  * @throws CompilerException
  * @throws Exception
  */
 public function compile(CompilationContext $compilationContext)
 {
     if ($this->value['type'] == 'static-constant-access') {
         $name = $this->value['left']['value'] . '::' . $this->value['right']['value'];
         if (defined($name)) {
             $value = constant($name);
             if (is_int($value)) {
                 $this->value['type'] = 'int';
                 $this->value['value'] = $value;
             } elseif (is_float($value)) {
                 $this->value['type'] = 'double';
                 $this->value['value'] = $value;
             } elseif (is_bool($value)) {
                 $this->value['type'] = 'bool';
                 if (!$value) {
                     $this->value['value'] = 'false';
                 } else {
                     $this->value['value'] = 'true';
                 }
             } elseif (is_string($value)) {
                 $this->value['type'] = 'string';
                 $this->value['value'] = $value;
             } elseif (is_null($value)) {
                 $this->value['type'] = 'null';
             }
         }
     }
     switch ($this->value['type']) {
         case 'constant':
             $constant = new Constants();
             $compiledExpression = $constant->compile($this->value, $compilationContext);
             $this->value['type'] = $compiledExpression->getType();
             $this->value['value'] = $compiledExpression->getCode();
             /**
              * With no-break this will be broken (unexpected), use re-compile for new type pass
              * @todo review variant without break
              */
             $this->compile($compilationContext);
             break;
         case 'long':
         case 'int':
             $compilationContext->codePrinter->output("zend_declare_class_constant_long(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), " . $this->value['value'] . " TSRMLS_CC);");
             break;
         case 'double':
             $compilationContext->codePrinter->output("zend_declare_class_constant_double(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), " . $this->value['value'] . " TSRMLS_CC);");
             break;
         case 'bool':
             if ($this->value['value'] == 'false') {
                 $compilationContext->codePrinter->output("zend_declare_class_constant_bool(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), 0 TSRMLS_CC);");
             } else {
                 $compilationContext->codePrinter->output("zend_declare_class_constant_bool(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), 1 TSRMLS_CC);");
             }
             break;
         case 'string':
         case 'char':
             $compilationContext->codePrinter->output("zend_declare_class_constant_string(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), \"" . Utils::addSlashes($this->value['value']) . "\" TSRMLS_CC);");
             break;
         case 'null':
             $compilationContext->codePrinter->output("zend_declare_class_constant_null(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\") TSRMLS_CC);");
             break;
         default:
             throw new CompilerException('Type "' . $this->value['type'] . '" is not supported.');
     }
 }
Beispiel #3
0
 /**
  * Resolves an expression
  *
  * @param CompilationContext $compilationContext
  * @return bool|CompiledExpression|mixed
  * @throws CompilerException
  */
 public function compile(CompilationContext $compilationContext)
 {
     $expression = $this->_expression;
     $type = $expression['type'];
     switch ($type) {
         case 'null':
             return new LiteralCompiledExpression('null', null, $expression);
         case 'int':
         case 'integer':
             return new LiteralCompiledExpression('int', $expression['value'], $expression);
         case 'long':
             return new LiteralCompiledExpression('long', $expression['value'], $expression);
         case 'double':
             return new LiteralCompiledExpression('double', $expression['value'], $expression);
         case 'bool':
             return new LiteralCompiledExpression('bool', $expression['value'], $expression);
         case 'string':
             if (!$this->_stringOperation) {
                 if (ctype_digit($expression['value'])) {
                     return new CompiledExpression('int', $expression['value'], $expression);
                 }
             }
             return new LiteralCompiledExpression('string', str_replace(PHP_EOL, '\\n', $expression['value']), $expression);
         case 'istring':
             return new LiteralCompiledExpression('istring', str_replace(PHP_EOL, '\\n', $expression['value']), $expression);
         case 'char':
             if (!strlen($expression['value'])) {
                 throw new CompilerException("Invalid empty char literal", $expression);
             }
             if (strlen($expression['value']) > 2) {
                 if (strlen($expression['value']) > 10) {
                     throw new CompilerException("Invalid char literal: '" . substr($expression['value'], 0, 10) . "...'", $expression);
                 } else {
                     throw new CompilerException("Invalid char literal: '" . $expression['value'] . "'", $expression);
                 }
             }
             return new LiteralCompiledExpression('char', $expression['value'], $expression);
         case 'variable':
             return new CompiledExpression('variable', $expression['value'], $expression);
         case 'constant':
             $constant = new Constants();
             $constant->setReadOnly($this->isReadOnly());
             $constant->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $constant->compile($expression, $compilationContext);
         case 'empty-array':
             return $this->emptyArray($expression, $compilationContext);
         case 'array-access':
             $arrayAccess = new NativeArrayAccess();
             $arrayAccess->setReadOnly($this->isReadOnly());
             $arrayAccess->setNoisy($this->isNoisy());
             $arrayAccess->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $arrayAccess->compile($expression, $compilationContext);
         case 'property-access':
             $propertyAccess = new PropertyAccess();
             $propertyAccess->setReadOnly($this->isReadOnly());
             $propertyAccess->setNoisy($this->isNoisy());
             $propertyAccess->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $propertyAccess->compile($expression, $compilationContext);
         case 'property-string-access':
         case 'property-dynamic-access':
             $propertyAccess = new PropertyDynamicAccess();
             $propertyAccess->setReadOnly($this->isReadOnly());
             $propertyAccess->setNoisy($this->isNoisy());
             $propertyAccess->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $propertyAccess->compile($expression, $compilationContext);
         case 'static-constant-access':
             $staticConstantAccess = new StaticConstantAccess();
             $staticConstantAccess->setReadOnly($this->isReadOnly());
             $staticConstantAccess->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $staticConstantAccess->compile($expression, $compilationContext);
         case 'static-property-access':
             $staticPropertyAccess = new StaticPropertyAccess();
             $staticPropertyAccess->setReadOnly($this->isReadOnly());
             $staticPropertyAccess->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $staticPropertyAccess->compile($expression, $compilationContext);
         case 'fcall':
             $functionCall = new FunctionCall();
             return $functionCall->compile($this, $compilationContext);
         case 'mcall':
             $methodCall = new MethodCall();
             return $methodCall->compile($this, $compilationContext);
         case 'scall':
             $staticCall = new StaticCall();
             return $staticCall->compile($this, $compilationContext);
         case 'isset':
             $expr = new IssetOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'fetch':
             $expr = new FetchOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'empty':
             $expr = new EmptyOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'array':
             $array = new NativeArray();
             $array->setReadOnly($this->isReadOnly());
             $array->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $array->compile($expression, $compilationContext);
         case 'new':
             $expr = new NewInstanceOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'new-type':
             $expr = new NewInstanceTypeOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'not':
             $expr = new NotOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_not':
             $expr = new BitwiseNotOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'equals':
             $expr = new EqualsOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'not-equals':
             $expr = new NotEqualsOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'identical':
             $expr = new IdenticalOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'not-identical':
             $expr = new NotIdenticalOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'greater':
             $expr = new GreaterOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'less':
             $expr = new LessOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'less-equal':
             $expr = new LessEqualOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'greater-equal':
             $expr = new GreaterEqualOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'add':
             $expr = new AddOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'minus':
             $expr = new MinusOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'sub':
             $expr = new SubOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'mul':
             $expr = new MulOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'div':
             $expr = new DivOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'mod':
             $expr = new ModOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'and':
             $expr = new AndOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'or':
             $expr = new OrOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_and':
             $expr = new BitwiseAndOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_or':
             $expr = new BitwiseOrOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_xor':
             $expr = new BitwiseXorOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_shiftleft':
             $expr = new ShiftLeftOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'bitwise_shiftright':
             $expr = new ShiftRightOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'concat':
             $expr = new ConcatOperator();
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'irange':
             $expr = new RangeInclusiveOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'erange':
             $expr = new RangeExclusiveOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'list':
             if ($expression['left']['type'] == 'list') {
                 $compilationContext->logger->warning("Unnecessary extra parentheses", "extra-parentheses", $expression);
             }
             $numberPrints = $compilationContext->codePrinter->getNumberPrints();
             $expr = new Expression($expression['left']);
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             $resolved = $expr->compile($compilationContext);
             if ($compilationContext->codePrinter->getNumberPrints() - $numberPrints <= 1) {
                 if (strpos($resolved->getCode(), ' ') !== false) {
                     return new CompiledExpression($resolved->getType(), '(' . $resolved->getCode() . ')', $expression);
                 }
             }
             return $resolved;
         case 'cast':
             $expr = new CastOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'type-hint':
             return $this->compileTypeHint($expression, $compilationContext);
         case 'instanceof':
             $expr = new InstanceOfOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'clone':
             $expr = new CloneOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'ternary':
             $expr = new TernaryOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'likely':
             if (!$this->_evalMode) {
                 throw new CompilerException("'likely' operator can only be used in evaluation expressions", $expression);
             }
             $expr = new LikelyOperator();
             $expr->setReadOnly($this->isReadOnly());
             return $expr->compile($expression, $compilationContext);
         case 'unlikely':
             if (!$this->_evalMode) {
                 throw new CompilerException("'unlikely' operator can only be used in evaluation expressions", $expression);
             }
             $expr = new UnlikelyOperator();
             $expr->setReadOnly($this->isReadOnly());
             return $expr->compile($expression, $compilationContext);
         case 'typeof':
             $expr = new TypeOfOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'require':
             $expr = new RequireOperator();
             $expr->setReadOnly($this->isReadOnly());
             $expr->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $expr->compile($expression, $compilationContext);
         case 'closure':
             $closure = new Closure();
             $closure->setReadOnly($this->isReadOnly());
             $closure->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $closure->compile($expression, $compilationContext);
         case 'closure-arrow':
             $closure = new ClosureArrow();
             $closure->setReadOnly($this->isReadOnly());
             $closure->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $closure->compile($expression, $compilationContext);
         case 'reference':
             $reference = new Reference();
             $reference->setReadOnly($this->isReadOnly());
             $reference->setExpectReturn($this->_expecting, $this->_expectingVariable);
             return $reference->compile($expression, $compilationContext);
         default:
             throw new CompilerException("Unknown expression: " . $type, $expression);
     }
 }
Beispiel #4
0
 /**
  * Produce the code to register a class constant
  *
  * @param CompilationContext $compilationContext
  * @throws CompilerException
  * @throws Exception
  */
 public function compile(CompilationContext $compilationContext)
 {
     if ($this->value['type'] == 'static-constant-access') {
         $this->resolveClassConstant();
     }
     switch ($this->value['type']) {
         case 'constant':
             $constant = new Constants();
             $compiledExpression = $constant->compile($this->value, $compilationContext);
             $this->value['type'] = $compiledExpression->getType();
             $this->value['value'] = $compiledExpression->getCode();
             $this->compile($compilationContext);
             return;
         case 'long':
         case 'int':
             $compilationContext->codePrinter->output("zend_declare_class_constant_long(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), " . $this->value['value'] . " TSRMLS_CC);");
             break;
         case 'double':
             $compilationContext->codePrinter->output("zend_declare_class_constant_double(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), " . $this->value['value'] . " TSRMLS_CC);");
             break;
         case 'bool':
             if ($this->value['value'] == 'false') {
                 $compilationContext->codePrinter->output("zend_declare_class_constant_bool(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), 0 TSRMLS_CC);");
             } else {
                 $compilationContext->codePrinter->output("zend_declare_class_constant_bool(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), 1 TSRMLS_CC);");
             }
             break;
         case 'string':
         case 'char':
             $compilationContext->codePrinter->output("zend_declare_class_constant_string(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\"), \"" . Utils::addSlashes($this->value['value']) . "\" TSRMLS_CC);");
             break;
         case 'null':
             $compilationContext->codePrinter->output("zend_declare_class_constant_null(" . $compilationContext->classDefinition->getClassEntry($compilationContext) . ", SL(\"" . $this->getName() . "\") TSRMLS_CC);");
             break;
         default:
             throw new CompilerException('Type "' . $this->value['type'] . '" is not supported.');
     }
 }