Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

Commit

Permalink
Added await/async support & updated mcs.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrueger committed Sep 30, 2011
1 parent d91eb2c commit e4c70d4
Show file tree
Hide file tree
Showing 22 changed files with 1,239 additions and 1,033 deletions.
6 changes: 5 additions & 1 deletion ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs
Expand Up @@ -57,7 +57,8 @@ protected internal override bool DoMatch(AstNode other, PatternMatching.Match ma
Modifiers.Abstract, Modifiers.Virtual, Modifiers.Sealed, Modifiers.Static, Modifiers.Override,
Modifiers.Readonly, Modifiers.Volatile,
Modifiers.Extern, Modifiers.Partial, Modifiers.Const,
Modifiers.Any
Modifiers.Any,
Modifiers.Async
};

public static IEnumerable<Modifiers> AllModifiers {
Expand Down Expand Up @@ -107,6 +108,9 @@ public static string GetModifierName(Modifiers modifier)
case Modifiers.Any:
// even though it's used for patterns only, it needs to be in this list to be usable in the AST
return "any";
case Modifiers.Async:
// even though it's used for patterns only, it needs to be in this list to be usable in the AST
return "async";
default:
throw new NotSupportedException("Invalid value for Modifiers");
}
Expand Down
39 changes: 29 additions & 10 deletions ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
Expand Up @@ -900,7 +900,6 @@ public override void Visit (Method m)
AddAttributeSection (newMethod, m);
var location = LocationsBag.GetMemberLocation (m);
AddModifiers (newMethod, location);

newMethod.AddChild (ConvertToType (m.TypeName), AstNode.Roles.Type);
if (m.MethodName.Left != null) {
newMethod.AddChild (ConvertToType (m.MethodName.Left), MethodDeclaration.PrivateImplementationTypeRole);
Expand Down Expand Up @@ -2891,14 +2890,19 @@ public override object Visit (Mono.CSharp.AnonymousMethodExpression anonymousMet
{
var result = new AnonymousMethodExpression ();
var location = LocationsBag.GetLocations (anonymousMethodExpression);
int l = 0;
if (anonymousMethodExpression.IsAsync) {
result.IsAsync = true;
result.AddChild (new CSharpTokenNode (Convert (location[l++]), "async".Length), AnonymousMethodExpression.AsyncModifierRole);
}
if (location != null) {
result.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword);

if (location.Count > 1) {
if (location.Count > l) {
result.HasParameterList = true;
result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AnonymousMethodExpression.Roles.LPar);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), 1), AnonymousMethodExpression.Roles.LPar);
AddParameter (result, anonymousMethodExpression.Parameters);
result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AnonymousMethodExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location[l++]), 1), AnonymousMethodExpression.Roles.RPar);
}
}
result.AddChild ((BlockStatement)anonymousMethodExpression.Block.Accept (this), AnonymousMethodExpression.Roles.Body);
Expand All @@ -2909,17 +2913,22 @@ public override object Visit (Mono.CSharp.LambdaExpression lambdaExpression)
{
var result = new LambdaExpression ();
var location = LocationsBag.GetLocations (lambdaExpression);
int l = 0;
if (lambdaExpression.IsAsync) {
result.IsAsync = true;
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "async".Length), LambdaExpression.AsyncModifierRole);
}

if (location == null || location.Count == 1) {
if (location == null || location.Count == l + 1) {
AddParameter (result, lambdaExpression.Parameters);
if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location [0]), "=>".Length), LambdaExpression.ArrowRole);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "=>".Length), LambdaExpression.ArrowRole);
} else {
result.AddChild (new CSharpTokenNode (Convert (lambdaExpression.Location), 1), LambdaExpression.Roles.LPar);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), 1), LambdaExpression.Roles.LPar);
AddParameter (result, lambdaExpression.Parameters);
if (location != null) {
result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), LambdaExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location [1]), "=>".Length), LambdaExpression.ArrowRole);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), 1), LambdaExpression.Roles.RPar);
result.AddChild (new CSharpTokenNode (Convert (location [l++]), "=>".Length), LambdaExpression.ArrowRole);
}
}
if (lambdaExpression.Block.IsCompilerGenerated) {
Expand Down Expand Up @@ -3192,6 +3201,16 @@ public override object Visit (Mono.CSharp.Linq.ThenByDescending thenByDescending
result.AddChild (ordering, QueryOrderClause.OrderingRole);
return result;
}

public override object Visit (Await awaitExpr)
{
var result = new UnaryOperatorExpression ();
result.Operator = UnaryOperatorType.Await;
result.AddChild (new CSharpTokenNode (Convert (awaitExpr.Location), 1), UnaryOperatorExpression.OperatorRole);
if (awaitExpr.Expression != null)
result.AddChild ((Expression)awaitExpr.Expression.Accept (this), UnaryOperatorExpression.Roles.Expression);
return result;
}
#endregion
}

