예제 #1
0
 public static EXPR StripNullableConstructor(EXPR pExpr)
 {
     while (IsNullableConstructor(pExpr))
     {
         Debug.Assert(pExpr.isCALL());
         pExpr = pExpr.asCALL().GetOptionalArguments();
         Debug.Assert(pExpr != null && !pExpr.isLIST());
     }
     return(pExpr);
 }
예제 #2
0
        // Value
        public EXPR BindValue(EXPR exprSrc)
        {
            Debug.Assert(exprSrc != null && exprSrc.type.IsNullableType());

            // For new T?(x), the answer is x.
            if (CNullable.IsNullableConstructor(exprSrc))
            {
                Debug.Assert(exprSrc.asCALL().GetOptionalArguments() != null && !exprSrc.asCALL().GetOptionalArguments().isLIST());
                return(exprSrc.asCALL().GetOptionalArguments());
            }

            CType         typeBase = exprSrc.type.AsNullableType().GetUnderlyingType();
            AggregateType ats      = exprSrc.type.AsNullableType().GetAts(GetErrorContext());

            if (ats == null)
            {
                EXPRPROP rval = GetExprFactory().CreateProperty(typeBase, exprSrc);
                rval.SetError();
                return(rval);
            }

            // UNDONE: move this to transform pass ...
            PropertySymbol prop = GetSymbolLoader().getBSymmgr().propNubValue;

            if (prop == null)
            {
                prop = GetSymbolLoader().getPredefinedMembers().GetProperty(PREDEFPROP.PP_G_OPTIONAL_VALUE);
                GetSymbolLoader().getBSymmgr().propNubValue = prop;
            }

            PropWithType     pwt       = new PropWithType(prop, ats);
            MethWithType     mwt       = new MethWithType(prop != null ? prop.methGet : null, ats);
            MethPropWithInst mpwi      = new MethPropWithInst(prop, ats);
            EXPRMEMGRP       pMemGroup = GetExprFactory().CreateMemGroup(exprSrc, mpwi);
            EXPRPROP         exprRes   = GetExprFactory().CreateProperty(typeBase, null, null, pMemGroup, pwt, mwt, null);

            if (prop == null)
            {
                exprRes.SetError();
            }

            return(exprRes);
        }
예제 #3
0
 public static EXPR StripNullableConstructor(EXPR pExpr)
 {
     while (IsNullableConstructor(pExpr))
     {
         Debug.Assert(pExpr.isCALL());
         pExpr = pExpr.asCALL().GetOptionalArguments();
         Debug.Assert(pExpr != null && !pExpr.isLIST());
     }
     return pExpr;
 }
예제 #4
0
        // Value
        public EXPR BindValue(EXPR exprSrc)
        {
            Debug.Assert(exprSrc != null && exprSrc.type.IsNullableType());

            // For new T?(x), the answer is x.
            if (CNullable.IsNullableConstructor(exprSrc))
            {
                Debug.Assert(exprSrc.asCALL().GetOptionalArguments() != null && !exprSrc.asCALL().GetOptionalArguments().isLIST());
                return exprSrc.asCALL().GetOptionalArguments();
            }

            CType typeBase = exprSrc.type.AsNullableType().GetUnderlyingType();
            AggregateType ats = exprSrc.type.AsNullableType().GetAts(GetErrorContext());
            if (ats == null)
            {
                EXPRPROP rval = GetExprFactory().CreateProperty(typeBase, exprSrc);
                rval.SetError();
                return rval;
            }

            PropertySymbol prop = GetSymbolLoader().getBSymmgr().propNubValue;
            if (prop == null)
            {
                prop = GetSymbolLoader().getPredefinedMembers().GetProperty(PREDEFPROP.PP_G_OPTIONAL_VALUE);
                GetSymbolLoader().getBSymmgr().propNubValue = prop;
            }

            PropWithType pwt = new PropWithType(prop, ats);
            MethWithType mwt = new MethWithType(prop != null ? prop.methGet : null, ats);
            MethPropWithInst mpwi = new MethPropWithInst(prop, ats);
            EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(exprSrc, mpwi);
            EXPRPROP exprRes = GetExprFactory().CreateProperty(typeBase, null, null, pMemGroup, pwt, mwt, null);

            if (prop == null)
            {
                exprRes.SetError();
            }

            return exprRes;
        }
