TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
5.0 KiB
171 lines
5.0 KiB
<?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->symbols->putFunction($this->escapeFunction($name), $functionDef);
|
|
}
|
|
|
|
/**
|
|
* @param string $name 必须传入带有完整命名空间的类名,将会自动转义为 native name
|
|
*/
|
|
protected function hasFunction(string $name): bool
|
|
{
|
|
return $this->symbols->hasFunction($this->escapeFunction($name));
|
|
}
|
|
|
|
protected function getFunction(string $name): FunctionDef
|
|
{
|
|
return $this->symbols->function($this->escapeFunction($name));
|
|
}
|
|
|
|
protected function addClass(string $name, ClassDef $classDef): void
|
|
{
|
|
$this->symbols->putClass($this->escapeClass($name), $classDef);
|
|
}
|
|
|
|
protected function getClass(string $name): ClassDef
|
|
{
|
|
return $this->symbols->class($this->escapeClass($name));
|
|
}
|
|
|
|
public function getClassDef(string $name): ?ClassDef
|
|
{
|
|
return $this->symbols->findClass($this->escapeClass($name));
|
|
}
|
|
|
|
public function getParentClass(string $class): string
|
|
{
|
|
return $this->symbols->parent(strtolower(ltrim($class, '\\')));
|
|
}
|
|
|
|
protected function hasClass(string $name): bool
|
|
{
|
|
return $this->symbols->hasClass($this->escapeClass($name));
|
|
}
|
|
|
|
protected function hasInterface(string $name): bool
|
|
{
|
|
return $this->symbols->hasInterface($this->escapeClass($name));
|
|
}
|
|
|
|
protected function getInterface(string $name): InterfaceDef
|
|
{
|
|
return $this->symbols->interface($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();
|
|
}
|
|
}
|
|
}
|
|
|