refactor(compiler): extract diagnostic and unary expression traits

- Move compiler diagnostic methods to CompilerDiagnosticTrait
- Extract unary expression parsing logic to UnaryExpressionTrait
- Remove unused TestError exception import
- Add proper trait usage in CompilerBase class
-
pull/17/head
韩天峰 2 months ago
parent 41aaff4094
commit 688993e587
  1. 121
      src/CompilerBase.php
  2. 65
      src/Diagnostics/CompilerDiagnosticTrait.php
  3. 82
      src/Parser/UnaryExpressionTrait.php

@ -15,6 +15,7 @@ use TypePhp\Build\NativeBuildConfigurationTrait;
use TypePhp\Entity\ArgInfo;
use TypePhp\Context\FunctionContext;
use TypePhp\Context\CompilationStateTrait;
use TypePhp\Diagnostics\CompilerDiagnosticTrait;
use TypePhp\Entity\ClassDef;
use TypePhp\Entity\ConstantDef;
use TypePhp\Entity\FunctionDef;
@ -24,7 +25,6 @@ use TypePhp\Entity\PropertyDef;
use TypePhp\Exception\DynamicCall;
use TypePhp\Exception\PlaceHolder;
use TypePhp\Exception\Redo;
use TypePhp\Exception\TestError;
use TypePhp\Generator\AnonClassGenerator;
use TypePhp\Generator\CallArgumentGenerator;
use TypePhp\Generator\ClosureGenerator;
@ -56,6 +56,7 @@ use TypePhp\Parser\SelectionExpressionTrait;
use TypePhp\Parser\SwitchTrait;
use TypePhp\Parser\TypeConversionTrait;
use TypePhp\Parser\TypeDetectionTrait;
use TypePhp\Parser\UnaryExpressionTrait;
use TypePhp\Parser\UniversalMethodCall;
use TypePhp\Optimizer\FuncCallOptimizer;
use TypePhp\Platform\Linux;
@ -97,6 +98,7 @@ class CompilerBase implements PropertyAccessContext
{
public const string DEFAULT_PHP_VERSION = '8.5';
use CompositeTypeCheckerTrait;
use CompilerDiagnosticTrait;
use CompilationStateTrait;
use NativeTypeCompatibilityTrait;
use NativeBuildConfigurationTrait;
@ -127,6 +129,7 @@ class CompilerBase implements PropertyAccessContext
use SwitchTrait;
use TypeConversionTrait;
use TypeDetectionTrait;
use UnaryExpressionTrait;
use AssignOpTrait;
use ArrayExpressionTrait;
use UniversalMethodCall;
@ -2622,49 +2625,6 @@ class CompilerBase implements PropertyAccessContext
return $result;
}
/**
* Report a compiler fatal error.
*/
public function error(string $msg): never
{
if ($this->forTest) {
throw new TestError($msg);
} else {
$this->climate->red("Fatal error: {$msg}");
if ($this->printBacktraceOnError) {
debug_print_backtrace();
}
exit(255);
}
}
public function fatalError(NodeAbstract $node, string $msg): never
{
$this->error("{$msg} in {$this->file}:{$node->getStartLine()}");
}
protected function warning(Node $node, string $msg): void
{
$this->climate->magenta("{$msg} in {$this->file}:{$node->getStartLine()}");
}
protected function errorUndefinedVariable(Variable $node): never
{
$this->fatalError($node, "The variable `\${$node->name}` is undefined");
}
protected function warningUndefinedBehavior(NodeAbstract $expr): void
{
$this->warning($expr, 'Use this expression carefully, which may be inconsistent with the dynamic execution behavior');
}
protected function dump(NodeAbstract $v): void
{
if ($this->debugLine == $v->getStartLine()) {
var_dump($v);
}
}
/**
* $GLOBALS['var'] 等价于 global $var; $var ,将字符串常量转为变量名称即可
* 仅限于字面量字符串可以转为变量名称,其他则使用 php::global() 函数获取
@ -2713,11 +2673,6 @@ class CompilerBase implements PropertyAccessContext
return false;
}
protected function foundStrayCode(Node $node): never
{
$this->fatalError($node, 'All execution code must be within a function, found stray code');
}
protected function checkInternalFunctionArgCount(string $funcName, Node\Expr\FuncCall $expr): void
{
$ref = Reflection::getFunction($funcName);
@ -2961,23 +2916,6 @@ class CompilerBase implements PropertyAccessContext
return $result;
}
protected function parseBitwiseNot(Expr\BitwiseNot $expr): string
{
$type = $this->detectTypeOfExpr($expr->expr);
$this->assertExprCanBeUsedAsValue($expr->expr, 'bitwise operand');
if ($type === self::TYPE_BIGINT) {
return 'php::BigInt::bitNot(' . $this->parseExpr($expr->expr) . ')';
}
$var = $this->parseIdentifier($expr->expr);
return '~' . $this->convertIntExpr($var);
}
protected function parseBooleanNot(Expr\BooleanNot $expr): string
{
$this->assertExprCanBeUsedAsCondition($expr->expr, 'boolean operand');
return '!(' . $this->parseExprAsValue($expr->expr) . ')';
}
protected function parsePrint(Expr\Print_ $expr): string
{
$this->assertExprCanBeUsedAsValue($expr->expr, 'print operand');
@ -3127,57 +3065,6 @@ class CompilerBase implements PropertyAccessContext
return $this->getClassEntryPtr($className);
}
protected function parseCastInt(Expr\Cast\Int_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertIntExpr($this->parseExprAsValue($node->expr));
}
protected function parseCastString(Expr\Cast\String_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertExprToStringByType(
$this->parseExprAsValue($node->expr),
$this->detectTypeOfExpr($node->expr)
);
}
protected function parseCastBool(Expr\Cast\Bool_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertBoolExpr($this->parseExprAsValue($node->expr));
}
protected function parseCastObject(Expr\Cast\Object_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertObjectExpr($this->parseExprAsValue($node->expr));
}
protected function parseUnaryMinus(Expr\UnaryMinus $expr): string
{
$type = $this->detectTypeOfExpr($expr->expr);
$this->assertExprCanBeUsedAsValue($expr->expr, 'unary operand');
if ($type === self::TYPE_BIGFLOAT) {
return 'php::BigFloat::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
if ($type === self::TYPE_BIGINT) {
return 'php::BigInt::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
if ($type === self::TYPE_DECIMAL) {
return 'php::Decimal::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
$code = $this->parseExprAsValue($expr->expr);
return '-' . $code;
}
protected function parseUnaryPlus(Expr\UnaryPlus $expr): string
{
$this->assertExprCanBeUsedAsValue($expr->expr, 'unary operand');
return $this->parseExprAsValue($expr->expr);
}
protected function parseInterpolatedString(Node\Scalar\InterpolatedString $expr): string
{
$parts = $expr->parts;

@ -0,0 +1,65 @@
<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace TypePhp\Diagnostics;
use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PhpParser\NodeAbstract;
use TypePhp\Exception\TestError;
trait CompilerDiagnosticTrait
{
/**
* Report a compiler fatal error.
*/
public function error(string $msg): never
{
if ($this->forTest) {
throw new TestError($msg);
}
$this->climate->red("Fatal error: {$msg}");
if ($this->printBacktraceOnError) {
debug_print_backtrace();
}
exit(255);
}
public function fatalError(NodeAbstract $node, string $msg): never
{
$this->error("{$msg} in {$this->file}:{$node->getStartLine()}");
}
protected function warning(Node $node, string $msg): void
{
$this->climate->magenta("{$msg} in {$this->file}:{$node->getStartLine()}");
}
protected function errorUndefinedVariable(Variable $node): never
{
$this->fatalError($node, "The variable `\${$node->name}` is undefined");
}
protected function warningUndefinedBehavior(NodeAbstract $expr): void
{
$this->warning($expr, 'Use this expression carefully, which may be inconsistent with the dynamic execution behavior');
}
protected function dump(NodeAbstract $node): void
{
if ($this->debugLine == $node->getStartLine()) {
var_dump($node);
}
}
protected function foundStrayCode(Node $node): never
{
$this->fatalError($node, 'All execution code must be within a function, found stray code');
}
}

@ -0,0 +1,82 @@
<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace TypePhp\Parser;
use PhpParser\Node\Expr;
trait UnaryExpressionTrait
{
protected function parseBitwiseNot(Expr\BitwiseNot $expr): string
{
$type = $this->detectTypeOfExpr($expr->expr);
$this->assertExprCanBeUsedAsValue($expr->expr, 'bitwise operand');
if ($type === self::TYPE_BIGINT) {
return 'php::BigInt::bitNot(' . $this->parseExpr($expr->expr) . ')';
}
$var = $this->parseIdentifier($expr->expr);
return '~' . $this->convertIntExpr($var);
}
protected function parseBooleanNot(Expr\BooleanNot $expr): string
{
$this->assertExprCanBeUsedAsCondition($expr->expr, 'boolean operand');
return '!(' . $this->parseExprAsValue($expr->expr) . ')';
}
protected function parseCastInt(Expr\Cast\Int_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertIntExpr($this->parseExprAsValue($node->expr));
}
protected function parseCastString(Expr\Cast\String_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertExprToStringByType(
$this->parseExprAsValue($node->expr),
$this->detectTypeOfExpr($node->expr)
);
}
protected function parseCastBool(Expr\Cast\Bool_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertBoolExpr($this->parseExprAsValue($node->expr));
}
protected function parseCastObject(Expr\Cast\Object_ $node): string
{
$this->assertExprCanBeUsedAsValue($node->expr, 'cast operand');
return $this->convertObjectExpr($this->parseExprAsValue($node->expr));
}
protected function parseUnaryMinus(Expr\UnaryMinus $expr): string
{
$type = $this->detectTypeOfExpr($expr->expr);
$this->assertExprCanBeUsedAsValue($expr->expr, 'unary operand');
if ($type === self::TYPE_BIGFLOAT) {
return 'php::BigFloat::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
if ($type === self::TYPE_BIGINT) {
return 'php::BigInt::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
if ($type === self::TYPE_DECIMAL) {
return 'php::Decimal::neg(' . $this->parseExprAsValue($expr->expr) . ')';
}
$code = $this->parseExprAsValue($expr->expr);
return '-' . $code;
}
protected function parseUnaryPlus(Expr\UnaryPlus $expr): string
{
$this->assertExprCanBeUsedAsValue($expr->expr, 'unary operand');
return $this->parseExprAsValue($expr->expr);
}
}
Loading…
Cancel
Save