예제 #5
0
        public static bool IsNullableConstructor(EXPR expr)
        {
            Debug.Assert(expr != null);

            if (!expr.isCALL())
            {
                return false;
            }

            EXPRCALL pCall = expr.asCALL();
            if (pCall.GetMemberGroup().GetOptionalObject() != null)
            {
                return false;
            }

            MethodSymbol meth = pCall.mwi.Meth();
            if (meth == null)
            {
                return false;
            }
            return meth.IsNullableConstructor();
        }
예제 #6
0
        public static bool IsNullableConstructor(EXPR expr)
        {
            Debug.Assert(expr != null);

            if (!expr.isCALL())
            {
                return(false);
            }

            EXPRCALL pCall = expr.asCALL();

            if (pCall.GetMemberGroup().GetOptionalObject() != null)
            {
                return(false);
            }

            MethodSymbol meth = pCall.mwi.Meth();

            if (meth == null)
            {
                return(false);
            }
            return(meth.IsNullableConstructor());
        }
예제 #7
0
 protected bool IsDelegateConstructorCall(EXPR pExpr)
 {
     Debug.Assert(pExpr != null);
     if (!pExpr.isCALL())
     {
         return false;
     }
     EXPRCALL pCall = pExpr.asCALL();
     return pCall.mwi.Meth() != null &&
         pCall.mwi.Meth().IsConstructor() &&
         pCall.type.isDelegateType() &&
         pCall.GetOptionalArguments() != null &&
         pCall.GetOptionalArguments().isLIST() &&
         pCall.GetOptionalArguments().asLIST().GetOptionalNextListNode().kind == ExpressionKind.EK_FUNCPTR;
 }
