Example #1
0
        private static bool TryCreateGenericTask(TypeSystemServices tss,
                                                 IType genericArg, out AsyncMethodBuilderMemberCollection collection)
        {
            var builderType = tss.AsyncGenericTaskMethodBuilderType.GenericInfo.ConstructType(genericArg);

            return(TryCreate(
                       builderType,
                       genericArg,
                       out collection));
        }
Example #2
0
        private static bool TryCreateVoid(TypeSystemServices tss,
                                          out AsyncMethodBuilderMemberCollection collection)
        {
            var builderType = tss.AsyncVoidMethodBuilderType;
            var resultType  = tss.VoidType;

            return(TryCreate(
                       builderType,
                       resultType,
                       out collection));
        }
Example #3
0
        private static bool TryCreate(IType builderType, IType resultType,
                                      out AsyncMethodBuilderMemberCollection collection)
        {
            var members = builderType.GetMembers().OfType <IMember>().Where(m => m.IsPublic).ToDictionary(m => m.Name);
            var task    = members.ContainsKey("Task") ? (IProperty)members["Task"] : null;

            collection = new AsyncMethodBuilderMemberCollection(
                builderType,
                resultType,
                (IMethod)members["Create"],
                (IMethod)members["SetException"],
                (IMethod)members["SetResult"],
                (IMethod)members["AwaitOnCompleted"],
                (IMethod)members["AwaitUnsafeOnCompleted"],
                (IMethod)members["Start"],
                (IMethod)members["SetStateMachine"],
                task);

            return(true);
        }
Example #4
0
        public static bool TryCreate(TypeSystemServices tss, Method method, IType genericArg,
                                     out AsyncMethodBuilderMemberCollection collection)
        {
            if (ContextAnnotations.IsAsync(method))
            {
                var returnType = (IType)method.ReturnType.Entity;
                if (returnType == tss.VoidType)
                {
                    return(TryCreateVoid(tss, out collection));
                }
                if (returnType == tss.TaskType)
                {
                    return(TryCreateTask(tss, out collection));
                }
                if (returnType.ConstructedInfo != null &&
                    returnType.ConstructedInfo.GenericDefinition == tss.GenericTaskType)
                {
                    return(TryCreateGenericTask(tss, genericArg, out collection));
                }
            }

            throw CompilerErrorFactory.InvalidAsyncType(method.ReturnType);
        }
Example #5
0
        protected override void SetupStateMachine()
        {
            _stateMachineClass.AddBaseType(TypeSystemServices.ValueTypeType);
            _stateMachineClass.AddBaseType(TypeSystemServices.IAsyncStateMachineType);
            _stateMachineClass.Modifiers |= TypeMemberModifiers.Final;
            var ctr = TypeSystemServices.Map(typeof(AsyncStateMachineAttribute)).GetConstructors().Single();

            _method.Method.Attributes.Add(
                CodeBuilder.CreateAttribute(
                    ctr,
                    CodeBuilder.CreateTypeofExpression(_stateMachineClass.Entity)));
            AsyncMethodBuilderMemberCollection.TryCreate(
                TypeSystemServices,
                _method.Method,
                MethodGenArg(true),
                out _asyncMethodBuilderMemberCollection);

            _state = (IField)_stateMachineClass.AddInternalField(UniqueName("State"), TypeSystemServices.IntType).Entity;
            _asyncMethodBuilderField = _stateMachineClass.AddInternalField(
                UniqueName("Builder"),
                _asyncMethodBuilderMemberCollection.BuilderType);
            CreateSetStateMachine();
            PreprocessMethod();
        }
Example #6
0
        private void FixAsyncMethodBody(MethodInvocationExpression stateMachineConstructorInvocation)
        {
            var method = _method.Method;
            // If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder<T>
            // needs to use the method's type parameters inside the rewritten method body. All other methods generated
            // during async rewriting are members of the synthesized state machine struct, and use the type parameters
            // structs type parameters.
            AsyncMethodBuilderMemberCollection methodScopeAsyncMethodBuilderMemberCollection;

            if (!AsyncMethodBuilderMemberCollection.TryCreate(
                    TypeSystemServices,
                    method,
                    MethodGenArg(false),
                    out methodScopeAsyncMethodBuilderMemberCollection))
            {
                throw new NotImplementedException("Custom async patterns are not supported");
            }

            var bodyBuilder     = new Block();
            var builderVariable = CodeBuilder.DeclareTempLocal(method, methodScopeAsyncMethodBuilderMemberCollection.BuilderType);

            var stateMachineType = stateMachineConstructorInvocation.ExpressionType;

            var stateMachineVariable = CodeBuilder.DeclareLocal(
                method,
                UniqueName("async"),
                stateMachineType);

            bodyBuilder.Add(CodeBuilder.CreateAssignment(
                                CodeBuilder.CreateLocalReference(stateMachineVariable),
                                stateMachineConstructorInvocation));

            // local.$builder = System.Runtime.CompilerServices.AsyncTaskMethodBuilder<typeArgs>.Create();
            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType)),
                    CodeBuilder.CreateMethodInvocation(methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

            // local.$stateField = NotStartedStateMachine
            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity(_state, stateMachineType)),
                    CodeBuilder.CreateIntegerLiteral(StateMachineStates.NotStartedStateMachine)));

            bodyBuilder.Add(
                CodeBuilder.CreateAssignment(
                    CodeBuilder.CreateLocalReference(builderVariable),
                    CodeBuilder.CreateMemberReference(
                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                        ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType))));

            // local.$builder.Start(ref local) -- binding to the method AsyncTaskMethodBuilder<typeArgs>.Start()
            bodyBuilder.Add(
                CodeBuilder.CreateMethodInvocation(
                    CodeBuilder.CreateLocalReference(builderVariable),
                    methodScopeAsyncMethodBuilderMemberCollection.Start.GenericInfo.ConstructMethod(stateMachineType),
                    CodeBuilder.CreateLocalReference(stateMachineVariable)));

            var methodBuilderField = stateMachineType.ConstructedInfo == null
                        ? (IField)_asyncMethodBuilderField.Entity
                        : stateMachineType.ConstructedInfo.Map((IField)_asyncMethodBuilderField.Entity);

            bodyBuilder.Add(method.ReturnType.Entity == TypeSystemServices.VoidType
                ? new ReturnStatement()
                : new ReturnStatement(
                                CodeBuilder.CreateMethodInvocation(
                                    CodeBuilder.CreateMemberReference(
                                        CodeBuilder.CreateLocalReference(stateMachineVariable),
                                        methodBuilderField),
                                    methodScopeAsyncMethodBuilderMemberCollection.Task.GetGetMethod())));

            _method.Method.Body = bodyBuilder;
        }