{
class Await : ExpressionStatement
{
- readonly Expression expr;
+ Expression expr;
AwaitStatement stmt;
public Await (Expression expr, Location loc)
this.loc = loc;
}
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ var t = (Await) target;
+
+ t.expr = expr.Clone (clonectx);
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotImplementedException ("ET");
}
stmt = new AwaitStatement (expr, loc);
- stmt.Resolve (bc);
+ if (!stmt.Resolve (bc))
+ return null;
type = stmt.ResultType;
eclass = ExprClass.Variable;
public override void Emit (EmitContext ec)
{
+ stmt.EmitPrologue (ec);
+ stmt.Emit (ec);
+ }
+
+ public void EmitAssign (EmitContext ec, FieldExpr field)
+ {
+ stmt.EmitPrologue (ec);
+ field.InstanceExpression.Emit (ec);
stmt.Emit (ec);
}
var fe_awaiter = new FieldExpr (awaiter, loc);
fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
+ //
+ // result = awaiter.GetResult ();
+ //
+ var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
+ mg_result.InstanceExpression = fe_awaiter;
+
+ mg_result.EmitCall (ec, new Arguments (0));
+ }
+
+ public void EmitPrologue (EmitContext ec)
+ {
+ var fe_awaiter = new FieldExpr (awaiter, loc);
+ fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
+
//
// awaiter = expr.GetAwaiter ();
//
mg_completed.EmitCall (ec, args);
base.DoEmit (ec);
-
- //
- // result = awaiter.GetResult ();
- //
- var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
- mg_result.InstanceExpression = fe_awaiter;
-
- mg_result.EmitCall (ec, new Arguments (0));
}
public void EmitStatement (EmitContext ec)
{
+ EmitPrologue (ec);
Emit (ec);
if (ResultType.Kind != MemberKind.Void) {
public class AsyncInitializer : StateMachineInitializer
{
+ TypeInferenceContext return_inference;
+
public AsyncInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType)
: base (block, host, returnType)
{
}
+ #region Properties
+
public override string ContainerType {
get {
return "async state machine block";
}
}
+ public Block OriginalBlock {
+ get {
+ return block.Parent;
+ }
+ }
+
+ public TypeInferenceContext ReturnTypeInference {
+ get {
+ return return_inference;
+ }
+ }
+
+ #endregion
+
public static void Create (ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc)
{
- if (returnType.Kind != MemberKind.Void &&
+ if (returnType != null && returnType.Kind != MemberKind.Void &&
returnType != host.Module.PredefinedTypes.Task.TypeSpec &&
- returnType.MemberDefinition != host.Module.PredefinedTypes.TaskGeneric.TypeSpec.MemberDefinition) {
+ !returnType.IsGenericTask) {
host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task<T>");
}
block.WrapIntoAsyncTask (host, returnType);
}
+ protected override BlockContext CreateBlockContext (ResolveContext rc)
+ {
+ var ctx = base.CreateBlockContext (rc);
+ var lambda = rc.CurrentAnonymousMethod as LambdaMethod;
+ if (lambda != null)
+ return_inference = lambda.ReturnTypeInference;
+
+ return ctx;
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
return base.CreateExpressionTree (ec);
protected override void EmitMoveNextEpilogue (EmitContext ec)
{
- base.EmitMoveNextEpilogue (ec);
-
var storey = (AsyncTaskStorey) Storey;
storey.EmitSetResult (ec);
}
LocalVariable hoisted_return;
public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type)
- : base (initializer.Block, initializer.Host, null, null, "async")
+ : base (initializer.OriginalBlock, initializer.Host, null, null, "async")
{
return_type = type;
}