Expand Down
10 changes: 9 additions & 1 deletion ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs
Expand Up @@ -1157,7 +1157,15 @@ public Expression Compatible (ResolveContext ec, TypeSpec type)
}
} else {
if (is_async) {
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc);
var rt = body.ReturnType;
if (rt.Kind != MemberKind.Void &&
rt != ec.Module.PredefinedTypes.Task.TypeSpec &&
!rt.IsGenericTask) {
ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'",
GetSignatureForError (), type.GetSignatureForError ());
}

AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, rt, loc);
}

am = body.Compatible (ec);
Expand Down
107 changes: 37 additions & 70 deletions ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs
Expand Up @@ -23,11 +23,17 @@

namespace Mono.CSharp
{
class Await : ExpressionStatement
public class Await : ExpressionStatement
{
Expression expr;
AwaitStatement stmt;


public Expression Expression {
get {
return expr;
}
}

public Await (Expression expr, Location loc)
{
this.expr = expr;
Expand Down Expand Up @@ -64,8 +70,7 @@ protected override Expression DoResolve (ResolveContext rc)
}

if (rc.IsUnsafe) {
// TODO: New error code
rc.Report.Error (-1900, loc,
rc.Report.Error (4004, loc,
"The `await' operator cannot be used in an unsafe context");
}

Expand Down Expand Up @@ -108,6 +113,11 @@ public override void EmitStatement (EmitContext ec)
{
stmt.EmitStatement (ec);
}

public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}

class AwaitStatement : YieldStatement<AsyncInitializer>
Expand All @@ -121,12 +131,12 @@ public AwaitableMemberAccess (Expression expr)

protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name)
{
Error_WrongGetAwaiter (rc, loc, type);
Error_OperatorCannotBeApplied (rc, type);
}

protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type)
{
rc.Report.Error (1991, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
}
}

Expand Down Expand Up @@ -288,16 +298,9 @@ public void EmitStatement (EmitContext ec)
}
}

static void Error_WrongGetAwaiter (ResolveContext rc, Location loc, TypeSpec type)
{
rc.Report.Error (1986, loc,
"The `await' operand type `{0}' must have suitable GetAwaiter method",
type.GetSignatureForError ());
}

void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter)
{
rc.Report.Error (1999, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members",
rc.Report.Error (4011, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members",
awaiter.GetSignatureForError ());
}

Expand Down Expand Up @@ -335,7 +338,10 @@ public override bool Resolve (BlockContext bc)
bc.Report.SetPrinter (old);

if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) {
Error_WrongGetAwaiter (bc, expr.Location, expr.Type);
bc.Report.Error (1986, expr.Location,
"The `await' operand type `{0}' must have suitable GetAwaiter method",
expr.Type.GetSignatureForError ());

return false;
}

