예제 #1
0
        /////////////////////////////////////////////////////////////////////////////////

        internal SymWithType LookupMember(
            string name,
            EXPR callingObject,
            ParentSymbol context,
            int arity,
            MemberLookup mem,
            bool allowSpecialNames,
            bool requireInvocable)
        {
            CType type = callingObject.type;

            if (type.IsArrayType())
            {
                type = _semanticChecker.GetSymbolLoader().GetReqPredefType(PredefinedType.PT_ARRAY);
            }
            if (type.IsNullableType())
            {
                type = type.AsNullableType().GetAts(_semanticChecker.GetSymbolLoader().GetErrorContext());
            }

            if (!mem.Lookup(
                _semanticChecker,
                type,
                callingObject,
                context,
                GetName(name),
                arity,
                MemLookFlags.TypeVarsAllowed |
                    (allowSpecialNames ? 0 : MemLookFlags.UserCallable) |
                    (name == SpecialNames.Indexer ? MemLookFlags.Indexer : 0) |
                    (name == SpecialNames.Constructor ? MemLookFlags.Ctor : 0) |
                    (requireInvocable ? MemLookFlags.MustBeInvocable : 0)))
            {
                return null;
            }
            return mem.SwtFirst();
        }
예제 #2
0
        private bool DeferBinding(
            DynamicMetaObjectBinder payload,
            ArgumentObject[] arguments,
            DynamicMetaObject[] args,
            Dictionary<int, LocalVariableSymbol> dictionary,
            out DynamicMetaObject deferredBinding)
        {
            // This method deals with any deferrals we need to do. We check deferrals up front
            // and bail early if we need to do them.

            // (1) InvokeMember deferral.
            //
            // This is the deferral for the d.Foo() scenario where Foo actually binds to a 
            // field or property, and not a method group that is invocable. We defer to
            // the standard GetMember/Invoke pattern.

            if (payload is CSharpInvokeMemberBinder)
            {
                ICSharpInvokeOrInvokeMemberBinder callPayload = payload as ICSharpInvokeOrInvokeMemberBinder;
                int arity = callPayload.TypeArguments != null ? callPayload.TypeArguments.Count : 0;
                MemberLookup mem = new MemberLookup();
                EXPR callingObject = CreateCallingObjectForCall(callPayload, arguments, dictionary);

                Debug.Assert(_bindingContext.ContextForMemberLookup() != null);
                SymWithType swt = _symbolTable.LookupMember(
                        callPayload.Name,
                        callingObject,
                        _bindingContext.ContextForMemberLookup(),
                        arity,
                        mem,
                        (callPayload.Flags & CSharpCallFlags.EventHookup) != 0,
                        true);

                if (swt != null && swt.Sym.getKind() != SYMKIND.SK_MethodSymbol)
                {
                    // The GetMember only has one argument, and we need to just take the first arg info.
                    CSharpGetMemberBinder getMember = new CSharpGetMemberBinder(callPayload.Name, false, callPayload.CallingContext, new CSharpArgumentInfo[] { callPayload.ArgumentInfo[0] });

                    // The Invoke has the remaining argument infos. However, we need to redo the first one
                    // to correspond to the GetMember result.
                    CSharpArgumentInfo[] argInfos = new CSharpArgumentInfo[callPayload.ArgumentInfo.Count];
                    callPayload.ArgumentInfo.CopyTo(argInfos, 0);

                    argInfos[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
                    CSharpInvokeBinder invoke = new CSharpInvokeBinder(callPayload.Flags, callPayload.CallingContext, argInfos);

                    DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length - 1];
                    Array.Copy(args, 1, newArgs, 0, args.Length - 1);
                    deferredBinding = invoke.Defer(getMember.Defer(args[0]), newArgs);
                    return true;
                }
            }

            deferredBinding = null;
            return false;
        }
예제 #3
0
        /////////////////////////////////////////////////////////////////////////////////

        private EXPR BindIsEvent(
            CSharpIsEventBinder binder,
            ArgumentObject[] arguments,
            Dictionary<int, LocalVariableSymbol> dictionary)
        {
            // The IsEvent binder will never be called without an instance object. This 
            // is because the compiler only gen's this code for dynamic dots.

            EXPR callingObject = CreateLocal(arguments[0].Type, false, dictionary[0]);
            MemberLookup mem = new MemberLookup();
            CType boolType = SymbolLoader.GetReqPredefType(PredefinedType.PT_BOOL);
            bool result = false;

            if (arguments[0].Value == null)
            {
                throw Error.NullReferenceOnMemberException();
            }

            Debug.Assert(_bindingContext.ContextForMemberLookup() != null);
            SymWithType swt = _symbolTable.LookupMember(
                    binder.Name,
                    callingObject,
                    _bindingContext.ContextForMemberLookup(),
                    0,
                    mem,
                    false,
                    false);

            // If lookup returns an actual event, then this is an event.
            if (swt != null && swt.Sym.getKind() == SYMKIND.SK_EventSymbol)
            {
                result = true;
            }

            // If lookup returns the backing field of a field-like event, then
            // this is an event. This is due to the Dev10 design change around
            // the binding of +=, and the fact that the "IsEvent" binding question
            // is only ever asked about the LHS of a += or -=.
            if (swt != null && swt.Sym.getKind() == SYMKIND.SK_FieldSymbol && swt.Sym.AsFieldSymbol().isEvent)
            {
                result = true;
            }

            return _exprFactory.CreateConstant(boolType, ConstValFactory.GetBool(result));
        }
예제 #4
0
        /////////////////////////////////////////////////////////////////////////////////

        private EXPR BindProperty(
            DynamicMetaObjectBinder payload,
            ArgumentObject argument,
            LocalVariableSymbol local,
            EXPR optionalIndexerArguments,
            bool fEventsPermitted)
        {
            // If our argument is a static type, then we're calling a static property.
            EXPR callingObject = argument.Info.IsStaticType ?
                _exprFactory.CreateClass(_symbolTable.GetCTypeFromType(argument.Value as Type), null, null) :
                CreateLocal(argument.Type, argument.Info.IsOut, local);

            if (!argument.Info.UseCompileTimeType && argument.Value == null)
            {
                throw Error.NullReferenceOnMemberException();
            }

            // If our argument is a struct type, unbox it.
            if (argument.Type.GetTypeInfo().IsValueType && callingObject.isCAST())
            {
                // If we have a struct type, unbox it.
                callingObject.flags |= EXPRFLAG.EXF_UNBOXRUNTIME;
            }
            string name = GetName(payload);
            BindingFlag bindFlags = GetBindingFlags(payload);

            MemberLookup mem = new MemberLookup();
            SymWithType swt = _symbolTable.LookupMember(name, callingObject, _bindingContext.ContextForMemberLookup(), 0, mem, false, false);
            if (swt == null)
            {
                if (optionalIndexerArguments != null)
                {
                    int numIndexArguments = ExpressionIterator.Count(optionalIndexerArguments);
                    // We could have an array access here. See if its just an array.
                    if ((argument.Type.IsArray && argument.Type.GetArrayRank() == numIndexArguments) ||
                        argument.Type == typeof(string))
                    {
                        return CreateArray(callingObject, optionalIndexerArguments);
                    }
                }
                mem.ReportErrors();
                Debug.Assert(false, "Why didn't member lookup report an error?");
            }

            switch (swt.Sym.getKind())
            {
                case SYMKIND.SK_MethodSymbol:
                    throw Error.BindPropertyFailedMethodGroup(name);

                case SYMKIND.SK_PropertySymbol:
                    if (swt.Sym is IndexerSymbol)
                    {
                        return CreateIndexer(swt, callingObject, optionalIndexerArguments, bindFlags);
                    }
                    else
                    {
                        BindingFlag flags = 0;
                        if (payload is CSharpGetMemberBinder || payload is CSharpGetIndexBinder)
                        {
                            flags = BindingFlag.BIND_RVALUEREQUIRED;
                        }

                        // Properties can be LValues.
                        callingObject.flags |= EXPRFLAG.EXF_LVALUE;
                        return CreateProperty(swt, callingObject, flags);
                    }

                case SYMKIND.SK_FieldSymbol:
                    return CreateField(swt, callingObject);

                case SYMKIND.SK_EventSymbol:
                    if (fEventsPermitted)
                    {
                        return CreateEvent(swt, callingObject);
                    }
                    else
                    {
                        throw Error.BindPropertyFailedEvent(name);
                    }

                default:
                    Debug.Assert(false, "Unexpected type returned from lookup");
                    throw Error.InternalCompilerError();
            }
        }
