// An ObjExp is just a temporary node. But that's the best a Context-Free parse can // do. So now that we're building a symbol table, we can do a Context-Sensitive resolution // and figure out what type of node this really is. public Exp GetResolvedNode(ISemanticResolver s, bool fRight) { Exp eResolved = null; // Lookup the symbol and determine what we are //SymEntry sym = s.LookupSymbol(this.m_strId, true); string stName = this.m_strId.Text; SymEntry sym = s.LookupSymbolWithContext(this.m_strId, false); // allow methods // Namespace if (sym is NamespaceEntry) { eResolved = new NamespaceExp(sym as NamespaceEntry); } // Local Variable else if (sym is LocalVarExpEntry) { eResolved = new LocalExp(sym as LocalVarExpEntry); } // Parameter else if (sym is ParamVarExpEntry) { eResolved = new ParamExp(sym as ParamVarExpEntry); } // A type name else if (sym is TypeEntry) { eResolved = new TypeExp(sym as TypeEntry); } // A field (w/ an implied 'this' pointer) else if (sym is FieldExpEntry) { // When a single identifier resolves to a field, it can be either // an instance field with an implied 'this' ref, or a static field of this class. FieldExpEntry f = sym as FieldExpEntry; Exp expInstance = null; if (!f.IsStatic) { expInstance = new SimpleObjExp("this"); Exp.ResolveExpAsRight(ref expInstance, s); } eResolved = new FieldExp(f, expInstance); } // An event (w/ an implied 'this' ptr) else if (sym is EventExpEntry) { EventExpEntry e = (EventExpEntry) sym; Exp expInstance = null; if (!e.Mods.IsStatic) { expInstance = new SimpleObjExp("this"); Exp.ResolveExpAsRight(ref expInstance, s); } eResolved = new EventExp(e, expInstance); } // A property (w/ an implied 'this' ptr). // Properties will eventually be converted into method calls. else if (sym is PropertyExpEntry) { PropertyExpEntry p = (PropertyExpEntry) sym; Exp expInstance = null; if (!p.IsStatic) { expInstance = new SimpleObjExp("this"); Exp.ResolveExpAsRight(ref expInstance, s); } eResolved = new PropertyExp(p, expInstance); } // Not recognized. else { if (stName == "this") // check a common error case... Debug.Assert(false, "Can't access 'this'. Are we in a static?"); if (sym == null) { MethodHeaderEntry h = s.GetCurrentClass().LookupMethodHeader(this.m_strId.Text); if (h != null) { return this; } ThrowError(SymbolError.UndefinedSymbol(m_strId)); //Debug.Assert(false, "Unknown name in SimpleObjExp:" + stName); } Debug.Assert(false, "Unknown symbol type:" + ((sym == null) ? "null" : sym.ToString())); } Debug.Assert(eResolved != null); return eResolved; }
// An ObjExp is just a temporary node. But that's the best a Context-Free parse can // do. So now that we're building a symbol table, we can do a Context-Sensitive resolution // and figure out what type of node this really is. public Exp GetResolvedNode(ISemanticResolver s) { string stText = this.m_strId.Text; // Left must already be resolved, then we resolve right in the context of left Debug.Assert(m_left != null); Exp eResolved = null; // @todo, what if left is a NullExp? if (m_left is NamespaceExp) { // We're either a nested namespace or a class NamespaceEntry n = (m_left as NamespaceExp).Symbol; SymEntry sym = n.ChildScope.LookupSymbol(stText); if (sym is NamespaceEntry) { eResolved = new NamespaceExp(sym as NamespaceEntry); } else if (sym is TypeEntry) { eResolved = new TypeExp(sym as TypeEntry); } else { //ThrowError_UndefinedSymbolInNamespace(s, n, m_strId); ThrowError(SymbolError.UndefinedSymbolInNamespace(n, m_strId)); } } // Check for statics else if (m_left is TypeExp) { TypeEntry t = ((TypeExp) m_left).Symbol; t.EnsureResolved(s); SymEntry sym = t.MemberScope.LookupSymbol(stText); if (sym is FieldExpEntry) { Debug.Assert(((FieldExpEntry) sym).IsStatic); eResolved = new FieldExp(sym as FieldExpEntry, null); // static } else if (sym is PropertyExpEntry) { eResolved = new PropertyExp(sym as PropertyExpEntry, null); } else if (sym is EventExpEntry) { eResolved = new EventExp(sym as EventExpEntry, null); } // Allow nested types else if (sym is TypeEntry) { eResolved = new TypeExp(sym as TypeEntry); } else { // Must be a method. The node transform occurs higher up though. Debug.Assert((sym = t.LookupMethodHeader(stText)) != null); eResolved = this; } if (eResolved == null) { //ThrowError_UndefinedSymbolInType(s, t, m_strId); ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId)); } } // m_left is a variable, and we're doing an instance member dereference else { TypeEntry t = null; t = s.ResolveCLRTypeToBlueType(this.m_left.CLRType); t.EnsureResolved(s); Scope scope = t.MemberScope; // @todo - broken for an interface. IA : IB, scope for IA doesn't link to IB. SymEntry sym = scope.LookupSymbol(stText); if (sym is FieldExpEntry) { eResolved = new FieldExp(sym as FieldExpEntry, this.m_left); } else if (sym is PropertyExpEntry) { eResolved = new PropertyExp(sym as PropertyExpEntry, this.m_left); } else if (sym is EventExpEntry) { eResolved = new EventExp(sym as EventExpEntry, this.m_left); } else { // Must be a method. The node transform occurs higher up though. sym = t.LookupMethodHeader(stText); if (sym != null) eResolved = this; } if (eResolved == null) { ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId)); } } Debug.Assert(eResolved != null); return eResolved; }
// See section 10.7 of the C# spec. // Outside of our class, we can only use an event as the LS in += and -= // However, within our class, we can use an event on the RS, like a delegate. // This is a little goofy. // We can actually never use an event on the RS. When try to, we're actually // using a compiler generated delegate (that has the exact same name) instead. // However, we can't put both an event & a delegate in the same scope (because // the names would conflict). So the delegate has a different name than the event. // When the user tries to access an event as a RHS, we switch it to the delegate here. protected override Exp ResolveExpAsRight(ISemanticResolver s) { FieldExpEntry f = m_symbol.Field; if (f == null) { // Events aren't allowed as RHS expressions. ThrowError(SymbolError.NoEventOnRHS(this)); } Exp e = new FieldExp(f, this.InstanceExp); Exp.ResolveExpAsRight(ref e, s); return e; }