private static bool TryCreateGenericTask(TypeSystemServices tss, IType genericArg, out AsyncMethodBuilderMemberCollection collection) { var builderType = tss.AsyncGenericTaskMethodBuilderType.GenericInfo.ConstructType(genericArg); return(TryCreate( builderType, genericArg, out collection)); }
private static bool TryCreateVoid(TypeSystemServices tss, out AsyncMethodBuilderMemberCollection collection) { var builderType = tss.AsyncVoidMethodBuilderType; var resultType = tss.VoidType; return(TryCreate( builderType, resultType, out collection)); }
private static bool TryCreate(IType builderType, IType resultType, out AsyncMethodBuilderMemberCollection collection) { var members = builderType.GetMembers().OfType <IMember>().Where(m => m.IsPublic).ToDictionary(m => m.Name); var task = members.ContainsKey("Task") ? (IProperty)members["Task"] : null; collection = new AsyncMethodBuilderMemberCollection( builderType, resultType, (IMethod)members["Create"], (IMethod)members["SetException"], (IMethod)members["SetResult"], (IMethod)members["AwaitOnCompleted"], (IMethod)members["AwaitUnsafeOnCompleted"], (IMethod)members["Start"], (IMethod)members["SetStateMachine"], task); return(true); }
public static bool TryCreate(TypeSystemServices tss, Method method, IType genericArg, out AsyncMethodBuilderMemberCollection collection) { if (ContextAnnotations.IsAsync(method)) { var returnType = (IType)method.ReturnType.Entity; if (returnType == tss.VoidType) { return(TryCreateVoid(tss, out collection)); } if (returnType == tss.TaskType) { return(TryCreateTask(tss, out collection)); } if (returnType.ConstructedInfo != null && returnType.ConstructedInfo.GenericDefinition == tss.GenericTaskType) { return(TryCreateGenericTask(tss, genericArg, out collection)); } } throw CompilerErrorFactory.InvalidAsyncType(method.ReturnType); }
protected override void SetupStateMachine() { _stateMachineClass.AddBaseType(TypeSystemServices.ValueTypeType); _stateMachineClass.AddBaseType(TypeSystemServices.IAsyncStateMachineType); _stateMachineClass.Modifiers |= TypeMemberModifiers.Final; var ctr = TypeSystemServices.Map(typeof(AsyncStateMachineAttribute)).GetConstructors().Single(); _method.Method.Attributes.Add( CodeBuilder.CreateAttribute( ctr, CodeBuilder.CreateTypeofExpression(_stateMachineClass.Entity))); AsyncMethodBuilderMemberCollection.TryCreate( TypeSystemServices, _method.Method, MethodGenArg(true), out _asyncMethodBuilderMemberCollection); _state = (IField)_stateMachineClass.AddInternalField(UniqueName("State"), TypeSystemServices.IntType).Entity; _asyncMethodBuilderField = _stateMachineClass.AddInternalField( UniqueName("Builder"), _asyncMethodBuilderMemberCollection.BuilderType); CreateSetStateMachine(); PreprocessMethod(); }
private void FixAsyncMethodBody(MethodInvocationExpression stateMachineConstructorInvocation) { var method = _method.Method; // If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder<T> // needs to use the method's type parameters inside the rewritten method body. All other methods generated // during async rewriting are members of the synthesized state machine struct, and use the type parameters // structs type parameters. AsyncMethodBuilderMemberCollection methodScopeAsyncMethodBuilderMemberCollection; if (!AsyncMethodBuilderMemberCollection.TryCreate( TypeSystemServices, method, MethodGenArg(false), out methodScopeAsyncMethodBuilderMemberCollection)) { throw new NotImplementedException("Custom async patterns are not supported"); } var bodyBuilder = new Block(); var builderVariable = CodeBuilder.DeclareTempLocal(method, methodScopeAsyncMethodBuilderMemberCollection.BuilderType); var stateMachineType = stateMachineConstructorInvocation.ExpressionType; var stateMachineVariable = CodeBuilder.DeclareLocal( method, UniqueName("async"), stateMachineType); bodyBuilder.Add(CodeBuilder.CreateAssignment( CodeBuilder.CreateLocalReference(stateMachineVariable), stateMachineConstructorInvocation)); // local.$builder = System.Runtime.CompilerServices.AsyncTaskMethodBuilder<typeArgs>.Create(); bodyBuilder.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateMemberReference( CodeBuilder.CreateLocalReference(stateMachineVariable), ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType)), CodeBuilder.CreateMethodInvocation(methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder))); // local.$stateField = NotStartedStateMachine bodyBuilder.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateMemberReference( CodeBuilder.CreateLocalReference(stateMachineVariable), ExternalFieldEntity(_state, stateMachineType)), CodeBuilder.CreateIntegerLiteral(StateMachineStates.NotStartedStateMachine))); bodyBuilder.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateLocalReference(builderVariable), CodeBuilder.CreateMemberReference( CodeBuilder.CreateLocalReference(stateMachineVariable), ExternalFieldEntity((IField)_asyncMethodBuilderField.Entity, stateMachineType)))); // local.$builder.Start(ref local) -- binding to the method AsyncTaskMethodBuilder<typeArgs>.Start() bodyBuilder.Add( CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateLocalReference(builderVariable), methodScopeAsyncMethodBuilderMemberCollection.Start.GenericInfo.ConstructMethod(stateMachineType), CodeBuilder.CreateLocalReference(stateMachineVariable))); var methodBuilderField = stateMachineType.ConstructedInfo == null ? (IField)_asyncMethodBuilderField.Entity : stateMachineType.ConstructedInfo.Map((IField)_asyncMethodBuilderField.Entity); bodyBuilder.Add(method.ReturnType.Entity == TypeSystemServices.VoidType ? new ReturnStatement() : new ReturnStatement( CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateMemberReference( CodeBuilder.CreateLocalReference(stateMachineVariable), methodBuilderField), methodScopeAsyncMethodBuilderMemberCollection.Task.GetGetMethod()))); _method.Method.Body = bodyBuilder; }