// Imported public MethodExpEntry( ISemanticResolver s, System.Reflection.MethodBase info // CLR info for this method ) { Debug.Assert(info != null); this.m_infoMethod = info; this.m_fIsSpecialName = info.IsSpecialName; this.m_strName = info.Name; this.m_classDefined = s.ResolveCLRTypeToBlueType(info.DeclaringType); // Set return type for non-constructors System.Reflection.MethodInfo mInfo = info as System.Reflection.MethodInfo; if (mInfo != null) { // not a ctor this.m_type = s.ResolveCLRTypeToBlueType(mInfo.ReturnType); } else { // ctor this.m_type = null; m_strName = m_classDefined.Name; } }
// Imported field public FieldExpEntry( ISemanticResolver s, System.Reflection.FieldInfo fInfo ) { m_strName = fInfo.Name; m_type = s.ResolveCLRTypeToBlueType(fInfo.FieldType); m_nodeDecl = null; m_tClassDefined = s.ResolveCLRTypeToBlueType(fInfo.DeclaringType); m_info = fInfo; }
public ResolvedTypeSig(System.Type t, ISemanticResolver s) { Debug.Assert(!t.IsByRef, "Don't expect ref types"); Debug.Assert(t != null); Debug.Assert(s != null); m_type = s.ResolveCLRTypeToBlueType(t); }
public override void DebugCheck(ISemanticResolver s) { Debug.Assert(m_type != null); TypeEntry t = BlueType; if (t.IsRef) return; System.Type clrType = t.CLRType; // Make sure that our CLR type matches our TypeEntry if (clrType != null) { // @todo - Enums aren't entered into the hash. if (!(t is EnumTypeEntry)) { TypeEntry t2 = s.ResolveCLRTypeToBlueType(clrType); Debug.Assert(t == t2); } } if (clrType == null) { // Even now, the only way we can have no clr type is if we // are a user declared class Debug.Assert(t.Node != null); } } // DebugCheck
// Create an array node given an existing CLR array type public ArrayTypeSig(System.Type tArray, ISemanticResolver s) { Debug.Assert(tArray != null); m_filerange = null; m_cDimension = tArray.GetArrayRank(); Debug.Assert(m_cDimension == 1, "@todo - only 1d arrays currently implemented"); m_ArrayTypeRec = s.ResolveCLRTypeToBlueType(tArray).AsArrayType; m_sigBase = null; // left as null. }
// Ctor for imported properties public PropertyExpEntry( ISemanticResolver s, System.Reflection.PropertyInfo info ) { m_info = info; m_strName = m_info.Name; // Class that we're defined in? System.Type tClrClass = info.DeclaringType; m_tClassDefined = s.ResolveCLRTypeToBlueType(tClrClass); // Symbol type this.m_type = s.ResolveCLRTypeToBlueType(info.PropertyType); // Spoof accessors if (info.CanRead) // Has Get { System.Reflection.MethodInfo mGet = info.GetGetMethod(); m_symbolGet = new MethodExpEntry(s, mGet); } if (info.CanWrite) // Has Set { System.Reflection.MethodInfo mSet = info.GetSetMethod(); m_symbolSet = new MethodExpEntry(s, mSet); } // Get modifiers System.Reflection.MethodInfo [] m = info.GetAccessors(); m_mods = new Modifiers(m[0]); /* * m_mods = new Modifiers(); * if (m[0].IsStatic) m_mods.SetStatic(); * if (m[0].IsAbstract) m_mods.SetAbstract(); * if (m[0].IsVirtual) m_mods.SetVirtual(); */ }
// Imported events public EventExpEntry( System.Reflection.EventInfo eInfo, ISemanticResolver s ) { Debug.Assert(eInfo != null); Debug.Assert(s != null); this.m_strName = eInfo.Name; this.m_tClassDefined = s.ResolveCLRTypeToBlueType(eInfo.DeclaringType); this.m_type = s.ResolveCLRTypeToBlueType(eInfo.EventHandlerType); this.m_node = null; System.Reflection.MethodInfo mAdd = eInfo.GetAddMethod(); System.Reflection.MethodInfo mRemove = eInfo.GetRemoveMethod(); SetAddMethod(new MethodExpEntry(s, mAdd)); SetRemoveMethod(new MethodExpEntry(s, mRemove)); this.m_mods = new Modifiers(mAdd); }
// Search for an overloaded operator. Return the symbol for the method if found. // Return null if not found. MethodExpEntry SearchForOverloadedOp(ISemanticResolver s) { Type [] alParams = new Type[2]; alParams[0] = m_left.CLRType; alParams[1] = m_right.CLRType; string stName = MethodDecl.GetOpOverloadedName(this.Op); MethodExpEntry sym; if (m_left.CLRType != null) { TypeEntry t1 = s.ResolveCLRTypeToBlueType(m_left.CLRType); sym = t1.LookupOverloadedOperator(s, stName, alParams); if (sym != null) return sym; } if (m_right.CLRType != null) { TypeEntry t2 = s.ResolveCLRTypeToBlueType(m_right.CLRType); sym = t2.LookupOverloadedOperator(s, stName, alParams); if (sym != null) return sym; } return null; }
// Determine the CLR Type of this expression // As a convenience, return the clr type to saves us from having to // call CLRType public System.Type CalcCLRType(ISemanticResolver s) { Type tOld = m_clrType; m_clrType = CalcCLRTypeHelper(s); Debug.Assert(m_clrType != null || Exp.CanBeNullType(this)); // Assert that if we called this multiple times, the value hasn't changed on us Debug.Assert(((tOld == null)) || (tOld == m_clrType)); // @todo - we don't resolve pointers yet.... // The only place we can use them is in evaluating a MethodPtr for a delegate ctor. if (m_clrType == Type.GetType("System.IntPtr")) { Debug.Assert(this is MethodPtrExp); return m_clrType; } // @todo - move this into a place w/ better perf... // EnsureResolved if (m_clrType != null) { TypeEntry t = s.ResolveCLRTypeToBlueType(m_clrType); t.EnsureResolved(s); } return m_clrType; }
// Internal helper. Since the left & right cases are close enough // we want to merge them into a function. private Exp ResolveInternal(ISemanticResolver s, bool fIsLeft) { ResolveExpAsRight(ref m_oeLeft, s); ResolveExpAsRight(ref m_expIndex, s); // @todo - check that m_expIndex is an integer // Check for indexers: // If the Left is not an array, then we must be an indexer. // Strip references, So T[]& --> T[] System.Type t = m_oeLeft.CLRType; if (t.IsByRef) t = t.GetElementType(); if (!t.IsArray) { m_fIsIndexer = true; // If we're the leftside, we have a problem. We don't know the exp on the RS, // so we don't have a full signature, so we don't know what we're supposed to // change too. So just leave it that we're an indexer and let our parent // in the AST resolve us. // But this also means that we don't have a good thing to set our CLR type too. // So we just don't call CalcCLRType(). That's ok since our parent will drop // this node immediately anyways. if (fIsLeft) { return this; } // Rightside: get_Item(idx); System.Type [] alParams = new Type [] { this.ExpIndex.CLRType }; TypeEntry tLeft = s.ResolveCLRTypeToBlueType(m_oeLeft.CLRType); MethodExpEntry m = tLeft.LookupIndexer(m_oeLeft.Location, s, alParams, fIsLeft); Exp e = new MethodCallExp( this.Left, m, new ArgExp[] { new ArgExp(EArgFlow.cIn, ExpIndex) }, s); Exp.ResolveExpAsRight(ref e, s); return e; } CalcCLRType(s); return this; }
// 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; }
// Delegates are really just blessed Types. void CreateProxyType(ISemanticResolver s) { Debug.Assert(m_nodeProxy == null, "only create proxy once"); // The delegate R F(A) (where R is a return type, and A is a parameter list) // Can be converted into the type: // sealed class F : System.MulticastDelegate { // F(object, native int) { } // BeginInvoke() { } // EndInvoke() { } // R Invoke(A) { } // } BlockStatement stmtEmpty = new BlockStatement(null, new Statement[0]); Modifiers modsPublic = new Modifiers(); modsPublic.SetPublic(); Modifiers modsVirtual = modsPublic; modsVirtual.SetVirtual(); //System.Type tNativeInt = typeof(int); System.Type tNativeInt = Type.GetType("System.IntPtr"); TypeEntry t_IAsyncResult = s.ResolveCLRTypeToBlueType(typeof(System.IAsyncResult)); // Create the parameters for the BeginInvoke() ParamVarDecl [] paramBeginInvoke = new ParamVarDecl[m_arParams.Length + 2]; m_arParams.CopyTo(paramBeginInvoke, 0); paramBeginInvoke[m_arParams.Length]= new ParamVarDecl( new Identifier("cb"), new ResolvedTypeSig(typeof(System.AsyncCallback), s), EArgFlow.cIn ); paramBeginInvoke[m_arParams.Length + 1] = new ParamVarDecl( new Identifier("state"), new ResolvedTypeSig(typeof(System.Object), s), EArgFlow.cIn ); m_nodeProxy = new ClassDecl( m_idName, new TypeSig[] { new ResolvedTypeSig(typeof(System.MulticastDelegate), s) }, new MethodDecl[] { // Ctor new MethodDecl( m_idName, null, new ParamVarDecl[] { new ParamVarDecl(new Identifier("instance"), new ResolvedTypeSig(typeof(object), s), EArgFlow.cIn), new ParamVarDecl(new Identifier("func"), new ResolvedTypeSig(tNativeInt, s), EArgFlow.cIn) }, stmtEmpty, modsPublic ), // Invoke, new MethodDecl( new Identifier("Invoke"), this.m_tRetType, this.m_arParams, stmtEmpty, modsVirtual), // Begin Invoke new MethodDecl( new Identifier("BeginInvoke"), new ResolvedTypeSig(t_IAsyncResult), paramBeginInvoke, stmtEmpty, modsVirtual), // End Invoke new MethodDecl( new Identifier("EndInvoke"), this.m_tRetType, new ParamVarDecl[] { new ParamVarDecl(new Identifier("result"), new ResolvedTypeSig(t_IAsyncResult), EArgFlow.cIn) }, stmtEmpty, modsVirtual) }, new PropertyDecl[0], new FieldDecl[0], new EventDecl[0], new TypeDeclBase[0], m_mods, true); // isClass }
// Resolve protected override Exp ResolveExpAsRight(ISemanticResolver s) { // Resolve the type we're allocating m_tType.ResolveType(s); // One major exception for creating a new delegate, of the form: // new T(E.i) //if (m_tType.CLRType.BaseType == typeof(System.MulticastDelegate)) if (DelegateDecl.IsDelegate(m_tType.CLRType)) { //Debug.Assert(false, "@todo - Impl Delegates in New"); if (Params.Length != 1) { // When this is resolved, we actually have 2 params (not just one). // Make sure we've already resolved this. return this; } Exp.ResolveExpAsRight(ref m_arParams[0], s); DotObjExp e = m_arParams[0] as DotObjExp; Debug.Assert(e != null); Exp expInstance = null; TypeEntry tLeft = null; if (e.LeftExp is TypeExp) { // Static expInstance = new NullExp(Location); tLeft = ((TypeExp) e.LeftExp).Symbol; } else { // Instance expInstance = e.LeftExp; tLeft = s.ResolveCLRTypeToBlueType(e.LeftExp.CLRType); } // Use the parameter list off the delegate type to discern for overloads. System.Type [] alDelegateParams = DelegateDecl.GetParams(m_tType.BlueType); // Lookup what function we're passing to the delegate. bool fIsOut; MethodExpEntry m = tLeft.LookupMethod(s, e.Id, alDelegateParams, out fIsOut); Debug.Assert(!fIsOut, "@todo - can't have a delegate reference a vararg function"); // Change parameters m_arParams = new Exp [] { expInstance, new MethodPtrExp(m) }; } // Resolve all parameters System.Type [] alParamTypes = new Type[Params.Length]; for(int i = 0; i < this.m_arParams.Length; i++) { Exp.ResolveExpAsRight(ref m_arParams[i], s); alParamTypes[i] = m_arParams[i].CLRType; //Debug.Assert(alParamTypes[i] != null); } // Now we're back to normal... // Figure out what constructor we're calling if (m_tType.BlueType.IsStruct && (alParamTypes.Length == 0)) { // Structs have no default constructor } else { // Else resolve the ctor bool fIsVarArg; m_symCtor = m_tType.BlueType.LookupMethod( s, new Identifier(m_tType.BlueType.Name, this.Location), alParamTypes, out fIsVarArg); } //(m_tType.TypeRec, s); CalcCLRType(s); return this; }
// 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(); }
public DeclareLocalStmtExp(System.Type t, ISemanticResolver s) : this(s.ResolveCLRTypeToBlueType(t)) { }
// Ctor for imported properties public PropertyExpEntry( ISemanticResolver s, System.Reflection.PropertyInfo info ) { m_info = info; m_strName = m_info.Name; // Class that we're defined in? System.Type tClrClass = info.DeclaringType; m_tClassDefined = s.ResolveCLRTypeToBlueType(tClrClass); // Symbol type this.m_type = s.ResolveCLRTypeToBlueType(info.PropertyType); // Spoof accessors if (info.CanRead) // Has Get { System.Reflection.MethodInfo mGet = info.GetGetMethod(); m_symbolGet = new MethodExpEntry(s, mGet); } if (info.CanWrite) // Has Set { System.Reflection.MethodInfo mSet = info.GetSetMethod(); m_symbolSet = new MethodExpEntry(s, mSet); } // Get modifiers System.Reflection.MethodInfo [] m = info.GetAccessors(); m_mods = new Modifiers(m[0]); /* m_mods = new Modifiers(); if (m[0].IsStatic) m_mods.SetStatic(); if (m[0].IsAbstract) m_mods.SetAbstract(); if (m[0].IsVirtual) m_mods.SetVirtual(); */ }
// Semantic resolution. // This is where we check for Set-Property transformations (where an // assignment gets changed into a methodcall) protected override Exp ResolveExpAsRight(ISemanticResolver s) { // Resolve the leftside of the operator Exp.ResolveExpAsLeft(ref m_oeLeft, s); // Event transform actually occurs in the assignment node. // A.e = A.e + d --> A.add_e(d) // We have to do this before we resolve the RHS of the operator (Since we // can't resolve events as a RHS). if (m_oeLeft is EventExp) { EventExp nodeEvent = (EventExp)m_oeLeft; EventExpEntry e = nodeEvent.Symbol; // Here we just do some asserts. BinaryExp b = this.m_expRight as BinaryExp; Debug.Assert(b != null, "bad formed event +=,-="); // By now, we know we have something of the form A = B + C // Make sure that A=B. Since we resolved A as left, must resolve B as left too. Exp eTempLeft = b.Left; Exp.ResolveExpAsLeft(ref eTempLeft, s); Debug.Assert(eTempLeft is EventExp); Debug.Assert(Object.ReferenceEquals(((EventExp) eTempLeft).Symbol, e)); // symbols should be exact references // Resolve C (the delegate that we're adding to the event) Exp eTempRight = b.Right; Exp.ResolveExpAsRight(ref eTempRight, s); Debug.Assert(AST.DelegateDecl.IsDelegate(eTempRight.CLRType), "Event only ops w/ delegates"); // @todo -legit/ Debug.Assert(b.Op == BinaryExp.BinaryOp.cAdd || b.Op == BinaryExp.BinaryOp.cSub); MethodExpEntry m2 = (b.Op == BinaryExp.BinaryOp.cAdd) ? e.AddMethod : e.RemoveMethod; Exp e2 = new MethodCallExp( nodeEvent.InstanceExp, m2, new ArgExp[] { new ArgExp(EArgFlow.cIn, eTempRight) }, s ); Exp.ResolveExpAsRight(ref e2, s); return e2; } Exp.ResolveExpAsRight(ref m_expRight, s); // Check for calling add_, remove on events // a.E += X // a.E = a.E + X (parser transforms) // if E is a delegate, and RHS is structured like E + X // then transform to a.add_E(X) or a.remove_E(x) // @todo - use the EventInfo to get exact add / remove functions if (DelegateDecl.IsDelegate(m_oeLeft.CLRType)) { // Events can only exist on a class AST.FieldExp f = m_oeLeft as FieldExp; if (f == null) goto NotAnEvent; Exp eInstance = f.InstanceExp; // ok if static BinaryExp rhs = m_expRight as BinaryExp; if (rhs == null) goto NotAnEvent; // Check if RHS is a.E + X if ((rhs.Left != m_oeLeft) || (rhs.Right.CLRType != rhs.Left.CLRType)) goto NotAnEvent; string stEventName = f.Symbol.Name; string stOpName; if (rhs.Op == BinaryExp.BinaryOp.cAdd) stOpName = "add_" + stEventName; else if (rhs.Op == BinaryExp.BinaryOp.cSub) stOpName = "remove_" + stEventName; else goto NotAnEvent; // a.add_E(X); Exp e = new MethodCallExp( eInstance, new Identifier(stOpName), new ArgExp[] { new ArgExp(EArgFlow.cIn, rhs.Right) } ); Exp.ResolveExpAsRight(ref e, s); e.SetLocation(this.Location); return e; NotAnEvent: ; } // Check for set-indexer if (m_oeLeft is ArrayAccessExp) { ArrayAccessExp a = m_oeLeft as ArrayAccessExp; if (a.IsIndexer) { // Leftside: get_Item(idx, value); System.Type [] alParams = new Type [] { a.ExpIndex.CLRType, m_expRight.CLRType }; TypeEntry t = s.ResolveCLRTypeToBlueType(a.Left.CLRType); MethodExpEntry m = t.LookupIndexer(a.Left.Location, s, alParams, true); Exp e = new MethodCallExp( a.Left, m, new ArgExp[] { new ArgExp(EArgFlow.cIn, a.ExpIndex), new ArgExp(EArgFlow.cIn, m_expRight) }, s); Exp.ResolveExpAsRight(ref e, s); e.SetLocation(this.Location); return e; } } // Check for transforming properties into MethodCalls if (m_oeLeft is PropertyExp) { PropertyExp p = (PropertyExp) m_oeLeft; Exp e = new MethodCallExp( p.InstanceExp, p.Symbol.SymbolSet, new ArgExp[] { new ArgExp(EArgFlow.cIn, m_expRight) }, s); Exp.ResolveExpAsRight(ref e, s); e.SetLocation(this.Location); return e; } CalcCLRType(s); // Ensure type match s.EnsureAssignable(m_expRight, m_oeLeft.CLRType); return this; }
// Semantic resolution protected override Exp ResolveExpAsRight(ISemanticResolver s) { // Only resolve once. if (m_symbol != null) return this; // First, resolve our parameters (because of overloading) // We need to know the URT types for our parameters // in order to resolve between overloaded operators Type [] alParamTypes = new Type[m_arParams.Length]; for(int i = 0; i < m_arParams.Length; i++) { Exp e = m_arParams[i]; ResolveExpAsRight(ref e, s); Debug.Assert(e == m_arParams[i]); Type tParam = e.CLRType; //if ((tParam !=null) && tParam.IsByRef) // tParam = tParam.GetElementType(); alParamTypes[i] = tParam; //Debug.Assert(alParamTypes[i] != null); } TypeEntry tCur = s.GetCurrentClass(); TypeEntry tLeft = null; // Type to lookup in // Is this a 'base' access? // Convert to the real type and set a non-virtual flag if (m_objExp is SimpleObjExp) { SimpleObjExp e = m_objExp as SimpleObjExp; if (e.Name.Text == "base") { // Set the scope that we lookup in. tLeft = tCur.Super; // Still need to resolve the expression. m_objExp = new SimpleObjExp("this"); m_fIsNotPolymorphic = true; } } #if true // See if we have a delegate here Exp eDelegate = null; if (m_objExp == null) { Exp e = new SimpleObjExp(m_idName); Exp.ResolveExpAsRight(ref e, s); if (!(e is SimpleObjExp)) eDelegate = e; } else { // If it's an interface, then we know we can't have a delegate field on it, // so short-circuit now. Exp.ResolveExpAsRight(ref m_objExp, s); if (!m_objExp.CLRType.IsInterface) { Exp e = new DotObjExp(m_objExp, m_idName); Exp.ResolveExpAsRight(ref e, s); if (!(e is DotObjExp)) eDelegate = e; } } if (eDelegate != null) { if (!DelegateDecl.IsDelegate(eDelegate.CLRType)) { //Debug.Assert(false, "@todo - " + m_strName + " is not a delegate or function"); // @todo - legit // Just fall through for now, method resolution will decide if this is a valid function } else { Exp e = new MethodCallExp( eDelegate, new Identifier("Invoke"), this.m_arParams ); Exp.ResolveExpAsRight(ref e, s); return e; } } #endif // No delegate, carry on with a normal function call // If there's no objexp, then the function is a method // of the current class. // make it either a 'this' or a static call if (m_objExp == null) { // Lookup bool fIsVarArgDummy; MethodExpEntry sym = tCur.LookupMethod(s, m_idName, alParamTypes, out fIsVarArgDummy); if (sym.IsStatic) { m_objExp = new TypeExp(tCur); } else { m_objExp = new SimpleObjExp("this"); } } // Need to Lookup m_strName in m_objExp's scope (inherited scope) Exp.ResolveExpAsRight(ref m_objExp, s); // Get type of of left side object // This call can either be a field on a variable // or a static method on a class bool fIsStaticMember = false; // If we don't yet know what TypeEntry this methodcall is on, then figure // it out based off the expression if (tLeft == null) { if (m_objExp is TypeExp) { fIsStaticMember = true; tLeft = ((TypeExp) m_objExp).Symbol; } else { fIsStaticMember = false; tLeft = s.ResolveCLRTypeToBlueType(m_objExp.CLRType); } } // Here's the big lookup. This will jump through all sorts of hoops to match // parameters, search base classes, do implied conversions, varargs, // deal with abstract, etc. bool fIsVarArg; m_symbol = tLeft.LookupMethod(s, m_idName, alParamTypes, out fIsVarArg); Debug.Assert(m_symbol != null); if (m_fIsNotPolymorphic) { // of the form 'base.X(....)' if (m_symbol.IsStatic) ThrowError(SymbolError.BaseAccessCantBeStatic(this.Location, m_symbol)); // @todo - PrintError? } else { // normal method call /* if (fIsStaticMember && !m_symbol.IsStatic) ThrowError(SymbolError.ExpectInstanceMember(this.Location)); // @todo - PrintError? else if (!fIsStaticMember && m_symbol.IsStatic) ThrowError(SymbolError.ExpectStaticMember(this.Location)); // @todo - PrintError? */ Debug.Assert(fIsStaticMember == m_symbol.IsStatic, "@todo - user error. Mismatch between static & instance members on line."); } // If we have a vararg, then transform it if (fIsVarArg) { // Create the array int cDecl = m_symbol.ParamCount; int cCall = this.ParamExps.Length; ArrayTypeSig tSig = new ArrayTypeSig(m_symbol.ParamCLRType(cDecl - 1), s); Node [] list = new Node[cCall - cDecl + 1]; for(int i = 0; i < list.Length; i++) { list[i] = this.ParamExps[i + cDecl - 1]; } Exp eArray = new NewArrayObjExp( tSig, new ArrayInitializer( list ) ); Exp.ResolveExpAsRight(ref eArray, s); // Change the parameters to use the array ArgExp [] arParams = new ArgExp[cDecl]; for(int i = 0; i < cDecl - 1; i++) arParams[i] = m_arParams[i]; arParams[cDecl - 1] = new ArgExp(EArgFlow.cIn, eArray); m_arParams = arParams; } // end vararg transformation this.CalcCLRType(s); return this; }