Beispiel #1
0
 // 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;
 }
Beispiel #2
0
 // Nothing to resolve for literal expressions
 protected override Exp ResolveExpAsRight(ISemanticResolver s)
 {   
     // Always resolve our children     
     ResolveExpAsRight(ref m_left, s);
     ResolveExpAsRight(ref m_right, s);
     
     // If we don't match a predefined operator, then check for overloads
     if (!MatchesPredefinedOp(Op, this.Left.CLRType, this.Right.CLRType))
     {
         // Packagage Left & Right into parameters for a method call
         ArgExp [] args = new ArgExp [2] {
             new ArgExp(EArgFlow.cIn, m_left),
             new ArgExp(EArgFlow.cIn, m_right)
         };
                                 
         // Check for delegate combination
         // D operator+(D, D)
         // D operator-(D, D)            
         if (AST.DelegateDecl.IsDelegate(m_left.CLRType))
         {
             if (m_left.CLRType == m_right.CLRType)
             {
                 if (Op == BinaryOp.cAdd || Op == BinaryOp.cSub)
                 {
                     System.Type d = m_left.CLRType;
                     
                     // Translates to:
                     // op+ --> (D) System.Delegate.Combine(left, right)
                     // op- --> (D) System.Delegate.Remove(left, right)
                     
                     TypeEntry tDelegate = s.LookupSystemType("MulticastDelegate");
                     string stName = (Op == BinaryOp.cAdd) ? "Combine" : "Remove";
                     
                     bool dummy;
                     MethodExpEntry sym = tDelegate.LookupMethod(s, new Identifier(stName), 
                         new Type[] { d, d}, out dummy);
                     
                     
                     Exp call2 = new CastObjExp(
                         new ResolvedTypeSig(d, s),
                         new MethodCallExp(
                             null,sym, args, s)
                     );
                     
                     Exp.ResolveExpAsRight(ref call2, s);
                     return call2;                                
                 
                 }
             }
         
         } // end delgate op+ check
                                         
         // Check for System.String.Concat().
         // @todo - this should be able to compress an entire subtree, not just 2 args.
         // (ie, a+b+c -> String.Concat(a,b,c);
         // So we can't merge this into the SearchForOverload.
         // But for now we'll be lazy...
         if ((Op == BinaryOp.cAdd) && (Left.CLRType == typeof(string) || Right.CLRType == typeof(string)))
         {                
             Exp call2 = new MethodCallExp(                    
                     new DotObjExp(
                         new SimpleObjExp(
                             new Identifier("System", this.m_filerange)
                         ),
                         new Identifier("String", this.m_filerange)),
                     new Identifier("Concat", m_filerange),
                     args);
             call2.SetLocation(this.Location);
             Exp.ResolveExpAsRight(ref call2, s);
                     
             return call2;
         }
     
         MethodExpEntry  m = SearchForOverloadedOp(s);
         if (m == null && (Op == BinaryOp.cEqu || Op == BinaryOp.cNeq))
         {
             // If it's '==' or '!=', then it's ok if we didn't find 
             // an overload.
         } else 
         {
             // Couldn't find an overload, throw error
             if (m == null)
             {
                 //ThrowError_NoAcceptableOperator(s, this.Location, m_left.CLRType, m_right.CLRType, Op);
                 ThrowError(SymbolError.NoAcceptableOperator(this.Location, m_left.CLRType, m_right.CLRType, Op));
             }
             
             // Replace this node w/ the method call            
             MethodCallExp call = new MethodCallExp(null, m, args, s);
             call.SetLocation(this.Location);
             
             return call;
         }
     }
     
     
     CalcCLRType(s);
     
     return this;
 }