// Resolve expression as a RHS value. The exp node can totally change on us // (operator overloading, constant folding, etc), so we must pass as a ref public static void ResolveExpAsRight(ref Exp e, ISemanticResolver s) { // Debugging helper. Useful when we want to break when resolving // a particular symbol. #if false // Set lTarget to a symbol that we want to see resolved. FileRange lTarget = new FileRange("SemanticChecker.cs", 143, 39, 143, 43); if (lTarget.Equals(e.Location)) { System.Diagnostics.Debugger.Break(); } #endif e = e.ResolveExpAsRight(s); Debug.Assert(e != null); }
// Use this when we already have a static method to call // and we already have the symbols public MethodCallExp( Exp eInstance, // null if static MethodExpEntry symMethod, ArgExp [] arParams, ISemanticResolver s ) { this.m_idName = new Identifier(symMethod.Name); m_arParams = arParams; m_symbol = symMethod; // Spoof Left if (eInstance == null) { //m_objExp = new SimpleObjExp(symMethod.SymbolClass.Name); m_objExp = new TypeExp(symMethod.SymbolClass); } else m_objExp = eInstance; Exp.ResolveExpAsRight(ref m_objExp, s); // Resolve args, just in case foreach(ArgExp eArg in arParams) { Exp e = eArg; Exp.ResolveExpAsRight(ref e, s); Debug.Assert(e == eArg); } //ResolveAsExpEntry(m_symbol, s); CalcCLRType(s); }
public AssignStmtExp(Exp expLeft, Exp expRight) { Debug.Assert(expLeft != null); Debug.Assert(expRight != null); m_oeLeft = expLeft; m_expRight = expRight; //m_filerange = FileRange.Merge(expLeft.Location, expRight.Location); }
//......................................................................... // Semantic resolution. Resolve the exp as either a LHS or RHS value. //......................................................................... // Resolve the expression as a LHS value public static void ResolveExpAsLeft(ref Exp e, ISemanticResolver s) { e = e.ResolveExpAsLeft(s); Debug.Assert(e != null); }
public BinaryExp(Exp left, Exp right, BinaryOp op) { Debug.Assert(left != null); Debug.Assert(right != null); //m_filerange = FileRange.Merge(left.Location, right.Location); m_left = left; m_right = right; m_op = op; }
public UnaryExp(Exp left, UnaryOp op) { Debug.Assert(left != null); m_filerange = left.Location; m_left = left; m_op = op; }
public NewArrayObjExp( ArrayTypeSig tArrayType, // full array type (includes rank) Exp [] arExpSize, // rank to allocate, eval at runtime ArrayInitializer aInit // optional initilizer list ) { Debug.Assert(tArrayType != null); Debug.Assert(arExpSize != null); m_tFullType = tArrayType; this.m_arExpList = arExpSize; this.m_ArrayInit = aInit; // @todo - this is wrong m_filerange = tArrayType.Location; }
public IsExp( Exp expTest, TypeSig tTarget ) { Debug.Assert(expTest != null); Debug.Assert(tTarget != null); m_expTest = expTest; m_tTarget = tTarget; //m_filerange = FileRange.Merge(expTest.Location, tTarget.Location); }
public BaseCastObjExp( TypeSig tTargetType, Exp expSource ) { m_tTargetType = tTargetType; m_expSource = expSource; Debug.Assert(m_tTargetType != null); Debug.Assert(m_expSource != null); // @todo - have parser resolve this //m_filerange = FileRange.Merge(expSource.Location, m_tTargetType.Location); }
public NewObjExp( TypeSig tType, Exp [] arParams ) { Debug.Assert(tType != null); Debug.Assert(arParams != null); m_tType = tType; m_arParams = arParams; // @todo- this is wrong m_filerange = tType.Location; }
public CastObjExp( TypeSig tTargetType, Exp expSource ) : base(tTargetType, expSource) { }
public AsExp( TypeSig tTargetType, Exp expSource ) : base(tTargetType, expSource) { }
// 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; }
// For search path public UsingDirective(Exp eNamespace) { Debug.Assert(eNamespace != null); m_stAlias = null; m_eNamespace = eNamespace; }
public ArrayAccessExp( Exp expLeft, Exp expIndex ) { Debug.Assert(expLeft != null); Debug.Assert(expIndex != null); m_oeLeft = expLeft; m_expIndex = expIndex; // @todo- this is wrong m_filerange = m_oeLeft.Location; }
public IfExp( Exp expTest, Exp expTrue, Exp expFalse ) { Debug.Assert(expTest != null); Debug.Assert(expTrue != null); Debug.Assert(expFalse != null); m_expTest = expTest; m_expTrue = expTrue; m_expFalse = expFalse; }
public FieldExp( FieldExpEntry symbol, Exp expInstance // null for statics ) { Debug.Assert(symbol != null); m_symbol = symbol; m_expInstance = expInstance; }
// @todo - not really working yet. We don't do constant folding. //......................................................................... // Simplifying an expression that we pass in. Pass out the simplified // expression (or the same thing we passed in if we can't simplify) //......................................................................... public static void TrySimplify(ref Exp e) { e = e.TrySimplify(); }
public DotObjExp(Exp left, Identifier id) { m_left = left; m_strId = id; m_filerange = id.Location; }
// Return true iff the given expression is allowed to have a null type public static bool CanBeNullType(Exp e) { return (e is NullExp) || (e is IfExp) || (e is ArgExp) || (e is NamespaceExp); }
public SimpleTypeSig(Exp e) { if (e != null) m_filerange = e.Location; m_oeValue = e; }
public ArgExp(AST.EArgFlow eFlow, Exp exp) { Debug.Assert(exp != null); Debug.Assert(!(exp is ArgExp), "ArgExp should never wrap an ArgExp"); m_exp = exp; m_eFlow = eFlow; }
public ThrowStatement( Exp oeException // can be null for a rethrow ) { m_oeException = oeException; }
// <e0, e1, e2 .... en> // e_0 .. e_n-1 are StatementExp, that generate as Statements (to produce side effects) // e_n is a normal expression, generated as an expression, to produce a value public CompoundStmtExp( StatementExp [] eList, Exp eLast ) { Debug.Assert(eList != null); Debug.Assert(eLast != null); m_eList = eList; m_eLast = eLast; }
public SwitchStatement( Exp expTest, SwitchSection [] sections ) { m_expTest = expTest; m_sections = sections; m_proxy = null; }
public OpEqualStmtExp(Exp expLeft, Exp expRight, BinaryExp.BinaryOp op) { Debug.Assert(false, "OpEqualStmtExp is obsolete"); // m_op = op; m_eLeft = expLeft; m_expRight = expRight; }
// For alias public UsingDirective(string stAlias, Exp eNamespace) { Debug.Assert(stAlias != null); Debug.Assert(eNamespace != null); m_stAlias = stAlias; m_eNamespace = eNamespace; }
public PrePostIncDecStmtExp( Exp e, bool fPre, bool fInc) { m_exp = e; m_fPre = fPre; m_fInc = fInc; }
public MethodCallExp( Exp e, // may be null, Identifier id, ArgExp [] arParams ) { // m_objExp may be null _until_ we resolve this. And then it's either // going to the implied 'this' ptr, a global func or a static func. m_objExp = e; m_idName = id; m_arParams = (arParams == null) ? new ArgExp[0] : arParams; // @todo - set in parser m_filerange = id.Location; }