Exemplo n.º 1
0
 public UnaOpSig(PredefinedType pt, UnaOpMask grfuom, int cuosSkip, PfnBindUnaOp pfn, UnaOpFuncKind fnkind)
 {
     this.pt       = pt;
     this.grfuom   = grfuom;
     this.cuosSkip = cuosSkip;
     this.pfn      = pfn;
     this.fnkind   = fnkind;
 }
Exemplo n.º 2
0
 public UnaOpSig(PredefinedType pt, UnaOpMask grfuom, int cuosSkip, PfnBindUnaOp pfn, UnaOpFuncKind fnkind)
 {
     this.pt = pt;
     this.grfuom = grfuom;
     this.cuosSkip = cuosSkip;
     this.pfn = pfn;
     this.fnkind = fnkind;
 }
Exemplo n.º 3
0
        /////////////////////////////////////////////////////////////////////////////////

        private bool FindApplicableSignatures(
                EXPR pArgument,
                UnaOpMask unaryOpMask,
                List<UnaOpFullSig> pSignatures)
        {
            // All callers should already assert this to be the case.
            Debug.Assert(pArgument != null);
            Debug.Assert(pArgument.type != null);

            long iuosMinLift = GetSymbolLoader().FCanLift() ? 0 : g_rguos.Length;

            CType pArgumentType = pArgument.type;
            CType pRawType = pArgumentType.StripNubs();
            PredefinedType pt = pArgumentType.isPredefined() ? pArgumentType.getPredefType() : PredefinedType.PT_COUNT;
            PredefinedType ptRaw = pRawType.isPredefined() ? pRawType.getPredefType() : PredefinedType.PT_COUNT;

            for (int index = 0; index < g_rguos.Length; index++)
            {
                UnaOpSig uos = g_rguos[index];
                if ((uos.grfuom & unaryOpMask) == 0)
                {
                    continue;
                }

                ConvKind cv = GetConvKind(pt, g_rguos[index].pt);
                CType typeSig = null;

                switch (cv)
                {
                    default:
                        VSFAIL("Shouldn't happen!");
                        continue;

                    case ConvKind.None:
                        continue;

                    case ConvKind.Explicit:
                        if (!pArgument.isCONSTANT_OK())
                        {
                            continue;
                        }
                        if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt)))
                        {
                            break;
                        }
                        if (index < iuosMinLift)
                        {
                            continue;
                        }
                        typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig);
                        if (!canConvert(pArgument, typeSig))
                        {
                            continue;
                        }
                        break;

                    case ConvKind.Unknown:
                        if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt)))
                        {
                            break;
                        }
                        if (index < iuosMinLift)
                        {
                            continue;
                        }
                        typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig);
                        if (!canConvert(pArgument, typeSig))
                        {
                            continue;
                        }
                        break;

                    case ConvKind.Implicit:
                        break;

                    case ConvKind.Identity:
                        {
                            UnaOpFullSig result = new UnaOpFullSig(this, uos);
                            if (result.GetType() != null)
                            {
                                pSignatures.Add(result);
                                return true;
                            }
                        }
                        break;
                }

                if (typeSig != null && typeSig.IsNullableType())
                {
                    // Need to use a lifted signature.
                    LiftFlags grflt = LiftFlags.None;

                    switch (GetConvKind(ptRaw, uos.pt))
                    {
                        default:
                            grflt = grflt | LiftFlags.Convert1;
                            break;
                        case ConvKind.Implicit:
                        case ConvKind.Identity:
                            grflt = grflt | LiftFlags.Lift1;
                            break;
                    }

                    pSignatures.Add(new UnaOpFullSig(typeSig, uos.pfn, grflt, uos.fnkind));

                    // NOTE: Can't skip any if we use the lifted signature because the
                    // type might convert to int? and to long (but not to int) in which
                    // case we should get an ambiguity. But we can skip the lifted ones....
                    iuosMinLift = index + uos.cuosSkip + 1;
                }
                else
                {
                    // Record it as applicable and skip accordingly.
                    UnaOpFullSig newResult = new UnaOpFullSig(this, uos);
                    if (newResult.GetType() != null)
                    {
                        pSignatures.Add(newResult);
                    }
                    index += uos.cuosSkip;
                }
            }
            return false;
        }