예제 #5
0
        /////////////////////////////////////////////////////////////////////////////////

        private EXPR BindCall(
            ICSharpInvokeOrInvokeMemberBinder payload,
            EXPR callingObject,
            ArgumentObject[] arguments,
            Dictionary<int, LocalVariableSymbol> dictionary)
        {
            if (payload is InvokeBinder && !callingObject.type.isDelegateType())
            {
                throw Error.BindInvokeFailedNonDelegate();
            }

            EXPR pResult = null;
            int arity = payload.TypeArguments != null ? payload.TypeArguments.Count : 0;
            MemberLookup mem = new MemberLookup();

            Debug.Assert(_bindingContext.ContextForMemberLookup() != null);
            SymWithType swt = _symbolTable.LookupMember(
                    payload.Name,
                    callingObject,
                    _bindingContext.ContextForMemberLookup(),
                    arity,
                    mem,
                    (payload.Flags & CSharpCallFlags.EventHookup) != 0,
                    true);
            if (swt == null)
            {
                mem.ReportErrors();
                Debug.Assert(false, "Why didn't member lookup report an error?");
            }

            if (swt.Sym.getKind() != SYMKIND.SK_MethodSymbol)
            {
                Debug.Assert(false, "Unexpected type returned from lookup");
                throw Error.InternalCompilerError();
            }

            // At this point, we're set up to do binding. We need to do the following:
            //
            // 1) Create the EXPRLOCALs for the arguments, linking them to the local
            //    variable symbols defined above.
            // 2) Create the EXPRMEMGRP for the call and the EXPRLOCAL for the object
            //    of the call, and link the correct local variable symbol as above.
            // 3) Do overload resolution to get back an EXPRCALL.
            //
            // Our caller takes care of the rest.

            // First we need to check the sym that we got back. If we got back a static 
            // method, then we may be in the situation where the user called the method
            // via a simple name call through the phantom overload. If thats the case,
            // then we want to sub in a type instead of the object.
            EXPRMEMGRP memGroup = CreateMemberGroupEXPR(payload.Name, payload.TypeArguments, callingObject, swt.Sym.getKind());
            if ((payload.Flags & CSharpCallFlags.SimpleNameCall) != 0)
            {
                callingObject.flags |= EXPRFLAG.EXF_SIMPLENAME;
            }

            if ((payload.Flags & CSharpCallFlags.EventHookup) != 0)
            {
                mem = new MemberLookup();
                SymWithType swtEvent = _symbolTable.LookupMember(
                        payload.Name.Split('_')[1],
                        callingObject,
                        _bindingContext.ContextForMemberLookup(),
                        arity,
                        mem,
                        (payload.Flags & CSharpCallFlags.EventHookup) != 0,
                        true);
                if (swtEvent == null)
                {
                    mem.ReportErrors();
                    Debug.Assert(false, "Why didn't member lookup report an error?");
                }

                CType eventCType = null;
                if (swtEvent.Sym.getKind() == SYMKIND.SK_FieldSymbol)
                {
                    eventCType = swtEvent.Field().GetType();
                }
                else if (swtEvent.Sym.getKind() == SYMKIND.SK_EventSymbol)
                {
                    eventCType = swtEvent.Event().type;
                }

                Type eventType = SymbolLoader.GetTypeManager().SubstType(eventCType, swtEvent.Ats).AssociatedSystemType;

                if (eventType != null)
                {
                    // If we have an event hookup, first find the event itself.
                    BindImplicitConversion(new ArgumentObject[] { arguments[1] }, eventType, dictionary, false);
                }
                memGroup.flags &= ~EXPRFLAG.EXF_USERCALLABLE;

                if (swtEvent.Sym.getKind() == SYMKIND.SK_EventSymbol && swtEvent.Event().IsWindowsRuntimeEvent)
                {
                    return BindWinRTEventAccessor(
                                    new EventWithType(swtEvent.Event(), swtEvent.Ats),
                                    callingObject,
                                    arguments,
                                    dictionary,
                                    payload.Name.StartsWith("add_", StringComparison.Ordinal)); //isAddAccessor?
                }
            }

            // Check if we have a potential call to an indexed property accessor.
            // If so, we'll flag overload resolution to let us call non-callables.
            if ((payload.Name.StartsWith("set_", StringComparison.Ordinal) && swt.Sym.AsMethodSymbol().Params.Size > 1) ||
                (payload.Name.StartsWith("get_", StringComparison.Ordinal) && swt.Sym.AsMethodSymbol().Params.Size > 0))
            {
                memGroup.flags &= ~EXPRFLAG.EXF_USERCALLABLE;
            }

            pResult = _binder.BindMethodGroupToArguments(// Tree
                BindingFlag.BIND_RVALUEREQUIRED | BindingFlag.BIND_STMTEXPRONLY, memGroup, CreateArgumentListEXPR(arguments, dictionary, 1, arguments.Length));

            // If overload resolution failed, throw an error.
            if (pResult == null || !pResult.isOK())
            {
                throw Error.BindCallFailedOverloadResolution();
            }
            CheckForConditionalMethodError(pResult);

            return ReorderArgumentsForNamedAndOptional(callingObject, pResult);
        }