예제 #8
0
            /***************************************************************************************************
            *   Called by BindImplicitConversion when the destination type is Nullable<T>. The following
            *   conversions are handled by this method:
            *
            * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit
            *     unboxing conversion S => T?
            * System.Enum => T? there is an unboxing conversion if T is an enum type
            * null => T? implemented as default(T?)
            *
            * Implicit T?* => T?+ implemented by either wrapping or calling GetValueOrDefault the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S => T?+ implemented by converting to T then wrapping the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S?+ => T?+ implemented by calling GetValueOrDefault (m-1) times
            *     then calling HasValue, producing a null if it returns false, otherwise calling Value,
            *     converting to T then wrapping the appropriate number of times.
            *
            *   The 3 rules above can be summarized with the following recursive rules:
            *
            * If imp/exp S => T? then imp/exp S? => T? implemented as
            *     qs.HasValue ? (T?)(qs.Value) : default(T?)
            * If imp/exp S => T then imp/exp S => T? implemented as new T?((T)s)
            *
            *   This method also handles calling bindUserDefinedConverion. This method does NOT handle
            *   the following conversions:
            *
            * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by BindImplicitConversion.)
            * If imp/exp S => T then explicit S?+ => T implemented by calling Value the appropriate number
            *     of times. (Handled by BindExplicitConversion.)
            *
            *   The recursive equivalent is:
            *
            * If imp/exp S => T and T is not nullable then explicit S? => T implemented as qs.Value
            *
            *   Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit
            *   then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard.
            ***************************************************************************************************/
            private bool BindNubConversion(NullableType nubDst)
            {
                // This code assumes that STANDARD and ISEXPLICIT are never both set.
                // bindUserDefinedConversion should ensure this!
                Debug.Assert(0 != (~flags & (CONVERTTYPE.STANDARD | CONVERTTYPE.ISEXPLICIT)));
                Debug.Assert(exprSrc == null || exprSrc.type == typeSrc);
                Debug.Assert(!needsExprDest || exprSrc != null);
                Debug.Assert(typeSrc != nubDst); // BindImplicitConversion should have taken care of this already.
                AggregateType atsDst = nubDst.GetAts(GetErrorContext());

                if (atsDst == null)
                {
                    return(false);
                }

                // Check for the unboxing conversion. This takes precedence over the wrapping conversions.
                if (GetSymbolLoader().HasBaseConversion(nubDst.GetUnderlyingType(), typeSrc) && !CConversions.FWrappingConv(typeSrc, nubDst))
                {
                    // These should be different! Fix the caller if typeSrc is an AggregateType of Nullable.
                    Debug.Assert(atsDst != typeSrc);

                    // typeSrc is a base type of the destination nullable type so there is an explicit
                    // unboxing conversion.
                    if (0 == (flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        return(false);
                    }

                    if (needsExprDest)
                    {
                        binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, EXPRFLAG.EXF_UNBOX);
                    }
                    return(true);
                }

                int       cnubDst;
                int       cnubSrc;
                CType     typeDstBase     = nubDst.StripNubs(out cnubDst);
                EXPRCLASS exprTypeDstBase = GetExprFactory().MakeClass(typeDstBase);
                CType     typeSrcBase     = typeSrc.StripNubs(out cnubSrc);

                ConversionFunc pfn = (flags & CONVERTTYPE.ISEXPLICIT) != 0 ?
                                     (ConversionFunc)binder.BindExplicitConversion :
                                     (ConversionFunc)binder.BindImplicitConversion;

                if (cnubSrc == 0)
                {
                    Debug.Assert(typeSrc == typeSrcBase);

                    // The null type can be implicitly converted to T? as the default value.
                    if (typeSrc.IsNullType())
                    {
                        // If we have the constant null, generate it as a default value of T?.  If we have
                        // some crazy expression which has been determined to be always null, like (null??null)
                        // keep it in its expression form and transform it in the nullable rewrite pass.
                        if (needsExprDest)
                        {
                            if (exprSrc.isCONSTANT_OK())
                            {
                                exprDest = GetExprFactory().CreateZeroInit(nubDst);
                            }
                            else
                            {
                                exprDest = GetExprFactory().CreateCast(0x00, typeDest, exprSrc);
                            }
                        }
                        return(true);
                    }

                    EXPR exprTmp = exprSrc;

                    // If there is an implicit/explicit S => T then there is an implicit/explicit S => T?
                    if (typeSrc == typeDstBase || pfn(exprSrc, typeSrc, exprTypeDstBase, nubDst, needsExprDest, out exprTmp, flags | CONVERTTYPE.NOUDC))
                    {
                        if (needsExprDest)
                        {
                            // UNDONE: This is a premature realization of the nullable conversion as
                            // UNDONE: a constructor.  Rather than flagging this, can we simply emit it
                            // UNDONE: as a cast node and have the operator rewrite pass turn it into
                            // UNDONE: a constructor call?
                            EXPRUSERDEFINEDCONVERSION exprUDC = exprTmp.kind == ExpressionKind.EK_USERDEFINEDCONVERSION ? exprTmp.asUSERDEFINEDCONVERSION() : null;
                            if (exprUDC != null)
                            {
                                exprTmp = exprUDC.UserDefinedCall;
                            }

                            // This logic is left over from the days when T?? was legal. However there are error/LAF cases that necessitates the loop.
                            // typeSrc is not nullable so just wrap the required number of times. For legal code (cnubDst <= 0).

                            for (int i = 0; i < cnubDst; i++)
                            {
                                exprTmp = binder.BindNubNew(exprTmp);
                                exprTmp.asCALL().nubLiftKind = NullableCallLiftKind.NullableConversionConstructor;
                            }
                            if (exprUDC != null)
                            {
                                exprUDC.UserDefinedCall = exprTmp;
                                exprUDC.setType((CType)exprTmp.type);
                                exprTmp = exprUDC;
                            }
                            Debug.Assert(exprTmp.type == nubDst);
                            exprDest = exprTmp;
                        }
                        return(true);
                    }

                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (flags & CONVERTTYPE.NOUDC) && binder.bindUserDefinedConversion(exprSrc, typeSrc, nubDst, needsExprDest, out exprDest, 0 == (flags & CONVERTTYPE.ISEXPLICIT)));
                }

                // Both are Nullable so there is only a conversion if there is a conversion between the base types.
                // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+.
                if (typeSrcBase != typeDstBase && !pfn(null, typeSrcBase, exprTypeDstBase, nubDst, false, out exprDest, flags | CONVERTTYPE.NOUDC))
                {
                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (flags & CONVERTTYPE.NOUDC) && binder.bindUserDefinedConversion(exprSrc, typeSrc, nubDst, needsExprDest, out exprDest, 0 == (flags & CONVERTTYPE.ISEXPLICIT)));
                }

                if (needsExprDest)
                {
                    MethWithInst mwi       = new MethWithInst(null, null);
                    EXPRMEMGRP   pMemGroup = GetExprFactory().CreateMemGroup(null, mwi);
                    EXPRCALL     exprDst   = GetExprFactory().CreateCall(0, nubDst, exprSrc, pMemGroup, null);

                    // Here we want to first check whether or not the conversions work on the base types.

                    EXPR      arg1 = binder.mustCast(exprSrc, typeSrcBase);
                    EXPRCLASS arg2 = GetExprFactory().MakeClass(typeDstBase);

                    bool convertible;
                    if (0 != (flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        convertible = binder.BindExplicitConversion(arg1, arg1.type, arg2, typeDstBase, out arg1, flags | CONVERTTYPE.NOUDC);
                    }
                    else
                    {
                        convertible = binder.BindImplicitConversion(arg1, arg1.type, arg2, typeDstBase, out arg1, flags | CONVERTTYPE.NOUDC);
                    }
                    if (!convertible)
                    {
                        VSFAIL("bind(Im|Ex)plicitConversion failed unexpectedly");
                        return(false);
                    }

                    exprDst.castOfNonLiftedResultToLiftedType = binder.mustCast(arg1, nubDst, 0);
                    exprDst.nubLiftKind  = NullableCallLiftKind.NullableConversion;
                    exprDst.pConversions = exprDst.castOfNonLiftedResultToLiftedType;
                    exprDest             = exprDst;
                }

                return(true);
            }
