- Move variable management methods to CompilationStateTrait - Extract class and function handling logic into separate trait - Removepull/17/head
parent
742820dc0f
commit
e9182ed5b6
2 changed files with 173 additions and 154 deletions
@ -0,0 +1,171 @@ |
||||
<?php |
||||
/** |
||||
* This file is part of TypePHP. |
||||
* |
||||
* @link https://www.swoole.com/ |
||||
* @contact service@swoole.com |
||||
*/ |
||||
|
||||
namespace TypePhp\Context; |
||||
|
||||
use PhpParser\Node\Expr\Variable; |
||||
use TypePhp\Entity\ClassDef; |
||||
use TypePhp\Entity\FunctionDef; |
||||
use TypePhp\Entity\InterfaceDef; |
||||
use TypePhp\Exception\Skip; |
||||
|
||||
trait CompilationStateTrait |
||||
{ |
||||
protected function addLocalVar(string $name, string $type): void |
||||
{ |
||||
$this->context->localVars[$name] = $type; |
||||
} |
||||
|
||||
protected function registerStdType(string $key): int |
||||
{ |
||||
if (isset($this->stdTypeMap[$key])) { |
||||
return $this->stdTypeMap[$key]; |
||||
} |
||||
$typeId = count($this->stdTypeMap) + 1; |
||||
$this->stdTypeMap[$key] = $typeId; |
||||
return $typeId; |
||||
} |
||||
|
||||
protected function addTmpVar(string $type): string |
||||
{ |
||||
$var = $this->genTmpVarName(); |
||||
$this->addLocalVar($var, $type); |
||||
return $var; |
||||
} |
||||
|
||||
protected function addStaticVar(Variable $var, string $name, string $type): string |
||||
{ |
||||
if ($this->hasVar($name)) { |
||||
$this->fatalError($var, 'Duplicate variable `$' . $var->name . '`'); |
||||
} |
||||
$this->context->staticVars[$name] = $type; |
||||
// 静态变量实际上是一个全局变量的引用 |
||||
$globalVar = $this->escapeStaticVar($name); |
||||
$this->addGlobalVar($globalVar, $type); |
||||
return $globalVar; |
||||
} |
||||
|
||||
protected function hasArgument(string $name): bool |
||||
{ |
||||
return isset($this->context->arguments[$name]); |
||||
} |
||||
|
||||
protected function addArgument(string $name, string $type): void |
||||
{ |
||||
$this->context->arguments[$name] = $type; |
||||
$this->addLocalVar($name, $type); |
||||
} |
||||
|
||||
protected function addLiteralString(string $value): int |
||||
{ |
||||
$index = $this->literalStringIndex++; |
||||
$this->literalStrings[$value] = $index; |
||||
|
||||
return $index; |
||||
} |
||||
|
||||
protected function addGlobalVar(string $name, string $type): void |
||||
{ |
||||
$this->globalVars[$name] = $type; |
||||
} |
||||
|
||||
protected function addScopeGlobalVar(string $name, string $type): void |
||||
{ |
||||
$this->context->globalVars[$name] = $type; |
||||
} |
||||
|
||||
protected function addObject(string $name, string $class): void |
||||
{ |
||||
// Interfaces have no concrete method body for native calls. Abstract classes may have concrete methods. |
||||
if ($this->isInterface($class)) { |
||||
$this->context->declaredObjects[$name] = $class; |
||||
} elseif ($this->isNativeClass($class) or $this->isInternalClass($class)) { |
||||
$this->context->objects[$name] = $class; |
||||
} |
||||
} |
||||
|
||||
protected function hasVar(string $name): bool |
||||
{ |
||||
return $this->hasLocalVar($name) || $this->hasStaticVar($name) || $this->hasScopeGlobalVar($name) || $this->isSuperGlobal($name); |
||||
} |
||||
|
||||
protected function hasLocalVar(string $name): bool |
||||
{ |
||||
return isset($this->context->localVars[$name]); |
||||
} |
||||
|
||||
protected function hasObjectPropVar(string $name): bool |
||||
{ |
||||
return isset($this->context->objectProps[$name]); |
||||
} |
||||
|
||||
protected function addFunction(string $name, FunctionDef $functionDef): void |
||||
{ |
||||
$this->functions[$this->escapeFunction($name)] = $functionDef; |
||||
} |
||||
|
||||
/** |
||||
* @param string $name 必须传入带有完整命名空间的类名,将会自动转义为 native name |
||||
*/ |
||||
protected function hasFunction(string $name): bool |
||||
{ |
||||
return array_key_exists($this->escapeFunction($name), $this->functions); |
||||
} |
||||
|
||||
protected function getFunction(string $name): FunctionDef |
||||
{ |
||||
return $this->functions[$this->escapeFunction($name)]; |
||||
} |
||||
|
||||
protected function addClass(string $name, ClassDef $classDef): void |
||||
{ |
||||
$this->classes[$this->escapeClass($name)] = $classDef; |
||||
} |
||||
|
||||
protected function getClass(string $name): ClassDef |
||||
{ |
||||
return $this->classes[$this->escapeClass($name)]; |
||||
} |
||||
|
||||
public function getClassDef(string $name): ?ClassDef |
||||
{ |
||||
return $this->classes[$this->escapeClass($name)] ?? null; |
||||
} |
||||
|
||||
public function getParentClass(string $class): string |
||||
{ |
||||
return $this->classExtends[strtolower(ltrim($class, '\\'))] ?? ''; |
||||
} |
||||
|
||||
protected function hasClass(string $name): bool |
||||
{ |
||||
return array_key_exists($this->escapeClass($name), $this->classes); |
||||
} |
||||
|
||||
protected function hasInterface(string $name): bool |
||||
{ |
||||
return array_key_exists($this->escapeClass($name), $this->interfaces); |
||||
} |
||||
|
||||
protected function getInterface(string $name): InterfaceDef |
||||
{ |
||||
return $this->interfaces[$this->escapeClass($name)]; |
||||
} |
||||
|
||||
protected function checkFunction(string $name): void |
||||
{ |
||||
// 在预处理阶段检测到函数声明,但是未定义,说明在当前文件,但是顺序错误 |
||||
// 跳过,稍后再处理 |
||||
if (isset($this->symbolDeclInFile[$name]) |
||||
and $this->symbolDeclInFile[$name] === $this->file |
||||
and !$this->hasFunction($name)) { |
||||
$this->redoAfterDeclare[$name] = true; |
||||
throw new Skip(); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue