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.
 
 

207 lines
5.3 KiB

<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Generator;
use PhpAot\Php\CompilerBase;
use PhpAot\Php\Constants;
trait Utils
{
protected function genIntegerLiteral(int $value): string
{
if ($value === PHP_INT_MIN) {
return 'ZEND_LONG_MIN';
}
if ($value === PHP_INT_MAX) {
return 'ZEND_LONG_MAX';
}
return $value . $this->getPlatform()->getIntegerLiteralSuffix();
}
protected function genCValue(mixed $value): mixed
{
if (is_int($value)) {
return $this->genIntegerLiteral($value);
}
if (is_float($value)) {
return $value;
}
if (is_bool($value)) {
return $value ? 1 : 0;
}
if (is_string($value)) {
return $this->genCharPtr($value);
} else {
$this->error('Unsupported constant type: ' . gettype($value));
}
}
public function genCharPtr(string $str, bool $escape = false): string
{
return '"' . ($escape ? $this->escapeString($str) : $str) . '"';
}
protected function genZendStrl(string $char): string
{
return 'ZEND_STRL(' . $this->genCharPtr($char) . ')';
}
protected function genArray(array $elements): string
{
return CompilerBase::TYPE_ARRAY . '{' . implode(', ', $elements) . ' }';
}
protected function genRawStr(string $str): string
{
return 'R"(' . $str . ')"';
}
public function escapeString(string $str): string
{
$str = addcslashes($str, "\\\"\n\r\t\v\f\0\x01..\x1f\x7f..\xff");
// C++ trigraph
return str_replace('??', '\?\?', $str);
}
protected function escapeBool(bool $bool): string
{
return $bool ? 'true' : 'false';
}
protected function escapeVarName(string $name): string
{
if ($name === 'this') {
return 'this_';
}
if (in_array($name, Constants::CPP_RESERVED_NAMES, true)) {
return '_php__var__' . $name;
}
return $name;
}
protected function escapeStaticVar(string $name): string
{
$prefix = '';
if ($this->namespace) {
$prefix .= $this->escapeNamespace($this->namespace) . '_';
}
if ($this->class) {
$prefix .= $this->escapeClass($this->class) . '_';
if ($this->method) {
$prefix .= $this->method . '_';
}
} else {
if ($this->function) {
$prefix .= $this->function . '_';
}
}
return $prefix . $name;
}
protected function escapeGlobalVar(string $name): string
{
return self::GLOBAL_VAR . $name;
}
protected function escapeConstVar(string $name): string
{
return self::CONST_VAR . str_replace('\\', self::NAMESPACE_SEPARATOR, $name);
}
protected function escapeNamespace(string $ns): string
{
return str_replace('\\', self::NAMESPACE_SEPARATOR, strtolower($ns));
}
protected function escapeZendFnName(string $fn, bool $lower = true): string
{
return str_replace('\\', '_', $lower ? strtolower($fn) : $fn);
}
protected function escapeCeName(string $name): string
{
return $this->escapeZendFnName($name, false);
}
protected function escapeName(string $name): string
{
return strtolower($name);
}
protected function escapeClass(string $class): string
{
return str_replace('\\', '_', trim(strtolower($class), '\\'));
}
protected function escapeFunction(string $func): string
{
return $this->escapeClass($func);
}
protected function escapeFileName(string $file): string
{
return str_replace('-', '_', $file);
}
protected function unescapeVarName(string $name): string
{
return str_replace('_php__var__', '', $name);
}
protected function isClosedExpr($expr, $call): bool
{
if ($call === '') {
if (!str_starts_with($expr, '(')) {
return false;
}
$startPos = 0;
} else {
if (!str_starts_with($expr, $call . '(')) {
return false;
}
$startPos = strlen($call);
}
$bracketCount = 0;
$length = strlen($expr);
for ($i = $startPos; $i < $length; $i++) {
$char = $expr[$i];
if ($char === '(') {
$bracketCount++;
} elseif ($char === ')') {
$bracketCount--;
if ($bracketCount === 0) {
return $i === $length - 1;
}
}
}
return false;
}
/**
* Strip PHP numeric literal underscores (e.g. 1_000_000 → 1000000).
*/
protected function stripNumericUnderscores(string $rawValue): string
{
return str_replace('_', '', $rawValue);
}
protected function getNamespaceOfClass(string $class): string
{
$lastPos = strrpos($class, '\\');
if ($lastPos !== false) {
$namespace = substr($class, 0, $lastPos);
} else {
$namespace = '';
}
return $namespace;
}
}