Inheritance: DynamicExpressionStatement, IDynamicBinder
Ejemplo n.º 1
0
        public void EmitPrologue(EmitContext ec)
        {
            awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type);

            var fe_awaiter = new FieldExpr(awaiter, loc);

            fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc);

            Label skip_continuation = ec.DefineLabel();

            using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) {
                //
                // awaiter = expr.GetAwaiter ();
                //
                fe_awaiter.EmitAssign(ec, expr, false, false);

                Expression completed_expr;
                if (IsDynamic)
                {
                    var rc = new ResolveContext(ec.MemberContext);

                    Arguments dargs = new Arguments(1);
                    dargs.Add(new Argument(fe_awaiter));
                    completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc);

                    dargs = new Arguments(1);
                    dargs.Add(new Argument(completed_expr));
                    completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc);
                }
                else
                {
                    var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc);
                    pe.InstanceExpression = fe_awaiter;
                    completed_expr        = pe;
                }

                completed_expr.EmitBranchable(ec, skip_continuation, true);
            }

            base.DoEmit(ec);

            //
            // The stack has to be empty before calling await continuation. We handle this
            // by lifting values which would be left on stack into class fields. The process
            // is quite complicated and quite hard to test because any expression can possibly
            // leave a value on the stack.
            //
            // Following assert fails when some of expression called before is missing EmitToField
            // or parent expression fails to find await in children expressions
            //
            ec.AssertEmptyStack();

            var storey = (AsyncTaskStorey)machine_initializer.Storey;

            if (IsDynamic)
            {
                storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter);
            }
            else
            {
                storey.EmitAwaitOnCompleted(ec, fe_awaiter);
            }

            // Return ok
            machine_initializer.EmitLeave(ec, unwind_protect);

            ec.MarkLabel(resume_point);
            ec.MarkLabel(skip_continuation);
        }
Ejemplo n.º 2
0
			protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer)
			{
				if (li.Type == InternalType.Dynamic) {
					initializer = initializer.Resolve (bc);
					if (initializer == null)
						return null;

					// Once there is dynamic used defer conversion to runtime even if we know it will never succeed
					Arguments args = new Arguments (1);
					args.Add (new Argument (initializer));
					initializer = new DynamicConversion (TypeManager.idisposable_type, 0, args, initializer.Location).Resolve (bc);
					if (initializer == null)
						return null;

					var var = LocalVariable.CreateCompilerGenerated (TypeManager.idisposable_type, bc.CurrentBlock, loc);
					dispose_call = CreateDisposeCall (bc, var);
					dispose_call.Resolve (bc);

					return base.ResolveInitializer (bc, li, new SimpleAssign (var.CreateReferenceExpression (bc, loc), initializer, loc));
				}

				if (li == Variable) {
					CheckIDiposableConversion (bc, li, initializer);
					dispose_call = CreateDisposeCall (bc, li);
					dispose_call.Resolve (bc);
				}

				return base.ResolveInitializer (bc, li, initializer);
			}