- Extract const fetch logic from CompilerBase to ConstantExpressionTrait - Remove unused MagicConst import from CompilerBase - Add new ConstantExpressionTrait with complete constant handling implementation - Maintain all original constant parsing functionality in new trait structure - Update CompilerBase to use the new ConstantExpressionTrait - Remove duplicate constant-related methods from CompilerBasepull/17/head
parent
7fdf7213ce
commit
742820dc0f
2 changed files with 167 additions and 150 deletions
@ -0,0 +1,165 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* This file is part of TypePHP. |
||||||
|
* |
||||||
|
* @link https://www.swoole.com/ |
||||||
|
* @contact service@swoole.com |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace TypePhp\Parser; |
||||||
|
|
||||||
|
use PhpParser\Node; |
||||||
|
use PhpParser\Node\Expr; |
||||||
|
use PhpParser\Node\Scalar\MagicConst; |
||||||
|
use TypePhp\Symbol; |
||||||
|
|
||||||
|
trait ConstantExpressionTrait |
||||||
|
{ |
||||||
|
protected function parseConstFetch(Expr\ConstFetch $expr, bool $scalar = false): string |
||||||
|
{ |
||||||
|
if ($expr->name->getType() != 'Name' and !($expr->name instanceof Node\Name\FullyQualified)) { |
||||||
|
abort($expr); |
||||||
|
} |
||||||
|
$name = $this->parseIdentifier($expr->name); |
||||||
|
$name = ltrim($name, '\\'); |
||||||
|
if ($this->isNameExpr($expr->name) and $this->hasConstant($name)) { |
||||||
|
return $this->getConstant($name); |
||||||
|
} |
||||||
|
if ($this->namespace and $this->isNameExpr($expr->name) and !$expr->name instanceof Node\Name\FullyQualified) { |
||||||
|
$nsName = $this->namespace . '\\' . $name; |
||||||
|
if ($this->hasConstant($nsName)) { |
||||||
|
return $this->getConstant($nsName); |
||||||
|
} |
||||||
|
} |
||||||
|
if ($this->isNameExpr($expr->name) and isset($this->useConstants[$name])) { |
||||||
|
$importedName = $this->useConstants[$name]; |
||||||
|
if ($this->hasConstant($importedName)) { |
||||||
|
return $this->getConstant($importedName); |
||||||
|
} |
||||||
|
} |
||||||
|
if (strcasecmp($name, 'null') === 0) { |
||||||
|
return self::VALUE_NULL; |
||||||
|
} |
||||||
|
if (strcasecmp($name, 'true') === 0) { |
||||||
|
return 'true'; |
||||||
|
} |
||||||
|
if (strcasecmp($name, 'false') === 0) { |
||||||
|
return 'false'; |
||||||
|
} |
||||||
|
if ($name === 'PHP_EOL') { |
||||||
|
return '"' . $this->escapeString(PHP_EOL) . '"'; |
||||||
|
} |
||||||
|
if ($this->isInternalScalarConstant($name)) { |
||||||
|
return $this->getInternalScalarConstantValue($name); |
||||||
|
} |
||||||
|
if ($scalar) { |
||||||
|
return constant($expr->name); |
||||||
|
} |
||||||
|
if ($this->isNameExpr($expr->name)) { |
||||||
|
if (str_contains($name, '::')) { |
||||||
|
$ns = explode('::', $name)[0]; |
||||||
|
$fullName = $this->getNamespacedClassName($ns[0]); |
||||||
|
$ce = $this->getClassEntryPtr($fullName); |
||||||
|
return Symbol::constant() . '(' . $ce . ', ' . $this->getLiteralString($ns[1]) . ')'; |
||||||
|
} |
||||||
|
if ($this->isInternalConstant($name)) { |
||||||
|
return Symbol::constant() . '(' . $this->getLiteralString($name) . ')'; |
||||||
|
} |
||||||
|
if (isset($this->useAliases[$name])) { |
||||||
|
$name = $this->useAliases[$name]; |
||||||
|
} elseif (isset($this->useConstants[$name])) { |
||||||
|
$name = $this->useConstants[$name]; |
||||||
|
} else { |
||||||
|
$fullName = $this->getNamespacedClassName($name); |
||||||
|
if ($fullName) { |
||||||
|
$name = $fullName; |
||||||
|
} |
||||||
|
} |
||||||
|
return Symbol::constant() . '(nullptr, ' . $this->getLiteralString($name) . ')'; |
||||||
|
} |
||||||
|
return Symbol::constant() . '("' . $this->escapeString($name) . '")'; |
||||||
|
} |
||||||
|
|
||||||
|
protected function parseMagicConst(MagicConst $expr): string |
||||||
|
{ |
||||||
|
$class = ($this->namespace ? $this->namespace . '\\' : '') . $this->class; |
||||||
|
$function = ($this->namespace ? $this->namespace . '\\' : '') . $this->function; |
||||||
|
switch ($expr->getType()) { |
||||||
|
case 'Scalar_MagicConst_Dir': |
||||||
|
return '"' . $this->escapeString($this->dir) . '"'; |
||||||
|
case 'Scalar_MagicConst_File': |
||||||
|
return '"' . $this->escapeString($this->file) . '"'; |
||||||
|
case 'Scalar_MagicConst_Line': |
||||||
|
return (string) $expr->getStartLine(); |
||||||
|
case 'Scalar_MagicConst_Function': |
||||||
|
return '"' . $this->escapeString($function) . '"'; |
||||||
|
case 'Scalar_MagicConst_Class': |
||||||
|
if (!$this->classDef) { |
||||||
|
$this->fatalError($expr, 'The magic constant `__CLASS__` is not allowed in global scope'); |
||||||
|
} |
||||||
|
if ($this->classDef->trait) { |
||||||
|
return Symbol::getCalledClass(); |
||||||
|
} |
||||||
|
return '"' . $this->escapeString($class) . '"'; |
||||||
|
case 'Scalar_MagicConst_Trait': |
||||||
|
if (!$this->classDef or !$this->classDef->trait) { |
||||||
|
$this->fatalError($expr, 'The magic constant `__TRAIT__` is not allowed in global scope'); |
||||||
|
} |
||||||
|
return '"' . $this->escapeString($class) . '"'; |
||||||
|
case 'Scalar_MagicConst_Method': |
||||||
|
return '"' . $this->escapeString($class) . '::' . $this->escapeString($this->method) . '"'; |
||||||
|
default: |
||||||
|
abort($expr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected function detectConstType($expr): string |
||||||
|
{ |
||||||
|
$name = $this->parseIdentifier($expr->name); |
||||||
|
if ($this->hasConstant($name)) { |
||||||
|
return $this->getConstantType($name); |
||||||
|
} |
||||||
|
if ($this->isInternalConstant($name)) { |
||||||
|
return $this->getTypeFromZendType(gettype($this->internalConstants[$name])); |
||||||
|
} |
||||||
|
if (strcasecmp($name, 'true') === 0) { |
||||||
|
return self::TYPE_BOOL; |
||||||
|
} |
||||||
|
if (strcasecmp($name, 'false') === 0) { |
||||||
|
return self::TYPE_BOOL; |
||||||
|
} |
||||||
|
if ($name === 'NAN' or $name === 'INF') { |
||||||
|
return self::TYPE_FLOAT; |
||||||
|
} |
||||||
|
return self::TYPE_VAR; |
||||||
|
} |
||||||
|
|
||||||
|
protected function isInternalScalarConstant(string $name): bool |
||||||
|
{ |
||||||
|
return $this->isInternalConstant($name) && is_scalar($this->internalConstants[$name]); |
||||||
|
} |
||||||
|
|
||||||
|
protected function getInternalScalarConstantValue(string $name): string|int|float |
||||||
|
{ |
||||||
|
$value = $this->internalConstants[$name]; |
||||||
|
if (is_int($value)) { |
||||||
|
return $this->genIntegerLiteral($value); |
||||||
|
} |
||||||
|
if (is_float($value)) { |
||||||
|
if (is_nan($value)) { |
||||||
|
return self::VALUE_NAN; |
||||||
|
} |
||||||
|
if (is_infinite($value)) { |
||||||
|
return $value > 0 ? self::VALUE_INF : '-' . self::VALUE_INF; |
||||||
|
} |
||||||
|
return $this->genCValue($value); |
||||||
|
} |
||||||
|
if (is_bool($value)) { |
||||||
|
return $value ? 1 : 0; |
||||||
|
} |
||||||
|
if (is_string($value)) { |
||||||
|
return $this->genCharPtr($value, true); |
||||||
|
} |
||||||
|
$this->error('Unsupported constant type: ' . gettype($value)); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue