在 Vczh Library++ 3.0 的開發過程中,ManagedX 這個模仿 C# 的語言近期完成了一項核心功能:編譯器對類型在其上下文中可見性的檢查。這項工作耗時約三小時,涉及複雜的符號表處理、泛型類型展開以及存取修飾符的遞歸驗證。本文將深入剖析其核心邏輯與實現細節。
ManagedX 將類型系統大幅簡化,所有類型最終歸結為三類:
函數指標、基本數值類型均被視為類處理。由於類型別名在符號表中不直接體現,編譯器需在語義分析階段進行展開替換。
考慮以下泛型類型定義:
generic<inout T>
class A
{
generic<inout U>
public using S = B<T, U>;
}
generic<inout T, inout U>
class B
{
public using T = Dictionary<T, U>;
}
以 A<int>.S<string>.T 為例,其展開前後的類型結構關係如下:
A<T>.S<U>.T,父類型為 A<int>.S<string>A.S = B<T,U>),替換泛型參數,最終得到 Dictionary<int, string>這一過程涉及 TypeSymbol 的巢狀結構,包含 GetSymbol()、GetParentType()、GetGenericDeclaration() 及 GetGenericArguments() 等關鍵屬性。
由於存在繼承關係、父子類型嵌套及類型別名,判斷 public、protected、private、internal、protected internal 的可見性變得極為複雜。核心邏輯封裝在 EnsureTypeVisibility 函數中。
AccessorthisTypes),允許 public/protected/internal/protected internalbaseTypes),允許 public/internal/protected internal(protected 需特殊處理)TypeRename 時,根據泛型參數替換計算其真實父類型,繼續向上檢查void EnsureTypeVisibility(
ManagedLanguageElement* languageElement,
ManagedTypeSymbol* type,
const MAP& argument,
List<ManagedTypeSymbol*>& thisTypes,
List<ManagedTypeSymbol*>& baseTypes
) {
// 1. 收集類型層級鏈
List<ManagedTypeSymbol*> typeLevels;
ManagedTypeSymbol* currentType = type;
while (currentType) {
typeLevels.Add(currentType);
currentType = currentType->GetGenericDeclaration()
? currentType->GetGenericDeclaration()->GetParentType()
: currentType->GetParentType();
}
// 2. 從外層向內層檢查
ManagedTypeSymbol* parentType = 0;
for (vint i = typeLevels.Count() - 1; i >= 0; i--) {
// ... 獲取當前宣告與存取修飾符 ...
// 3. 遞歸檢查泛型參數
if (currentType->GetGenericDeclaration()) {
FOREACH(ManagedTypeSymbol*, genericArgument, currentType->GetGenericArguments()) {
EnsureTypeVisibility(languageElement, genericArgument, argument, thisTypes, baseTypes);
}
}
// 4. 可見性判斷邏輯
if (parentType && !thisTypes.Contains(parentType)) {
if (baseTypes.Contains(parentType)) {
// 基類鏈規則
} else {
// 外部類型規則
}
}
// 5. 類型別名展開處理
if (currentSymbol->GetSymbolType() == ManagedSymbolItem::TypeRename) {
// 計算實際父類型
}
}
}
以 A<int>.S<string>.T 為例,驗證邏輯分解為:
A<int>.S<string> 是否可見A<int>.S<string> 得到 B<int, string>,檢查 B<int, string>.T 是否可見注意:B<int, string> 本身的可見性在 using S = ... 的語義分析階段已驗證,此處無需重複檢查,避免產生冗餘錯誤。
CollectBaseTypes 負責遞歸收集指定類型的所有基類(含泛型參數替換),為可見性判斷提供 baseTypes 列表。
ManagedX 的類型可見性檢查通過層級遍歷、泛型參數遞歸、存取修飾符規則匹配以及類型別名動態展開,實現了完整的編譯期類型存取控制。這一設計既處理了巢狀泛型類型的複雜性,又正確應用了 C# 風格的存取修飾符語義,為語言的型別安全奠定了堅實基礎。