Expand Down Expand Up @@ -428,12 +434,6 @@ public AsyncInitializer (ParametersBlock block, TypeContainer host, TypeSpec ret

public static void Create (IMemberContext context, ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc)
{
if (returnType != null && returnType.Kind != MemberKind.Void &&
returnType != host.Module.PredefinedTypes.Task.TypeSpec &&
!returnType.IsGenericTask) {
host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task<T>");
}

for (int i = 0; i < parameters.Count; i++) {
Parameter p = parameters[i];
Parameter.Modifier mod = p.ModFlags;
Expand All @@ -443,17 +443,15 @@ public static void Create (IMemberContext context, ParametersBlock block, Parame
return;
}

// TODO:
if (p is ArglistParameter) {
host.Compiler.Report.Error (1636, p.Location,
"__arglist is not allowed in parameter list of iterators");
host.Compiler.Report.Error (4006, p.Location,
"__arglist is not allowed in parameter list of async methods");
return;
}

// TODO:
if (parameters.Types[i].IsPointer) {
host.Compiler.Report.Error (1637, p.Location,
"Iterators cannot have unsafe parameters or yield types");
host.Compiler.Report.Error (4005, p.Location,
"Async methods cannot have unsafe parameters");
return;
}
}
Expand Down Expand Up @@ -533,41 +531,6 @@ public override void EmitStatement (EmitContext ec)

class AsyncTaskStorey : StateMachine
{
sealed class ParametersLoadStatement : Statement
{
readonly FieldSpec[] fields;
readonly TypeSpec[] parametersTypes;
readonly int thisParameterIndex;

public ParametersLoadStatement (FieldSpec[] fields, TypeSpec[] parametersTypes, int thisParameterIndex)
{
this.fields = fields;
this.parametersTypes = parametersTypes;
this.thisParameterIndex = thisParameterIndex;
}

protected override void CloneTo (CloneContext clonectx, Statement target)
{
throw new NotImplementedException ();
}

protected override void DoEmit (EmitContext ec)
{
for (int i = 0; i < fields.Length; ++i) {
var field = fields[i];
if (field == null)
continue;

ec.EmitArgumentLoad (thisParameterIndex);
ec.EmitArgumentLoad (i);
if (parametersTypes[i] is ReferenceContainer)
ec.EmitLoadFromPtr (field.MemberType);

ec.Emit (OpCodes.Stfld, field);
}
}
}

int awaiters;
Field builder, continuation;
readonly TypeSpec return_type;
Expand Down Expand Up @@ -658,22 +621,26 @@ protected override bool DoDefineMembers ()
bf = pred_members.AsyncTaskMethodBuilderCreate;
sr = pred_members.AsyncTaskMethodBuilderSetResult;
se = pred_members.AsyncTaskMethodBuilderSetException;
task = pred_members.AsyncTaskMethodBuilderTask.Resolve (Location);
task = pred_members.AsyncTaskMethodBuilderTask.Get ();
} else {
builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric;
bf = pred_members.AsyncTaskMethodBuilderGenericCreate;
sr = pred_members.AsyncTaskMethodBuilderGenericSetResult;
se = pred_members.AsyncTaskMethodBuilderGenericSetException;
task = pred_members.AsyncTaskMethodBuilderGenericTask.Resolve (Location);
task = pred_members.AsyncTaskMethodBuilderGenericTask.Get ();
has_task_return_type = true;
}

set_result = sr.Resolve (Location);
set_exception = se.Resolve (Location);
var builder_factory = bf.Resolve (Location);
var bt = builder_type.Resolve ();
if (bt == null || set_result == null || builder_factory == null || set_exception == null)
return false;
set_result = sr.Get ();
set_exception = se.Get ();
var builder_factory = bf.Get ();
if (!builder_type.Define () || set_result == null || builder_factory == null || set_exception == null) {
Report.Error (1993, Location,
"Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?");
return base.DoDefineMembers ();
}

var bt = builder_type.TypeSpec;

//
// Inflate generic Task types
Expand Down
23 changes: 13 additions & 10 deletions ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs
Expand Up @@ -2593,12 +2593,6 @@ protected override void DefineContainerMembers (System.Collections.IList list)
continue;
}

Method method = m as Method;
if (method != null && method.ParameterInfo.HasExtensionMethodType) {
Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
continue;
}

Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
}

Expand Down Expand Up @@ -3598,13 +3592,22 @@ protected virtual void DoMemberTypeDependentChecks ()
}
}

protected bool IsTypePermitted ()
protected void IsTypePermitted ()
{
if (MemberType.IsSpecialRuntimeType) {
Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
return false;
if (Parent is StateMachine) {
Report.Error (4012, Location,
"Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
MemberType.GetSignatureForError ());
} else if (Parent is HoistedStoreyClass) {
Report.Error (4013, Location,
"Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
MemberType.GetSignatureForError ());
} else {
Report.Error (610, Location,
"Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
}
}
return true;
}

protected virtual bool CheckBase ()
Expand Down

0 comments on commit e4c70d4

Please sign in to comment.