public override bool Rewrite(CodeDescriptor decompilee, MethodBase callee, StackElement[] args, IDecompiler stack, IFunctionBuilder builder)
            {
                var ctx = stack.QueryAttribute<AsyncMethodDecompiler>();
                if (ctx.ImplStyle == EAsyncImplStyle.FSM)
                {
                    if (args.Length == 2 &&
                        ctx._curCoFSM.ResultVar != null)
                    {
                        builder.Store(ctx._curCoFSM.ResultVar, args[1].Expr);
                        if (args[1].Expr.ResultType.IsComplete)
                            ctx._curCoFSM.ResultVar.UpgradeType(args[1].Expr.ResultType);
                    }
                    
                    var si = ctx.ForkInitialSI();
                    var pi = new ProceedWithStateInfo()
                    {
                        TargetState = si,
                        TargetWaitState = false,
                        LambdaTransition = false
                    };

                    if (ctx._curCoFSM != null &&
                        ctx._curCoFSM.DoneVar != null)
                    {
                        var tr = LiteralReference.CreateConstant(true);
                        builder.Store(ctx._curCoFSM.DoneVar, tr);
                        pi.TargetState = null;
                    }

                    var fspec = new FunctionSpec(typeof(void))
                    {
                        IntrinsicRep = IntrinsicFunctions.ProceedWithState(pi)
                    };
                    builder.Call(fspec, LiteralReference.CreateConstant(pi));
                }
                return true;
            }
        private void ImplementJoin(JoinParams jp, IAlgorithmBuilder builder, StateInfo sin)
        {
            Contract.Requires<ArgumentNullException>(jp != null);
            Contract.Requires<ArgumentNullException>(builder != null);
            Contract.Requires<ArgumentNullException>(sin != null);

            var jspec = new FunctionSpec(typeof(bool))
            {
                IntrinsicRep = IntrinsicFunctions.Join(jp)
            };
            var jcall = new FunctionCall()
            {
                Callee = jspec,
                Arguments = new Expression[0],
                ResultType = typeof(bool)
            };

            builder.If(jcall);
            var pi1 = new ProceedWithStateInfo()
            {
                TargetState = sin,
                TargetWaitState = false,
                LambdaTransition = true
            };
            var pspec1 = new FunctionSpec(typeof(void))
            {
                IntrinsicRep = IntrinsicFunctions.ProceedWithState(pi1)
            };
            builder.Call(pspec1, LiteralReference.CreateConstant(pi1));
            builder.Else();
            var sin2 = sin.Fork(sin.ILState);
            var pi2 = new ProceedWithStateInfo()
            {
                TargetState = sin,
                TargetWaitState = true,
                LambdaTransition = false
            };
            var pspec2 = new FunctionSpec(typeof(void))
            {
                IntrinsicRep = IntrinsicFunctions.ProceedWithState(pi2)
            };
            builder.Call(pspec2, LiteralReference.CreateConstant(pi2));
            builder.EndIf();

            if (_curCoFSM != null)
                _curCoFSM.Dependencies.Add(jp.JoinedTask);
        }
            public override bool Rewrite(CodeDescriptor decompilee, MethodBase callee, StackElement[] args, IDecompiler stack, IFunctionBuilder builder)
            {
                var ctx = stack.QueryAttribute<AsyncMethodDecompiler>();
                if (ctx == null)
                    throw new InvalidOperationException("Method must be decompiled using AsyncMethodDecompiler.");
                if (ctx.ImplStyle == EAsyncImplStyle.Sequential)
                    return true;

                var awaiterCallExpr = stack.ResolveVariableReference(stack.CurrentILIndex, args[1].Expr);
                var awaiterCall = awaiterCallExpr as FunctionCall;
                if (awaiterCall != null)
                {
                    var waitObject = awaiterCall.Arguments[0];
                    var asyncCall = waitObject as FunctionCall;
                    if (asyncCall != null)
                    {
                        var cspec = asyncCall.Callee as FunctionSpec;
                        if (cspec != null && 
                            cspec.CILRep != null &&
                            cspec.CILRep.HasCustomOrInjectedAttribute<TickAttribute>())
                        {
                            var si = ctx.ForkNextSI();
                            var pi = new ProceedWithStateInfo()
                            {
                                TargetState = si,
                                TargetWaitState = false,
                                LambdaTransition = false
                            };
                            var fspec = new FunctionSpec(typeof(void))
                            {
                                IntrinsicRep = IntrinsicFunctions.ProceedWithState(pi)
                            };
                            builder.Call(fspec, LiteralReference.CreateConstant(pi));
                            return true;
                        }
                    }
                }

                var awaiter = args[1].Sample;
                var task = ctx.GetTaskFromAwaiter(awaiter);

                if (task != null)
                {
                    if (!task.IsCompleted)
                        throw new InvalidOperationException("Task not completed - what are you awaiting for?");

                    var sin = ctx.ForkNextSI();
                    sin.HasWaitState = true;
                    var jp = new JoinParams()
                    {
                        JoinedTask = task,
                        Continuation = sin
                    };
                    sin.JP = jp;
                    ctx.ImplementJoin(jp, builder, sin);
                }

                return true;
            }
 internal static IntrinsicFunction ProceedWithState(ProceedWithStateInfo pi)
 {
     return new IntrinsicFunction(
         IntrinsicFunction.EAction.ProceedWithState,
         pi);
 }