// Resolve this array initializer list. // Provide with the type that we expect each element in the list to be public void Resolve(ISemanticResolver s, TypeEntry tExpected) { // Each node must either be an expression or a nested array initializer list //foreach(Node n in List) for(int i = 0; i < m_list.Length; i++) { Node n = m_list[i]; if (n is Exp) { Exp e = (Exp) n; Exp.ResolveExpAsRight(ref e, s); m_list[i] = e; s.EnsureAssignable(e, tExpected.CLRType); } else if (n is ArrayInitializer) { Debug.Assert(tExpected.IsArray); // @todo -legit ArrayInitializer a = (ArrayInitializer) n; TypeEntry tNested = tExpected.AsArrayType.ElemType; a.Resolve(s, tNested); } else { // Error Debug.Assert(false); // @todo - legit } } }
// 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); }
// Expose constructor that takes an already resolved type // Very useful when we build/modify parts of the AST during resolution public ResolvedTypeSig(TypeEntry t) { Debug.Assert(!t.IsRef, "Don't expect ref types"); Debug.Assert(t != null); m_type = t; }
// Semantic resolution public override void ResolveType(ISemanticResolver s) { if (m_type != null) return; Exp.ResolveExpAsRight(ref m_oeValue, s); Debug.Assert(m_oeValue is TypeExp); m_type = ((TypeExp) m_oeValue).Symbol; }
//TypeEntry m_symbol; #endregion #region Resolution // Helper function // Given a symbol for a delegate, get the params for it static public System.Type [] GetParams(TypeEntry t) { // We can do this by looking up the invoke function MethodHeaderEntry header = t.LookupMethodHeader("Invoke"); MethodExpEntry m = header.GetFirstMethod(); Debug.Assert(header.GetNextMethod(m) == null, "Delegate should only have 1 Invoke() method"); // Get parameters off this method System.Type [] al = m.ParamTypes(false); return al; }
// User defined events public EventExpEntry(TypeEntry tClass, AST.EventDecl e) { Debug.Assert(tClass != null); Debug.Assert(e != null); this.m_strName = e.Name.Text; this.m_type = e.EventType.BlueType; this.m_tClassDefined = tClass; this.m_node = e; this.m_mods = e.Mods; }
// Just check. This is useful because sometimes we want to fail if something // is a derived type (ex, CatchHandlers shouldn't be derived type of a previous handler) public bool IsDerivedType(TypeEntry tBase, TypeEntry tDerived) { // Note that System.Array is a derived type for all arrays, so special case that if (tBase.CLRType == typeof(System.Array)) { if (tDerived.IsArray) return true; } // @todo - For now, figure out how to safely convert System.Array to an array if (tDerived.CLRType == typeof(System.Array)) { if (tBase.CLRType == typeof(System.Array)) return true; } // Note that arrays may be different instances // but non arrays have only one TypeEntry per type // So peel off the arrays and get to the base type while (tBase.IsArray) { if (!tDerived.IsArray) return false; tBase = tBase.AsArrayType.ElemType; tDerived = tDerived.AsArrayType.ElemType; } // Compare innermost types if (tDerived.IsArray) { return false; } // Now walk up tDerived's chain looking for tBase TypeEntry t = tDerived; do { if (tBase == t) return true; t = t.Super; } while(t != null); // Ok. So tBase is not a base class of tDerived. Check if tBase is an interface // that tDerive implements if (tBase.IsInterface) { if (IsBaseInterface(tBase, tDerived)) return true; } return false; }
// Resolve the member given a symbol for the class we're defined in, a resolver, // and a provider public abstract void ResolveMember( TypeEntry symDefiningClass, ISemanticResolver s, ICLRtypeProvider provider );
// User-declared public MethodExpEntry( string stName, // name of the method AST.MethodDecl nodeClass, // node of ast defining us (can be null) TypeEntry tDefiningClass, // class we're defined in TypeEntry tReturnType // return type ) : this(stName, nodeClass, tDefiningClass, tReturnType, false) { }
// User-declared public MethodExpEntry( string stName, // name of the method AST.MethodDecl nodeClass, // node of ast defining us (can be null) TypeEntry tDefiningClass, // class we're defined in TypeEntry tReturnType, // return type bool fIsSpecialName ) { Debug.Assert(tDefiningClass != null); this.m_strName = stName; this.m_classDefined = tDefiningClass; this.m_decl = nodeClass; this.m_type = tReturnType; this.m_fIsSpecialName = fIsSpecialName; }
public FieldExpEntry( string stName, // name of this field TypeEntry tType, // type of this field TypeEntry tDefiningClassType, // type of class we're defined in AST.FieldDecl nodeDecl // AST node that we're defined at ) { m_strName = stName; m_type = tType; m_nodeDecl = nodeDecl; m_tClassDefined = tDefiningClassType; Debug.Assert(m_type != null); Debug.Assert(m_nodeDecl != null); // @todo - allow this for imports? Debug.Assert(m_tClassDefined != null); }
// Construction is the same as for Fields, #region Construction public LiteralFieldExpEntry( string stName, // name of this field TypeEntry tType, // type of this field TypeEntry tDefiningClassType, // type of class we're defined in AST.FieldDecl nodeDecl // AST node that we're defined at ) : base(stName, tType, tDefiningClassType, nodeDecl) { }
// Ctor for user-declared properties // We'll rip our data from the node public PropertyExpEntry ( TypeEntry tDefiningClassType, AST.PropertyDecl nodeDecl, AST.MethodDecl nodeGet, AST.MethodDecl nodeSet ) { Debug.Assert(nodeDecl != null); m_strName = nodeDecl.Name.Text; m_tClassDefined = tDefiningClassType; m_node = nodeDecl; m_type = nodeDecl.BlueType; m_symbolGet = (nodeGet == null) ? null : nodeGet.Symbol; m_symbolSet = (nodeSet == null) ? null : nodeSet.Symbol; m_mods = nodeDecl.Mods; }
// 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(); }
// Helper to check if tDerived implements the interface tBaseInterface. protected bool IsBaseInterface(TypeEntry tBaseInterface, TypeEntry tDerived) { Debug.Assert(tBaseInterface.IsInterface); if (tBaseInterface == tDerived) return true; // Check superclasses if (tDerived.Super != null) if (IsBaseInterface(tBaseInterface, tDerived.Super)) return true; // Check base interfaces foreach(TypeEntry ti in tDerived.BaseInterfaces) { if (IsBaseInterface(tBaseInterface, ti)) return true; } return false; }
// @todo - this is close, but wrong. See the C# specs on "Interface Mapping" for details. // Make sure that this class implements all methods on the interfaces it inherits. // Since an interface may inherit interfaces, we have to call recursively on the // interface tree to make sure we get them all. // Since properties are converted to methods, this will catch those too. void EnsureMethodsImplemented(ISemanticResolver s, TypeEntry tInterface) { Debug.Assert(tInterface.IsInterface); // Enforce that the type we're searching has indeed been fully populated. // Can't let anything slip through the cracks by adding a method after // we do this check... Debug.Assert(tInterface.MemberScope.IsLocked); string stMethod; TypeEntry t = this.Symbol; // For each method in this interface, look it up in the class to // make sure it's implemented foreach(SymEntry sym in tInterface.MemberScope) { if (!(sym is MethodExpEntry)) continue; MethodExpEntry mInterface = sym as MethodExpEntry; #if DEBUG stMethod = mInterface.PrettyDecoratedName; // helpful for debugging #endif MethodExpEntry m = t.LookupInterfaceMethod(mInterface, false); if (m == null) { // @todo - you're an idiot. Lookup in the C# spec and do it right. // @todo - This comment below is garbage. // There's one crazy little case where an error is too conservative: // IA IA.f() // CA : IA CA.f() // CA2 : CA, IA2 // CA2 does not define f(), but it inherits CA.f(). Normally this is // not ok, but since CA implements IA, it is. // So if we're missing, check for it in our super class // @todo - do we have to make sure that CA inherits from IA? m = t.LookupInterfaceMethod(mInterface, true); if (m == null) ThrowError(SymbolError.MissingInterfaceMethod(this.Location, mInterface, t)); } else { if (!m.Node.Mods.IsPublic) ThrowError(SymbolError.IMethodMustBePublic(this.Location, mInterface, t)); // If there's no 'virtual' / 'abstract' on an interface method, // then it's implicitily virtual & sealed. if (!m.Node.Mods.IsVirtual && !m.Node.Mods.IsAbstract) { m.Node.MarkAsVirtual(); m.Node.MarkAsFinal(); } } } // Ensure that we implement all the methods that the interface inherits foreach(TypeEntry tBase in tInterface.BaseInterfaces) EnsureMethodsImplemented(s, tBase); }
public void AddClrResolvedType(TypeEntry sym) { Debug.Assert(sym != null); Debug.Assert(sym.CLRType != null); // Make sure the blue & CLR types actually match. Debug.Assert(sym.FullName == sym.CLRType.FullName); /////// System.Type tEnum = sym.CLRType; /* int iEnum1 = tEnum.GetHashCode(); int iEnum2 = ((object) tEnum).GetHashCode(); int iInt1 = typeof(int).GetHashCode(); int iInt2 = ((object) typeof(int)).GetHashCode(); bool fFlag1 = Object.Equals(tEnum, typeof(int)); bool fFlag2 = Object.Equals(typeof(int), tEnum); bool f3 = (tEnum == typeof(int)); bool f4 = (typeof(int) == tEnum); */ ////////// try { m_hashClrType.Add(sym.CLRType, sym); } catch (System.Exception e) { object o = m_hashClrType[sym.CLRType]; Debug.Assert(false, "Exception:"+ e.Message); } }
// Resolve the events public override void ResolveMember( TypeEntry symDefiningClass, ISemanticResolver s, ICLRtypeProvider provider ) { m_tType.ResolveType(s); m_symbol = new EventExpEntry(symDefiningClass, this); s.GetCurrentContext().AddSymbol(m_symbol); // If an event has no handlers if (m_addMethod == null && m_addMethod == null) { FixDefaultHandlers(symDefiningClass, s, provider); } Debug.Assert(m_addMethod != null && m_removeMethod != null); Debug.Assert(m_addMethod.Symbol == null); // shouldn't have resolved handlers yet Debug.Assert(m_removeMethod.Symbol == null); // The handlers should be treated just like normal methods.. ClassDecl c = symDefiningClass.Node; c.AddMethodToList(m_addMethod); c.AddMethodToList(m_removeMethod); }
public void SetCurrentClass(TypeEntry type) { m_curClass = type; }
public DeclareLocalStmtExp(TypeEntry t) { LocalVarExpEntry l = new LocalVarExpEntry(); l.m_strName = ".temp_local_" + m_count; m_count++; l.m_type = t; m_exp = new LocalExp(l); }
public TypeExp(TypeEntry symbol) { m_symbol = symbol; }