12 KiB
TypePHP 核心类 OOA / OOD / OOP 重构计划
1. 文档目的
本文档用于指导 Translator、CompilerBase、Preprocessor 的后续架构重构。实施时应逐阶段完成,不进行一次性重写。
当前基线:
| 类 | 行数 | 方法数 | 当前角色 |
|---|---|---|---|
Translator |
3717 | 126 | CLI、项目配置、代码生成、构建协调 |
CompilerBase |
3843 | 208 | 编译状态、AST 分派、Resolver、Emitter |
Preprocessor |
973 | 25 | 声明收集、AST lowering、依赖和语义验证 |
当前继承结构:
Translator
extends Preprocessor
extends CompilerBase
主要问题:
- 三个类形成继承式 God Object,高层流程可以访问全部底层可变状态。
- 大量 Trait 只完成了物理拆分,仍隐式依赖宿主的全部
$this字段。 - 前端分析、名称解析、语义验证、代码生成和 native build 缺少明确边界。
- 数组、AST attribute 和
string|false被用作模块间隐式协议。 resetFile()、resetClass()、resetFunction()等手工状态切换容易遗漏恢复。
2. 重构原则
- 行为保持优先,架构重构和语义修改分开提交。
- 先建立对象边界,再删除旧入口;迁移期允许新旧实现并存。
- 优先使用组合、接口、不可变值对象;业务 Trait 仅作为过渡方案。
- Handler Registry 使用节点类名直接索引,避免线性责任链造成编译性能下降。
- 编译状态必须通过 Context 或 Session 显式传递。
- Resolver 负责决策,Generator/Emitter 负责生成代码,两者不得混合。
- 每个阶段必须具备独立 PHPUnit 和对应 PHPT 回归证据。
3. OOA:领域对象分析
3.1 编译会话域
负责一次编译生命周期的状态:
CompilationSession
CompilerConfiguration
ScopeStack
ScopeFrame
FileContext
ClassContext
FunctionContext
3.2 前端分析域
负责 PHP 源码到已验证 AST/模型:
SourceParser
FrontendPipeline
DeclarationCollector
DependencyAnalyzer
SemanticAnalyzer
AstLoweringPass
3.3 解析域
负责符号和语言语义决策:
NameResolver
TypeResolver
MethodCallResolver
PropertyResolver
ConstantResolver
AccessPolicy
SymbolRepository
InheritanceGraph
3.4 代码生成域
负责 AST/实体模型到 C++:
ExpressionCompiler
StatementCompiler
ClassCodeGenerator
FunctionCodeGenerator
WrapperGenerator
ExtensionModuleGenerator
3.5 构建域
负责生成文件到最终产物:
SourcePipeline
NativeBuilder
ResourceCompiler
BuildModeStrategy
CompileOptions
LinkOptions
BuildResult
3.6 应用入口域
负责用户输入和顶层流程:
CompilerApplication
CompileCommand
CompilerFacade
ProjectYamlLoader
CommandLineInput
4. OOD:目标架构
CompilerApplication
└─ CompilerFacade
├─ ProjectLoader
├─ SourcePipeline
├─ FrontendPipeline
│ ├─ DeclarationCollector
│ ├─ AstLoweringPass[]
│ ├─ DependencyAnalyzer
│ └─ SemanticAnalyzer
├─ TranslationCodeGenerator
│ ├─ ExpressionCompiler
│ ├─ StatementCompiler
│ ├─ ClassCodeGenerator
│ └─ FunctionCodeGenerator
└─ NativeBuilder
4.1 Translator 的目标
Translator 最终作为 Facade/Coordinator,仅组织流程:
final class Translator
{
public function translate(ProjectInput $input): BuildResult;
}
禁止继续承担:
- CLI 参数解析;
- AST 节点语义判断;
- 类、函数和 wrapper 的 C++ 模板拼接;
- shell 命令执行;
- 前处理器内部状态。
4.2 Preprocessor 的目标
Preprocessor 改为独立 Frontend Service,不再继承 CompilerBase:
final class Preprocessor
{
public function process(SourceUnit $source, CompilationSession $session): PreprocessResult;
}
使用 Pipeline 模式组织 Pass:
ParseSourcePass
→ NameResolutionPass
→ PropertyHookLoweringPass
→ DeclarationCollectionPass
→ TraitExpansionPass
→ InheritanceValidationPass
→ TypeValidationPass
→ DependencyCollectionPass
4.3 CompilerBase 的目标
CompilerBase 最终被以下对象替代:
CompilationSession:编译生命周期状态;ExpressionCompiler:表达式 Handler 分派;StatementCompiler:语句 Handler 分派;CompilerServices:Resolver 和 Generator 集合;CodeGenerationContext:生成期上下文。
完成迁移后删除 CompilerBase,或仅保留短期兼容 Facade。
5. 设计模式应用
Facade
CompilerFacade 和最终的 Translator 提供稳定顶层入口,隐藏 Frontend、Generator、Builder 细节。
Pipeline
FrontendPipeline 显式维护前处理 Pass 顺序,每个 Pass 可独立测试。
Handler Registry
表达式和语句以 AST 类名进行 O(1) 分派:
$handlers[Expr\MethodCall::class] = $methodCallHandler;
Strategy
构建模式由以下策略实现:
BinaryBuildStrategyExtensionBuildStrategyLibraryBuildStrategyEmbedBuildStrategy
Chain of Responsibility
方法解析顺序:
DeclaredMethodResolver
→ ObjectExtensionMethodResolver
→ UniversalMethodResolver
→ MagicCallResolver
→ DynamicCallResolver
属性解析顺序:
BackingSlotResolver
→ PropertyHookResolver
→ DeclaredPropertyResolver
→ NativePropertyResolver
→ DynamicPropertyResolver
Repository
SymbolRepository 统一管理函数、类、接口、常量和继承关系;调用方不再自行处理 Repository key。
State / Scope Stack
使用 ScopeStack 和 ScopeGuard 替代 reset 系列方法,确保异常、Skip、Redo 时恢复状态。
Value Object / Result Object
逐步引入:
SourceUnitSourceLocationGeneratedExpressionGeneratedStatementResolvedCallResolvedPropertyAccessPreprocessResultTranslationResultBuildResult
6. OOP 渐进实施阶段
阶段 0:架构保护测试
任务:
- 建立表达式和语句节点覆盖清单;
- 增加 Frontend Pass 顺序测试;
- 增加 Scope 异常恢复测试;
- 增加 SymbolRepository 名称规范化测试;
- 固定 Property Hook、扩展方法、继承和异常测试集合;
- 对关键生成 C++ 建立快照或结构断言。
验收:
- PHPUnit 全量通过;
- 核心 PHPT 全部通过;
- 后续阶段可以识别 Handler 遗漏和求值顺序变化。
阶段 1:CompilationSession 与 ScopeStack
任务:
- 新建
CompilationSession、CompilerConfiguration、ScopeStack。 - 移入当前文件、namespace、class、method、function、PHP 版本和 phase 状态。
CompilerBase旧属性先代理到 Session。- 将 reset 系列方法替换为
enter/leave和try/finally。 - 删除代理属性。
验收:
CompilerBase不再直接拥有作用域状态;- 异常、
Skip、Redo不会污染下一作用域; - ScopeStack 有独立单测。
阶段 2:Preprocessor Pipeline
任务:
- 新建
FrontendPass和FrontendPipeline。 - 首先迁移 Property Hook lowering。
- 迁移声明收集和 namespace/use 处理。
- 迁移依赖收集与文件排序。
- 迁移 Trait、继承、override 和接口实现验证。
- 解除
Preprocessor extends CompilerBase。
验收:
- 每个 Pass 有独立测试;
- Pass 顺序只有一处定义;
Preprocessor.php控制在 200~300 行。
阶段 3:ExpressionCompiler
任务:
- 新建
ExpressionHandlerRegistry和GeneratedExpression。 - 按顺序迁移 scalar/const/variable、unary/binary/cast、array/assign。
- 迁移 function/method/static call。
- 迁移 property、nullsafe、isset/empty/ref。
- 迁移 closure、generator、fiber、new、clone、instanceof。
- 删除旧
parseExpr()大型分派。
验收:
- 每种已支持 Expr 都有唯一 Handler;
- Handler 不依赖
CompilerBase; - Registry 启动时检查重复和遗漏;
- 求值顺序和副作用测试全部通过。
阶段 4:StatementCompiler
任务:
- 新建
StatementHandlerRegistry和GeneratedStatement。 - 迁移 return/echo、条件、循环、异常控制流。
- 迁移 global/static/namespace/declare。
- 消除共享
beforeStmtLines、afterStmtLines协议。
验收:
- Statement Handler 返回显式 Result;
- 控制流生成从
CompilerBase移除; - before/after 语句通过 Result 组合。
阶段 5:Resolver Chain
任务:
- 建立
MethodCallResolverChain。 - 建立
PropertyResolverChain。 - 建立
ConstantResolverChain。 - 建立统一
AccessPolicy。 - 将
MethodCallTrait、PropertyAccessTrait、UniversalMethodCall、MagicMethodDetector迁入 Resolver。
验收:
- 普通方法、扩展方法、
__call()优先级只有一处定义; - backing slot、Property Hook 和普通属性优先级只有一处定义;
private(set)、protected(set)只由 AccessPolicy 判断;- Resolver 不再返回
string|false。
阶段 6:独立代码生成器
任务:
- 建立
ClassCodeGenerator; - 建立
FunctionCodeGenerator; - 建立
WrapperGenerator; - 建立
ExtensionModuleGenerator; - 将
parseClass()、parseFunction()、wrapper 和注册代码移出Translator。
验收:
- Generator 输入为 Entity/IR,输出为
GeneratedFile; Translator不再直接拼接具体 C++ 模板;- 关键生成结果具备快照测试。
阶段 7:Translator Facade
任务:
- 将 CLI 移到
CompilerApplication/CompileCommand。 Translator仅注入 ProjectLoader、Frontend、CodeGenerator、NativeBuilder。- 解除
Translator extends Preprocessor。 - 将公共入口收敛为
translate(ProjectInput): BuildResult。
验收:
Translator不解析 CLI;- 不直接访问 AST;
- 不直接执行 shell;
- 不依赖 Preprocessor 内部状态;
- 文件控制在 300~500 行。
阶段 8:删除 CompilerBase 继承体系
任务:
- 清除剩余兼容代理和业务 Trait。
- 将公共查询接口放入明确 Service/Context。
- 删除
Translator → Preprocessor → CompilerBase继承链。 - 删除无调用的旧方法和字段。
验收:
- 核心组件仅通过接口和 DTO 协作;
- 无业务 Trait 隐式访问宿主全部状态;
- 不存在超过约 800 行的核心类;
- PHPUnit、核心 PHPT 和多 PHP 版本构建全部通过。
7. 每阶段执行模板
每个阶段都按照以下步骤实施:
- 列出迁移方法、字段和调用方。
- 先补保护测试。
- 新建接口、DTO 和实现。
- 旧入口改为委托新实现。
- 批量迁移调用方。
- 删除旧实现和代理字段。
- 运行语法检查、PHPUnit 和对应 PHPT。
- 检查
git diff --check和未跟踪构建产物。 - 更新本文档中的阶段状态和实际偏差。
8. 建议目录
src/
├─ Application/
├─ Compiler/
│ └─ Scope/
├─ Frontend/
│ ├─ Pass/
│ └─ Result/
├─ CodeGeneration/
│ ├─ Expression/
│ └─ Statement/
├─ Resolver/
│ ├─ Call/
│ ├─ Property/
│ ├─ Constant/
│ └─ Access/
├─ Symbol/
├─ Build/
│ ├─ BuildMode/
│ └─ Options/
└─ Diagnostics/
9. 阶段状态
| 阶段 | 状态 |
|---|---|
| 0. 架构保护测试 | 待开始 |
| 1. CompilationSession / ScopeStack | 待开始 |
| 2. Preprocessor Pipeline | 待开始 |
| 3. ExpressionCompiler | 待开始 |
| 4. StatementCompiler | 待开始 |
| 5. Resolver Chain | 待开始 |
| 6. 独立代码生成器 | 待开始 |
| 7. Translator Facade | 待开始 |
| 8. 删除 CompilerBase 继承体系 | 待开始 |
实施过程中应持续更新此表,不允许仅根据文件行数宣布阶段完成。