📄 ast.cs
字号:
if (t.IsEnum)
{
// If we imported the enum, it will import as a TypeEntry, but then we still
// don't have to add it.
EnumDecl e = ((EnumTypeEntry) f.Symbol.FieldType).Node;
if (e != null)
{
e.ReportClass(alClasses);
}
}
else if (t.IsValueType)
{
if (f.Symbol.FieldType.Node != null)
{
f.Symbol.FieldType.Node.ReportClass(alClasses);
}
}
}
}
#endif
// Now, add this class
alClasses.Add(this);
// Now that the outer type is added, make sure all nested classes
// get added.
foreach(TypeDeclBase t in this.m_alNestedTypes)
{
t.ReportClass(alClasses);
}
}
// Get the CLR type that this node represents. Useful for codegen.
public override System.Type CLRType
{
get {
return this.Symbol.CLRType;
}
}
#endregion
#region Resolve Types as Blue Stub
// Semantic checking
// Stubs can be resolved in any order.
public override void ResolveTypesAsBlueStub(
ISemanticResolver s,
string stNamespace,
Scope scopeParent
)
{
// Get our name. Nested classes are separated with a '+'
// Namespaces are separated with a '.'
string stFullName = (stNamespace == "") ?
(m_strName) :
(stNamespace + "." + m_strName);
// Are we a nested class?
if (scopeParent.Node is ClassDecl)
{
Debug.Assert(stNamespace != "");
stFullName = stNamespace + "+" + m_strName;
}
// Create a stub sym entry to add to current scope
m_symbol = new TypeEntry(stFullName, this, m_genre, scopeParent);
scopeParent.AddSymbol(m_symbol);
// Stub on nested types
//s.PushScope(m_symbol.MemberScope);
// Our context is the same as the scope on our symbol
Scope context = m_symbol.MemberScope;
Debug.Assert(context != null);
s.SetCurrentClass(m_symbol);
foreach(TypeDeclBase t in this.m_alNestedTypes)
{
t.ResolveTypesAsBlueStub(s, stFullName, context);
}
s.SetCurrentClass(null);
//s.PopScope(m_symbol.MemberScope);
}
#endregion
#region Resolve Type as CLR
// Called after we've resolved as a blue type
// Pair this type with a CLR type obtained via the Provider
// Recursively call on all inherited types (base class & interfaces)
public override void ResolveTypesAsCLR(
ISemanticResolver s,
ICLRtypeProvider provider
)
{
// Since this can be called recursively, bail if we're already resolved.
if (this.Symbol.IsInit)
return;
// S is already set to the context that we're evaluating in.
Scope prev = s.SetCurrentContext(this.Symbol.MemberScope.LexicalParent);
FixBaseTypes(s, provider); // this is recursive
CreateCLRType(s, provider);
s.RestoreContext(prev);
}
// Now that all the types have been stubbed and established their context,
// we can recursively run through and resolve all of our base types.
void FixBaseTypes(
ISemanticResolver s,
ICLRtypeProvider provider
)
{
TypeEntry tSuper = null;
BeginCheckCycle(s);
ArrayList alInterfaces = new ArrayList();
// Decide who our super class is and which interfaces we're inheriting
foreach(TypeSig sig in this.m_arSuper)
{
sig.ResolveType(s);
TypeEntry t = sig.BlueType;
// Make sure this base type is resolved. Do this recursively
ClassDecl c = t.Node;
if (c != null)
{
c.ResolveTypesAsCLR(s, provider);
}
if (t.IsClass)
{
Debug.Assert(this.IsClass, "Only a class can have a super-class");
if (tSuper != null)
{
ThrowError(SymbolError.OnlySingleInheritence(this));
}
tSuper = t;
} else {
// Both structs & interfaces can only derive from interfaces (not classes)
if (!t.IsInterface)
ThrowError(SymbolError.MustDeriveFromInterface(this, t));
alInterfaces.Add(t);
}
}
TypeEntry [] tInterfaces = new TypeEntry[alInterfaces.Count];
for(int i = 0; i < alInterfaces.Count; i++)
tInterfaces[i] = (TypeEntry) alInterfaces[i];
// If no super class is specified, then we use as follows:
// 'Interface' has no super class,
// 'Class' has 'System.Object'
// 'Struct' has 'System.ValueType'
if (!IsInterface && (tSuper == null))
{
if (IsClass)
tSuper = s.ResolveCLRTypeToBlueType(typeof(object));
if (IsStruct)
tSuper = s.ResolveCLRTypeToBlueType(typeof(System.ValueType));
}
Debug.Assert(IsInterface ^ (tSuper != null));
// Just to sanity check, make sure the symbol stub is still there
#if DEBUG
TypeEntry sym = (TypeEntry) s.GetCurrentContext().LookupSymbolInThisScopeOnly(m_strName);
Debug.Assert(sym == m_symbol);
#endif
m_symbol.InitLinks(tSuper, tInterfaces);
// Make sure all of our base types are resolved
foreach(TypeEntry t in this.Symbol.BaseInterfaces)
{
t.EnsureResolved(s);
}
if (Symbol.Super != null)
Symbol.Super.EnsureResolved(s);
// Final call. Set super scope
m_symbol.FinishInit();
EndCheckCycle();
}
// Flag to help check for cyclical dependencies
bool m_fIsResolving;
protected void BeginCheckCycle(
ISemanticResolver s
)
{
// This may get called mutliple times (since we call it recursively,
// and we may have multiple derived classes). But it shouldn't
// get called from itself (which would imply circular reference)
if (m_fIsResolving)
{
ThrowError(SymbolError.CircularReference(this.Symbol));
/*
s.ThrowError(SemanticChecker.Code.cCircularReference,
this.Location, "Type '" + this.Symbol.FullName + "' is in a circular reference");
*/
}
m_fIsResolving = true;
}
protected void EndCheckCycle()
{
m_fIsResolving = false;
}
// Requires that all of our base types have been resolved.
void CreateCLRType(
ISemanticResolver s,
ICLRtypeProvider provider)
{
// Should have already resolved as a blue type
Debug.Assert(this.Symbol != null);
BeginCheckCycle(s);
// Now that all of our dependent classes have their clr type set,
// we can go ahead and set ours.
// Note that a derived class may have already set ours, so we have
// to check
if (Symbol.CLRType == null)
{
// Get the clr type and then update the symbol engine
this.Symbol.SetCLRType(provider);
s.AddClrResolvedType(this.Symbol);
}
Debug.Assert(this.Symbol.CLRType != null);
// Nested classes
foreach(TypeDeclBase t in this.m_alNestedTypes)
{
t.ResolveTypesAsCLR(s, provider);
}
EndCheckCycle();
}
#endregion // resolution
#region Resolve Members
// Make sure that all of our base types are resolved.
void FixBaseMemberDecls(ISemanticResolver s, ICLRtypeProvider provider)
{
if (this.IsClass)
{
if (this.Symbol.Super.Node != null)
this.Symbol.Super.Node.ResolveMemberDecls(s, provider);
}
foreach(TypeEntry t in this.Symbol.BaseInterfaces)
{
if (t.Node != null)
t.Node.ResolveMemberDecls(s, provider);
}
}
// Resolve all the fields in this type. Only class/struct should call
// this.
void FixFields(ISemanticResolver s, ICLRtypeProvider provider)
{
Debug.Assert(!IsInterface);
int cInstance = 0;
int cStatic = 0;
foreach(FieldDecl f in m_alFields)
{
f.ResolveMember(m_symbol, s, provider);
//f.Symbol.SetInfo(provider);
if (f.InitialExp != null)
if (f.Mods.IsStatic)
cStatic++;
else
cInstance++;
}
Statement [] stmtStatic = new Statement[cStatic];
Statement [] stmtInstance = new Statement[cInstance];
cStatic = 0;
cInstance = 0;
// Fields can have assignments. Make 2 helper functions to do
// assignment for static & instance fields
foreach(FieldDecl f in m_alFields)
{
if (f.InitialExp != null)
{
Statement stmt = new ExpStatement(new AssignStmtExp(
new SimpleObjExp(new Identifier(f.Name, f.Location)), f.InitialExp));
if (f.Mods.IsStatic)
{
stmtStatic[cStatic] = stmt;
cStatic++;
}
else
{
if (IsStruct)
{
//ThrowError_NoFieldInitForStructs(s, f);
ThrowError(SymbolError.NoFieldInitForStructs(f));
}
stmtInstance[cInstance] = stmt;
cInstance ++;
}
} // end has initializer expression
}
Debug.Assert(cStatic == stmtStatic.Length);
Debug.Assert(cInstance == stmtInstance.Length);
// Create methods to initialize the static & instance fields.
// Then the ctors can call these methods
if (cStatic != 0)
{
Modifiers mods = new Modifiers();
mods.SetStatic();
mods.SetPrivate();
m_nodeStaticInit = new MethodDecl(
new Identifier(".StaticInit", this.Location),
new ResolvedTypeSig(typeof(void), s),
new ParamVarDecl[0],
new BlockStatement(null, stmtStatic),
mods
);
//AddMethodToList(m_nodeStaticInit);
}
if (cInstance != 0)
{
Modifiers mods = new Modifiers();
mods.SetPrivate();
m_nodeInstanceInit = new MethodDecl(
new Identifier(".InstanceInit", this.Location),
new ResolvedTypeSig(typeof(void), s),
new ParamVarDecl[0],
new BlockStatement(null, stmtInstance),
mods
);
AddMethodToList(m_nodeInstanceInit);
}
} // end fields
// Debug only, make sure that we don't add methods after we start resolving them.
#if DEBUG
bool m_fLockMethodList;
#endif
void FixMethods(
ISemanticResolver s,
ICLRtypeProvider provider
)
{
#if DEBUG
Debug.Assert(!m_fLockMethodList);
m_fLockMethodList = true;
#endif
// Resolve all methods, do some inheritence checks too:
// - if a class has any abstract members, it must be abstract
bool fHasAbstractMember = false;
foreach(MethodDecl m in m_alMethods)
{
// set provider=null since we have to tweak members based off inheritence checks
m.ResolveMember(m_symbol, s, null);
if (m.Mods.IsAbstract)
fHasAbstractMember = true;
}
Debug.Assert(!fHasAbstractMember || !this.IsStruct, "Only classes / interfaces can have abstract members");
// If we have any abstract members, then the class must be abstract
if (fHasAbstractMember && !this.Mods.IsAbstract)
PrintError(SymbolError.ClassMustBeAbstract(this));
// Do some checks that will modify how we create the CLR type.
if (!IsInterface)
{
// Make sure that we implement all methods from all the interfaces
// that we inherit from
foreach(TypeEntry t in this.Symbol.BaseInterfaces)
EnsureMethodsImplemented(s, t);
}
foreach(MethodDecl m in m_alMethods)
{
m.Symbol.SetInfo(provider);
// If a method is 'override', an exact match must exist in a super clas that:
// a) is marked 'override' also
// b) is marked 'virtual'
if (m.Mods.IsOverride)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -