// 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 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 // "a X= b" is semantically equivalent to "a = a X b" protected override Exp ResolveExpAsRight(ISemanticResolver s) { // Note that the left side ("a") of "a X= b" is both a // Left & Right side value ResolveExpAsLeft(ref this.m_eLeft, s); ResolveExpAsRight(ref this.m_expRight, s); CalcCLRType(s); // Ensure type match s.EnsureAssignable(m_expRight, Left.CLRType); return this; }
// Semantic resolution protected override Exp ResolveExpAsRight(ISemanticResolver s) { ResolveExpAsRight(ref this.m_expTest, s); ResolveExpAsRight(ref this.m_expTrue, s); ResolveExpAsRight(ref this.m_expFalse, s); s.EnsureAssignable(m_expTest, typeof(bool)); CalcCLRType(s); return this; }
// Semantic resolution protected override Exp ResolveExpAsRight(ISemanticResolver s) { // We have a problem. If our arg is a property, then we need to // transform this x++ --> x = x + 1 // But we can't always transform since we can overload the ++, -- operators. // So resolve our arg, see if it's a property, and then transform if it is. // Since we update the Arg, we must resolve it as a left value Exp.ResolveExpAsLeft(ref this.m_exp, s); // First check if we have an overload // Check if we're a property if (m_exp is PropertyExp) { Exp e = null; int iDelta = IsInc ? 1 : -1; e = new AssignStmtExp( m_exp, new BinaryExp( m_exp, new IntExp(iDelta, this.m_filerange), BinaryExp.BinaryOp.cAdd ) ); Exp.ResolveExpAsRight(ref e, s); return e; } CalcCLRType(s); // Ensure type match, unless we have an overload. s.EnsureAssignable(Arg, typeof(int)); return this; }
// Semantic resolution public override void ResolveStatement(ISemanticResolver s) { Exp.ResolveExpAsRight(ref this.m_expTest, s); m_loopcount++; BodyStmt.ResolveStatement(s); m_loopcount--; //s.EnsureDerivedType(s.ResolveCLRTypeToBlueType(typeof(bool)), TestExp); s.EnsureAssignable(TestExp, typeof(bool)); }
// Semantic resolution public override void ResolveStatement(ISemanticResolver s) { if (m_oeException != null) { Exp.ResolveExpAsRight(ref m_oeException, s); //Debug.Assert(m_oeException.SymbolMode == ObjExp.Mode.cExpEntry); // Must derive from System.Exception s.EnsureAssignable(m_oeException, typeof(System.Exception)); } }
public void ResolveHandler(ISemanticResolver s) { // Catch blocks can declare an identifier if (IdVarName != null) { m_var = new LocalVarDecl(IdVarName, m_type); Body.InjectLocalVar(m_var); } this.m_type.ResolveType(s); Body.ResolveStatement(s); // Catch type must be of type System.Exception if (m_var != null) { s.EnsureAssignable(m_var.Symbol.m_type.CLRType, typeof(System.Exception), IdVarName.Location); } // Catch type must be of type System.Exception //TypeEntry tSystem_Exception =s.ResolveCLRTypeToBlueType(typeof(System.Exception)); //s.EnsureDerivedType(tSystem_Exception, m_type.TypeRec, new FileRange()); }
// Semantic resolution public override void ResolveStatement(ISemanticResolver s) { MethodExpEntry m = s.GetCurrentMethod(); if (m_exp != null) { Exp.ResolveExpAsRight(ref m_exp, s); // Ensure that expression we're returning matches the method's // return type //s.EnsureDerivedType(m.RetType, m_exp); s.EnsureAssignable(m_exp, m.RetType.CLRType); } else { // If we're not returning an expression, then our return type should be void if (m.RetType.CLRType != typeof(void)) { ThrowError(SymbolError.NoReturnTypeExpected(this)); /* s.ThrowError(SemanticChecker.Code.cNoReturnTypeExpected, this.Location, "Functions with void return type can't return an expression" ); */ } } }