예제 #9
0
        private EXPR ReorderArgumentsForNamedAndOptional(EXPR callingObject, EXPR pResult)
        {
            EXPR arguments;
            AggregateType type;
            MethodOrPropertySymbol methprop;
            EXPRMEMGRP memgroup;
            TypeArray typeArgs;

            if (pResult.isCALL())
            {
                EXPRCALL call = pResult.asCALL();
                arguments = call.GetOptionalArguments();
                type = call.mwi.Ats;
                methprop = call.mwi.Meth();
                memgroup = call.GetMemberGroup();
                typeArgs = call.mwi.TypeArgs;
            }
            else
            {
                Debug.Assert(pResult.isPROP());
                EXPRPROP prop = pResult.asPROP();
                arguments = prop.GetOptionalArguments();
                type = prop.pwtSlot.Ats;
                methprop = prop.pwtSlot.Prop();
                memgroup = prop.GetMemberGroup();
                typeArgs = null;
            }

            ArgInfos argInfo = new ArgInfos();
            bool b;
            argInfo.carg = ExpressionBinder.CountArguments(arguments, out b);
            _binder.FillInArgInfoFromArgList(argInfo, arguments);

            // We need to substitute type parameters BEFORE getting the most derived one because
            // we're binding against the base method, and the derived method may change the 
            // generic arguments. 
            TypeArray parameters = SymbolLoader.GetTypeManager().SubstTypeArray(methprop.Params, type, typeArgs);
            methprop = ExpressionBinder.GroupToArgsBinder.FindMostDerivedMethod(SymbolLoader, methprop, callingObject.type);
            ExpressionBinder.GroupToArgsBinder.ReOrderArgsForNamedArguments(
                methprop,
                parameters,
                type,
                memgroup,
                argInfo,
                _semanticChecker.GetTypeManager(),
                _exprFactory,
                SymbolLoader);
            {
                EXPR pList = null;

                // We reordered, so make a new list of them and set them on the constructor.
                // Go backwards cause lists are right-flushed.
                // Also perform the conversions to the right types.
                for (int i = argInfo.carg - 1; i >= 0; i--)
                {
                    EXPR pArg = argInfo.prgexpr[i];

                    // Strip the name-ness away, since we don't need it.
                    pArg = StripNamedArgument(pArg);

                    // Perform the correct conversion.
                    pArg = _binder.tryConvert(pArg, parameters[i]);
                    if (pList == null)
                    {
                        pList = pArg;
                    }
                    else
                    {
                        pList = _exprFactory.CreateList(pArg, pList);
                    }
                }
                if (pResult.isCALL())
                {
                    pResult.asCALL().SetOptionalArguments(pList);
                }
                else
                {
                    pResult.asPROP().SetOptionalArguments(pList);
                }
            }
            return pResult;
        }
