示例#1
0
        /// <summary>
        /// Generate the body for <c>MoveNext()</c>.
        /// </summary>
        protected override void CreateMoveNext()
        {
            Method asyncMethod = _method.Method;

            BooMethodBuilder methodBuilder = _stateMachineClass.AddVirtualMethod("MoveNext", TypeSystemServices.VoidType);

            methodBuilder.Method.LexicalInfo = asyncMethod.LexicalInfo;
            _moveNext = methodBuilder.Entity;

            TransformLocalsIntoFields(asyncMethod);
            TransformParametersIntoFieldsInitializedByConstructor(_method.Method);

            _exprReturnLabel = CodeBuilder.CreateLabel(methodBuilder.Method, "exprReturn", 0);
            _exitLabel       = CodeBuilder.CreateLabel(methodBuilder.Method, "exitLabel", 0);
            _isGenericTask   = _method.ReturnType.ConstructedInfo != null;
            _exprRetValue    = _isGenericTask
                ? CodeBuilder.DeclareTempLocal(_moveNext.Method, _methodToStateMachineMapper.MapType(_asyncMethodBuilderMemberCollection.ResultType))
                : null;

            _cachedState = CodeBuilder.DeclareLocal(methodBuilder.Method, UniqueName("state"),
                                                    TypeSystemServices.IntType);

            _seenAwait = false;
            var rewrittenBody = (Block)Visit(_method.Method.Body);

            if (!_seenAwait)
            {
                Context.Warnings.Add(CompilerWarningFactory.AsyncNoAwait(_method.Method));
            }

            var bodyBuilder = methodBuilder.Body;

            bodyBuilder.Add(CodeBuilder.CreateAssignment(
                                CodeBuilder.CreateLocalReference(_cachedState),
                                CodeBuilder.CreateMemberReference(_state)));

            CheckForTryExcept();

            Block bodyBlock;

            if (_labels.Count > 0)
            {
                var dispatch =
                    CodeBuilder.CreateSwitch(
                        this.LexicalInfo,
                        CodeBuilder.CreateLocalReference(_cachedState),
                        _labels);
                CheckTryJumps((MethodInvocationExpression)((ExpressionStatement)dispatch).Expression);
                bodyBlock = new Block(dispatch, rewrittenBody);
            }
            else
            {
                bodyBlock = rewrittenBody;
            }
            InternalLocal exceptionLocal;

            bodyBuilder.Add(CodeBuilder.CreateTryExcept(
                                this.LexicalInfo,
                                bodyBlock,
                                new ExceptionHandler
            {
                Declaration = CodeBuilder.CreateDeclaration(
                    methodBuilder.Method,
                    UniqueName("exception"),
                    TypeSystemServices.ExceptionType,
                    out exceptionLocal),
                Block = new Block(
                    CodeBuilder.CreateFieldAssignment(
                        this.LexicalInfo,
                        _state,
                        CodeBuilder.CreateIntegerLiteral(StateMachineStates.FinishedStateMachine)),
                    new ExpressionStatement(
                        CodeBuilder.CreateMethodInvocation(
                            CodeBuilder.CreateMemberReference(
                                CodeBuilder.CreateSelfReference(_stateMachineClass.Entity),
                                (IField)_asyncMethodBuilderField.Entity),
                            _asyncMethodBuilderMemberCollection.SetException,
                            CodeBuilder.CreateLocalReference(exceptionLocal))),
                    GenerateReturn())
            }));

            // ReturnLabel (for the rewritten return expressions in the user's method body)
            bodyBuilder.Add(_exprReturnLabel.LabelStatement);

            // this.state = finishedState
            bodyBuilder.Add(CodeBuilder.CreateFieldAssignment(
                                this.LexicalInfo,
                                _state,
                                CodeBuilder.CreateIntegerLiteral(StateMachineStates.FinishedStateMachine)));

            // builder.SetResult([RetVal])
            var setResultInvocation = CodeBuilder.CreateMethodInvocation(
                CodeBuilder.CreateMemberReference(
                    CodeBuilder.CreateSelfReference(_stateMachineClass.Entity),
                    (IField)_asyncMethodBuilderField.Entity),
                _asyncMethodBuilderMemberCollection.SetResult);

            if (_isGenericTask)
            {
                setResultInvocation.Arguments.Add(CodeBuilder.CreateLocalReference(_exprRetValue));
            }

            bodyBuilder.Add(new ExpressionStatement(setResultInvocation));

            // this code is hidden behind a hidden sequence point.
            bodyBuilder.Add(_exitLabel.LabelStatement);
            bodyBuilder.Add(new ReturnStatement());
        }