예제 #6
0
        protected EXPR bindIndexer(EXPR pObject, EXPR args, BindingFlag bindFlags)
        {
            CType type = pObject.type;

            if (!type.IsAggregateType() && !type.IsTypeParameterType())
            {
                ErrorContext.Error(ErrorCode.ERR_BadIndexLHS, type);
                MethWithInst mwi = new MethWithInst(null, null);
                EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(pObject, mwi);
                EXPRCALL rval = GetExprFactory().CreateCall(0, type, args, pMemGroup, null);
                rval.SetError();
                return rval;
            }

            Name pName = GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_INDEXERINTERNAL);

            MemberLookup mem = new MemberLookup();
            if (!mem.Lookup(GetSemanticChecker(), type, pObject, ContextForMemberLookup(), pName, 0,
                            (bindFlags & BindingFlag.BIND_BASECALL) != 0 ? (MemLookFlags.BaseCall | MemLookFlags.Indexer) : MemLookFlags.Indexer))
            {
                mem.ReportErrors();
                type = GetTypes().GetErrorSym();
                Symbol pSymbol = null;

                if (mem.SwtInaccessible().Sym != null)
                {
                    Debug.Assert(mem.SwtInaccessible().Sym.IsMethodOrPropertySymbol());
                    type = mem.SwtInaccessible().MethProp().RetType;
                    pSymbol = mem.SwtInaccessible().Sym;
                }

                EXPRMEMGRP memgrp = null;

                if (pSymbol != null)
                {
                    memgrp = GetExprFactory().CreateMemGroup((EXPRFLAG)mem.GetFlags(),
                        pName, BSYMMGR.EmptyTypeArray(), pSymbol.getKind(), mem.GetSourceType(), null/*pMPS*/, mem.GetObject(), mem.GetResults());
                    memgrp.SetInaccessibleBit();
                }
                else
                {
                    MethWithInst mwi = new MethWithInst(null, null);
                    memgrp = GetExprFactory().CreateMemGroup(mem.GetObject(), mwi);
                }

                EXPRCALL rval = GetExprFactory().CreateCall(0, type, args, memgrp, null);
                rval.SetError();
                return rval;
            }

            Debug.Assert(mem.SymFirst().IsPropertySymbol() && mem.SymFirst().AsPropertySymbol().isIndexer());

            EXPRMEMGRP grp = GetExprFactory().CreateMemGroup((EXPRFLAG)mem.GetFlags(),
                pName, BSYMMGR.EmptyTypeArray(), mem.SymFirst().getKind(), mem.GetSourceType(), null/*pMPS*/, mem.GetObject(), mem.GetResults());

            EXPR pResult = BindMethodGroupToArguments(bindFlags, grp, args);
            Debug.Assert(pResult.HasObject());
            if (pResult.getObject() == null)
            {
                // We must be in an error scenario where the object was not allowed. 
                // This can happen if the user tries to access the indexer off the
                // type and not an instance or if the incorrect type/number of arguments 
                // were passed for binding.
                pResult.SetObject(pObject);
                pResult.SetError();
            }
            return pResult;
        }