예제 #10
0
        private void CheckForConditionalMethodError(EXPR pExpr)
        {
            Debug.Assert(pExpr.isCALL());
            if (pExpr.isCALL())
            {
                // This mimics the behavior of the native CompilerSymbolLoader in GetConditionalSymbols. Override
                // methods cannot have the conditional attribute, but implicitly acquire it from their slot.

                EXPRCALL call = pExpr.asCALL();

                MethodSymbol method = call.mwi.Meth();
                if (method.isOverride)
                {
                    method = method.swtSlot.Meth();
                }

                object[] conditions = method.AssociatedMemberInfo.GetCustomAttributes(typeof(ConditionalAttribute), false).ToArray();
                if (conditions.Length > 0)
                {
                    throw Error.BindCallToConditionalMethod(method.name);
                }
            }
        }
예제 #11
0
        protected void verifyMethodArgs(EXPR call, CType callingObjectType)
        {
            Debug.Assert(call.isCALL() || call.isPROP());

            EXPR argsPtr = call.getArgs();
            SymWithType swt = call.GetSymWithType();
            MethodOrPropertySymbol mp = swt.Sym.AsMethodOrPropertySymbol();
            TypeArray pTypeArgs = call.isCALL() ? call.asCALL().mwi.TypeArgs : null;
            EXPR newArgs;
            AdjustCallArgumentsForParams(callingObjectType, swt.GetType(), mp, pTypeArgs, argsPtr, out newArgs);
            call.setArgs(newArgs);
        }