Exemplo n.º 4
0
        /////////////////////////////////////////////////////////////////////////////////

        private UnaryOperatorSignatureFindResult PopulateSignatureList(EXPR pArgument, UnaOpKind unaryOpKind, UnaOpMask unaryOpMask, ExpressionKind exprKind, EXPRFLAG flags, List<UnaOpFullSig> pSignatures, out EXPR ppResult)
        {
            // We should have already checked argument != null and argument.type != null.
            Debug.Assert(pArgument != null);
            Debug.Assert(pArgument.type != null);

            ppResult = null;
            CType pArgumentType = pArgument.type;
            CType pRawType = pArgumentType.StripNubs();
            PredefinedType ptRaw = pRawType.isPredefined() ? pRawType.getPredefType() : PredefinedType.PT_COUNT;

            // Find all applicable operator signatures.
            // First check for special ones (enum, ptr) and check for user defined ops.

            if (ptRaw > PredefinedType.PT_ULONG)
            {
                // Enum types are special in that they carry a set of "predefined" operators (~ and inc/dec).
                if (pRawType.isEnumType())
                {
                    if ((unaryOpMask & (UnaOpMask.Tilde | UnaOpMask.IncDec)) != 0)
                    {
                        // We have an exact match.
                        LiftFlags liftFlags = LiftFlags.None;
                        CType typeSig = pArgumentType;

                        if (typeSig.IsNullableType())
                        {
                            if (typeSig.AsNullableType().GetUnderlyingType() != pRawType)
                            {
                                typeSig = GetSymbolLoader().GetTypeManager().GetNullable(pRawType);
                            }
                            liftFlags = LiftFlags.Lift1;
                        }
                        if (unaryOpKind == UnaOpKind.Tilde)
                        {
                            pSignatures.Add(new UnaOpFullSig(
                                    typeSig.getAggregate().GetUnderlyingType(),
                                    BindEnumUnaOp,
                                    liftFlags,
                                    UnaOpFuncKind.EnumUnaOp));
                        }
                        else
                        {
                            // For enums, we want to add the signature as the underlying type so that we'll
                            // perform the conversions to and from the enum type.
                            pSignatures.Add(new UnaOpFullSig(
                                    typeSig.getAggregate().GetUnderlyingType(),
                                    null,
                                    liftFlags,
                                    UnaOpFuncKind.None));
                        }
                        return UnaryOperatorSignatureFindResult.Match;
                    }
                }
                else if (unaryOpKind == UnaOpKind.IncDec)
                {
                    // Check for pointers
                    if (pArgumentType.IsPointerType())
                    {
                        pSignatures.Add(new UnaOpFullSig(
                                pArgumentType,
                                null,
                                LiftFlags.None,
                                UnaOpFuncKind.None));
                        return UnaryOperatorSignatureFindResult.Match;
                    }

                    // Check for user defined inc/dec
#if !CSEE
                    EXPRMULTIGET exprGet = GetExprFactory().CreateMultiGet(0, pArgumentType, null);
#else // CSEE

                    EXPR exprGet = pArgument;
#endif // CSEE

                    EXPR exprVal = bindUDUnop((ExpressionKind)(exprKind - ExpressionKind.EK_ADD + ExpressionKind.EK_INC), exprGet);
                    if (exprVal != null)
                    {
                        if (exprVal.type != null && !exprVal.type.IsErrorType() && exprVal.type != pArgumentType)
                        {
                            exprVal = mustConvert(exprVal, pArgumentType);
                        }

                        Debug.Assert(pArgument != null);
                        EXPRMULTI exprMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, pArgumentType, pArgument, exprVal);
#if ! CSEE
                        exprGet.SetOptionalMulti(exprMulti);
#endif // !CSEE

                        // Check whether Lvalue can be assigned. checkLvalue may return true 
                        // despite reporting an error. 
                        if (!checkLvalue(pArgument, CheckLvalueKind.Increment))
                        {
                            // This seems like it can never be reached - exprVal is only valid if 
                            // we have a UDUnop, and in order for checkLValue to return false, either the 
                            // arg has to not be OK, in which case we shouldn't get here, or we have an 
                            // AnonMeth, Lambda, or Constant, all of which cannot have UDUnops defined for them. 
                            exprMulti.SetError();
                        }
                        ppResult = exprMulti;
                        return UnaryOperatorSignatureFindResult.Return;
                    }
                    // Try for a predefined increment operator.
                }
                else
                {
                    // Check for user defined.
                    EXPR expr = bindUDUnop(exprKind, pArgument);
                    if (expr != null)
                    {
                        ppResult = expr;
                        return UnaryOperatorSignatureFindResult.Return;
                    }
                }
            }

            return UnaryOperatorSignatureFindResult.Continue;
        }