예제 #12
0
        /////////////////////////////////////////////////////////////////////////////////

        private Expression GetExpression(EXPR pExpr)
        {
            if (pExpr.isWRAP())
            {
                return _DictionaryOfParameters[pExpr.asWRAP().GetOptionalExpression().asCALL()];
            }
            else if (pExpr.isCONSTANT())
            {
                Debug.Assert(pExpr.type.IsNullType());
                return null;
            }
            else
            {
                // We can have a convert node or a call of a user defined conversion.
                Debug.Assert(pExpr.isCALL());
                EXPRCALL call = pExpr.asCALL();
                PREDEFMETH pm = call.PredefinedMethod;
                Debug.Assert(pm == PREDEFMETH.PM_EXPRESSION_CONVERT ||
                    pm == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT ||
                    pm == PREDEFMETH.PM_EXPRESSION_CALL ||
                    pm == PREDEFMETH.PM_EXPRESSION_PROPERTY ||
                    pm == PREDEFMETH.PM_EXPRESSION_FIELD ||
                    pm == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX ||
                    pm == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2 ||
                    pm == PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE ||
                    pm == PREDEFMETH.PM_EXPRESSION_NEW ||

                    // Binary operators.
                    pm == PREDEFMETH.PM_EXPRESSION_ASSIGN ||
                    pm == PREDEFMETH.PM_EXPRESSION_ADD ||
                    pm == PREDEFMETH.PM_EXPRESSION_AND ||
                    pm == PREDEFMETH.PM_EXPRESSION_DIVIDE ||
                    pm == PREDEFMETH.PM_EXPRESSION_EQUAL ||
                    pm == PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR ||
                    pm == PREDEFMETH.PM_EXPRESSION_GREATERTHAN ||
                    pm == PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL ||
                    pm == PREDEFMETH.PM_EXPRESSION_LEFTSHIFT ||
                    pm == PREDEFMETH.PM_EXPRESSION_LESSTHAN ||
                    pm == PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL ||
                    pm == PREDEFMETH.PM_EXPRESSION_MODULO ||
                    pm == PREDEFMETH.PM_EXPRESSION_MULTIPLY ||
                    pm == PREDEFMETH.PM_EXPRESSION_NOTEQUAL ||
                    pm == PREDEFMETH.PM_EXPRESSION_OR ||
                    pm == PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT ||
                    pm == PREDEFMETH.PM_EXPRESSION_SUBTRACT ||
                    pm == PREDEFMETH.PM_EXPRESSION_ORELSE ||
                    pm == PREDEFMETH.PM_EXPRESSION_ANDALSO ||
                    pm == PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED ||

                    // Checked binary
                    pm == PREDEFMETH.PM_EXPRESSION_ADDCHECKED ||
                    pm == PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED ||
                    pm == PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED ||
                    pm == PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED ||

                    // Unary operators.
                    pm == PREDEFMETH.PM_EXPRESSION_NOT ||
                    pm == PREDEFMETH.PM_EXPRESSION_NEGATE ||
                    pm == PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED ||

                    // Checked unary
                    pm == PREDEFMETH.PM_EXPRESSION_NEGATECHECKED ||
                    pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED ||
                    pm == PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED ||
                    pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED
                    );

                switch (pm)
                {
                    case PREDEFMETH.PM_EXPRESSION_CALL:
                        return GenerateCall(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_CONVERT:
                    case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED:
                    case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED:
                        return GenerateConvert(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT:
                        {
                            EXPRLIST list = call.GetOptionalArguments().asLIST();
                            return Expression.NewArrayInit(
                                list.GetOptionalElement().asTYPEOF().SourceType.type.AssociatedSystemType,
                                GetArgumentsFromArrayInit(list.GetOptionalNextListNode().asARRINIT()));
                        }

                    case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX:
                    case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2:
                        return GenerateArrayIndex(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_NEW:
                        return GenerateNew(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_PROPERTY:
                        return GenerateProperty(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_FIELD:
                        return GenerateField(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE:
                        return GenerateConstantType(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_ASSIGN:
                        return GenerateAssignment(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_ADD:
                    case PREDEFMETH.PM_EXPRESSION_AND:
                    case PREDEFMETH.PM_EXPRESSION_DIVIDE:
                    case PREDEFMETH.PM_EXPRESSION_EQUAL:
                    case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR:
                    case PREDEFMETH.PM_EXPRESSION_GREATERTHAN:
                    case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL:
                    case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT:
                    case PREDEFMETH.PM_EXPRESSION_LESSTHAN:
                    case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL:
                    case PREDEFMETH.PM_EXPRESSION_MODULO:
                    case PREDEFMETH.PM_EXPRESSION_MULTIPLY:
                    case PREDEFMETH.PM_EXPRESSION_NOTEQUAL:
                    case PREDEFMETH.PM_EXPRESSION_OR:
                    case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT:
                    case PREDEFMETH.PM_EXPRESSION_SUBTRACT:
                    case PREDEFMETH.PM_EXPRESSION_ORELSE:
                    case PREDEFMETH.PM_EXPRESSION_ANDALSO:
                    // Checked
                    case PREDEFMETH.PM_EXPRESSION_ADDCHECKED:
                    case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED:
                    case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED:
                        return GenerateBinaryOperator(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED:
                    // Checked
                    case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED:
                        return GenerateUserDefinedBinaryOperator(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_NOT:
                    case PREDEFMETH.PM_EXPRESSION_NEGATE:
                    case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED:
                        return GenerateUnaryOperator(call).Expression;

                    case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED:
                    case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED:
                        return GenerateUserDefinedUnaryOperator(call).Expression;

                    default:
                        Debug.Assert(false, "Invalid Predefined Method in GetExpression");
                        throw Error.InternalCompilerError();
                }
            }
        }