// // Return container with awaiter definition. It never returns null // but all container member can be null for easier error reporting // public AwaiterDefinition GetAwaiter(TypeSpec type) { AwaiterDefinition awaiter; if (awaiters.TryGetValue(type, out awaiter)) { return(awaiter); } awaiter = new AwaiterDefinition(); // // Predefined: bool IsCompleted { get; } // awaiter.IsCompleted = MemberCache.FindMember(type, MemberFilter.Property("IsCompleted", Compiler.BuiltinTypes.Bool), BindingRestriction.InstanceOnly) as PropertySpec; // // Predefined: GetResult () // // The method return type is also result type of await expression // awaiter.GetResult = MemberCache.FindMember(type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; // // Predefined: INotifyCompletion.OnCompleted (System.Action) // var nc = PredefinedTypes.INotifyCompletion; awaiter.INotifyCompletion = !nc.Define() || type.ImplementsInterface(nc.TypeSpec, false); awaiters.Add(type, awaiter); return(awaiter); }
public override bool Resolve(BlockContext bc) { if (bc.CurrentBlock is Linq.QueryBlock) { bc.Report.Error(1995, loc, "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause"); return(false); } if (!base.Resolve(bc)) { return(false); } Arguments args = new Arguments(0); type = expr.Type; // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; expr = ama; // // Predefined: bool IsCompleted { get; } // is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool), BindingRestriction.InstanceOnly) as PropertySpec; if (is_completed == null || !is_completed.HasGet) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: GetResult () // // The method return type is also result type of await expression // get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; if (get_result == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: INotifyCompletion.OnCompleted (System.Action) // var nc = bc.Module.PredefinedTypes.INotifyCompletion; if (nc.Define() && !awaiter_type.ImplementsInterface(nc.TypeSpec, false)) { bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'", awaiter_type.GetSignatureForError(), nc.GetSignatureForError()); return(false); } result_type = get_result.ReturnType; return(true); }
public PredefinedMembers(ModuleContainer module) { var types = module.PredefinedTypes; var atypes = module.PredefinedAttributes; var btypes = module.Compiler.BuiltinTypes; ActivatorCreateInstance = new PredefinedMember <MethodSpec> (module, types.Activator, MemberFilter.Method("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null)); AsyncTaskMethodBuilderCreate = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilder, MemberFilter.Method("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncTaskMethodBuilder.TypeSpec)); AsyncTaskMethodBuilderSetResult = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilder, MemberFilter.Method("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); AsyncTaskMethodBuilderSetException = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilder, MemberFilter.Method("SetException", 0, ParametersCompiled.CreateFullyResolved(btypes.Exception), btypes.Void)); AsyncTaskMethodBuilderTask = new PredefinedMember <PropertySpec> (module, types.AsyncTaskMethodBuilder, MemberFilter.Property("Task", null)); AsyncTaskMethodBuilderGenericCreate = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Method("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric, "SetResult", MemberKind.Method, () => new TypeSpec[] { types.AsyncTaskMethodBuilderGeneric.TypeSpec.MemberDefinition.TypeParameters[0] }); AsyncTaskMethodBuilderGenericSetException = new PredefinedMember <MethodSpec> (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Method("SetException", 0, ParametersCompiled.CreateFullyResolved(btypes.Exception), btypes.Void)); AsyncTaskMethodBuilderGenericTask = new PredefinedMember <PropertySpec> (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Property("Task", null)); AsyncVoidMethodBuilderCreate = new PredefinedMember <MethodSpec> (module, types.AsyncVoidMethodBuilder, MemberFilter.Method("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); AsyncVoidMethodBuilderSetException = new PredefinedMember <MethodSpec> (module, types.AsyncVoidMethodBuilder, MemberFilter.Method("SetException", 0, null, btypes.Void)); AsyncVoidMethodBuilderSetResult = new PredefinedMember <MethodSpec> (module, types.AsyncVoidMethodBuilder, MemberFilter.Method("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); DecimalCtor = new PredefinedMember <MethodSpec> (module, btypes.Decimal, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved( btypes.Int, btypes.Int, btypes.Int, btypes.Bool, btypes.Byte))); DecimalCtorInt = new PredefinedMember <MethodSpec> (module, btypes.Decimal, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(btypes.Int))); DecimalCtorLong = new PredefinedMember <MethodSpec> (module, btypes.Decimal, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(btypes.Long))); DecimalConstantAttributeCtor = new PredefinedMember <MethodSpec> (module, atypes.DecimalConstant, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved( btypes.Byte, btypes.Byte, btypes.UInt, btypes.UInt, btypes.UInt))); DefaultMemberAttributeCtor = new PredefinedMember <MethodSpec> (module, atypes.DefaultMember, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(btypes.String))); DelegateCombine = new PredefinedMember <MethodSpec> (module, btypes.Delegate, "Combine", btypes.Delegate, btypes.Delegate); DelegateRemove = new PredefinedMember <MethodSpec> (module, btypes.Delegate, "Remove", btypes.Delegate, btypes.Delegate); DelegateEqual = new PredefinedMember <MethodSpec> (module, btypes.Delegate, new MemberFilter(Operator.GetMetadataName(Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); DelegateInequal = new PredefinedMember <MethodSpec> (module, btypes.Delegate, new MemberFilter(Operator.GetMetadataName(Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); DynamicAttributeCtor = new PredefinedMember <MethodSpec> (module, atypes.Dynamic, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved( ArrayContainer.MakeType(module, btypes.Bool)))); FieldInfoGetFieldFromHandle = new PredefinedMember <MethodSpec> (module, types.FieldInfo, "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle); FieldInfoGetFieldFromHandle2 = new PredefinedMember <MethodSpec> (module, types.FieldInfo, "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle, new PredefinedType(btypes.RuntimeTypeHandle)); FixedBufferAttributeCtor = new PredefinedMember <MethodSpec> (module, atypes.FixedBuffer, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(btypes.Type, btypes.Int))); IDisposableDispose = new PredefinedMember <MethodSpec> (module, btypes.IDisposable, "Dispose", TypeSpec.EmptyTypes); IEnumerableGetEnumerator = new PredefinedMember <MethodSpec> (module, btypes.IEnumerable, "GetEnumerator", TypeSpec.EmptyTypes); InterlockedCompareExchange = new PredefinedMember <MethodSpec> (module, types.Interlocked, MemberFilter.Method("CompareExchange", 0, new ParametersImported( new[] { new ParameterData(null, Parameter.Modifier.REF), new ParameterData(null, Parameter.Modifier.NONE), new ParameterData(null, Parameter.Modifier.NONE) }, new[] { btypes.Int, btypes.Int, btypes.Int }, false), btypes.Int)); InterlockedCompareExchange_T = new PredefinedMember <MethodSpec> (module, types.Interlocked, MemberFilter.Method("CompareExchange", 1, new ParametersImported( new[] { new ParameterData(null, Parameter.Modifier.REF), new ParameterData(null, Parameter.Modifier.NONE), new ParameterData(null, Parameter.Modifier.NONE) }, new[] { new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), }, false), null)); MethodInfoGetMethodFromHandle = new PredefinedMember <MethodSpec> (module, types.MethodBase, "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle); MethodInfoGetMethodFromHandle2 = new PredefinedMember <MethodSpec> (module, types.MethodBase, "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle, new PredefinedType(btypes.RuntimeTypeHandle)); MonitorEnter = new PredefinedMember <MethodSpec> (module, types.Monitor, "Enter", btypes.Object); MonitorEnter_v4 = new PredefinedMember <MethodSpec> (module, types.Monitor, MemberFilter.Method("Enter", 0, new ParametersImported(new[] { new ParameterData(null, Parameter.Modifier.NONE), new ParameterData(null, Parameter.Modifier.REF) }, new[] { btypes.Object, btypes.Bool }, false), null)); MonitorExit = new PredefinedMember <MethodSpec> (module, types.Monitor, "Exit", btypes.Object); RuntimeCompatibilityWrapNonExceptionThrows = new PredefinedMember <PropertySpec> (module, atypes.RuntimeCompatibility, MemberFilter.Property("WrapNonExceptionThrows", btypes.Bool)); RuntimeHelpersInitializeArray = new PredefinedMember <MethodSpec> (module, types.RuntimeHelpers, "InitializeArray", btypes.Array, btypes.RuntimeFieldHandle); RuntimeHelpersOffsetToStringData = new PredefinedMember <PropertySpec> (module, types.RuntimeHelpers, MemberFilter.Property("OffsetToStringData", btypes.Int)); SecurityActionRequestMinimum = new PredefinedMember <ConstSpec> (module, types.SecurityAction, "RequestMinimum", MemberKind.Field, types.SecurityAction); StringEmpty = new PredefinedMember <FieldSpec> (module, btypes.String, MemberFilter.Field("Empty", btypes.String)); StringEqual = new PredefinedMember <MethodSpec> (module, btypes.String, new MemberFilter(Operator.GetMetadataName(Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); StringInequal = new PredefinedMember <MethodSpec> (module, btypes.String, new MemberFilter(Operator.GetMetadataName(Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); StructLayoutAttributeCtor = new PredefinedMember <MethodSpec> (module, atypes.StructLayout, MemberFilter.Constructor(ParametersCompiled.CreateFullyResolved(btypes.Short))); StructLayoutCharSet = new PredefinedMember <FieldSpec> (module, atypes.StructLayout, "CharSet", MemberKind.Field, types.CharSet); StructLayoutSize = new PredefinedMember <FieldSpec> (module, atypes.StructLayout, MemberFilter.Field("Size", btypes.Int)); TypeGetTypeFromHandle = new PredefinedMember <MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle); }
public override bool Resolve(BlockContext bc) { if (!base.Resolve(bc)) { return(false); } Arguments args = new Arguments(0); type = expr.Type; // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(type, loc); expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(awaiter_type, loc); expr = ama; // // Predefined: bool IsCompleted { get; } // is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool), BindingRestriction.InstanceOnly) as PropertySpec; if (is_completed == null || !is_completed.HasGet) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } // // Predefined: OnCompleted (Action) // if (bc.Module.PredefinedTypes.Action.Define()) { on_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Method("OnCompleted", 0, ParametersCompiled.CreateFullyResolved(bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void), BindingRestriction.InstanceOnly) as MethodSpec; if (on_completed == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } } // // Predefined: GetResult () // // The method return type is also result type of await expression // get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.InstanceOnly) as MethodSpec; if (get_result == null) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } result_type = get_result.ReturnType; return(true); }
/// <summary> /// This function tells whether one of our base classes implements /// the given method (which turns out, it is valid to have an interface /// implementation in a base /// </summary> bool BaseImplements(TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method) { base_method = null; bool base_can_implement = true; TypeSpec lookup_type; // // Special handling for properties/indexers which cannot have accessors // implementing an interface found in different types (e.g. current and base) // if (mi.IsAccessor && container.Interfaces != null) { bool new_implementation = false; foreach (var iface in container.Interfaces) { if (TypeSpecComparer.IsEqual(iface, iface_type)) { new_implementation = true; break; } } if (new_implementation) { MemberFilter filter; if (mi.Parameters.Count > 1) { var indexer_params = mi.Name [0] == 'g' ? mi.Parameters : IndexerSpec.CreateParametersFromSetter(mi, mi.Parameters.Count - 1); filter = new MemberFilter(MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, indexer_params, null); } else { var pname = mi.Name.Substring(4); filter = MemberFilter.Property(pname, null); } var prop = MemberCache.FindMember(container.CurrentType, filter, BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly); if (prop != null && (prop.Modifiers & Modifiers.NEW) != 0) { base_can_implement = false; } } } if (base_can_implement) { lookup_type = container.BaseType; if (lookup_type.ImplementsInterface(iface_type, false)) { return(true); } } else { lookup_type = container.CurrentType; } // // Setup filter with no return type to give better error message // about mismatch at return type when the check bellow rejects them // var parameters = mi.Parameters; MethodSpec close_match = null; while (true) { var candidates = MemberCache.FindMembers(lookup_type, mi.Name, !base_can_implement); if (candidates == null) { base_method = close_match; return(false); } MethodSpec similar_candidate = null; foreach (var candidate in candidates) { if (candidate.Kind != MemberKind.Method) { continue; } if (candidate.Arity != mi.Arity) { continue; } var candidate_param = ((MethodSpec)candidate).Parameters; if (!TypeSpecComparer.Override.IsEqual(parameters.Types, candidate_param.Types)) { continue; } bool modifiers_match = true; for (int i = 0; i < parameters.Count; ++i) { // // First check exact ref/out match // if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) { continue; } modifiers_match = false; // // Different in ref/out only // if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) { if (similar_candidate == null) { if (!candidate.IsPublic) { break; } if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, ((MethodSpec)candidate).ReturnType)) { break; } // It's used for ref/out ambiguity overload check similar_candidate = (MethodSpec)candidate; } continue; } similar_candidate = null; break; } if (!modifiers_match) { continue; } // // From this point the candidate is used for detailed error reporting // because it's very close match to what we are looking for // var m = (MethodSpec)candidate; if (!m.IsPublic) { if (close_match == null) { close_match = m; } continue; } if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, m.ReturnType)) { if (close_match == null) { close_match = m; } continue; } base_method = m; if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints(container, m, mi)) { return(true); } } if (base_method != null) { if (similar_candidate != null) { Report.SymbolRelatedToPreviousError(similar_candidate); Report.SymbolRelatedToPreviousError(mi); Report.SymbolRelatedToPreviousError(container); Report.Warning(1956, 1, ((MemberCore)base_method.MemberDefinition).Location, "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'", mi.GetSignatureForError(), base_method.GetSignatureForError(), similar_candidate.GetSignatureForError(), container.GetSignatureForError()); } break; } if (!base_can_implement) { return(false); } lookup_type = candidates[0].DeclaringType.BaseType; if (lookup_type == null) { base_method = close_match; return(false); } } if (!base_method.IsVirtual) { #if STATIC var base_builder = base_method.GetMetaInfo() as MethodBuilder; if (base_builder != null) { // // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can // be done for all methods from compiled assembly // base_builder.__SetAttributes(base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); return(true); } #endif DefineProxy(iface_type, base_method, mi); } return(true); }
protected override bool DoDefineMembers() { TypeSpec bt; bool has_task_return_type = false; var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; MethodSpec set_statemachine; if (return_type.IsCustomTaskType()) { // // TODO: Would be nice to cache all this on per-type basis // var btypes = Compiler.BuiltinTypes; bt = return_type.MemberDefinition.GetAsyncMethodBuilder(); TypeSpec bt_inflated; if (return_type.IsGeneric) { bt_inflated = bt.MakeGenericType(Module, bt.MemberDefinition.TypeParameters); } else { bt_inflated = bt; } var set_result_sign = MemberFilter.Method("SetResult", 0, ParametersCompiled.CreateFullyResolved(bt.MemberDefinition.TypeParameters), btypes.Void); set_result = new PredefinedMember <MethodSpec> (Module, bt, set_result_sign).Resolve(Location); var set_exception_sign = MemberFilter.Method("SetException", 0, ParametersCompiled.CreateFullyResolved(btypes.Exception), btypes.Void); set_exception = new PredefinedMember <MethodSpec> (Module, bt, set_exception_sign).Resolve(Location); var builder_factory_sign = MemberFilter.Method("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, bt_inflated); builder_factory = new PredefinedMember <MethodSpec> (Module, bt, builder_factory_sign).Resolve(Location); if (builder_factory?.IsStatic == false) { throw new NotImplementedException("report better error message"); } var builder_start_sign = MemberFilter.Method("Start", 1, new ParametersImported( new [] { new ParameterData(null, Parameter.Modifier.REF), }, new [] { new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), }, false), btypes.Void); builder_start = new PredefinedMember <MethodSpec> (Module, bt, builder_start_sign).Resolve(Location); if (!istate_machine.Define()) { return(false); } var set_statemachine_sign = MemberFilter.Method("SetStateMachine", 0, ParametersCompiled.CreateFullyResolved(istate_machine.TypeSpec), btypes.Void); set_statemachine = new PredefinedMember <MethodSpec> (Module, bt, set_statemachine_sign).Resolve(Location);; var task_sign = MemberFilter.Property("Task", return_type.MemberDefinition as TypeSpec); task = new PredefinedMember <PropertySpec> (Module, bt, task_sign).Resolve(Location); if (set_result == null || set_exception == null || builder_factory == null || builder_start == null || set_statemachine == null || task == null || !Module.PredefinedTypes.INotifyCompletion.Define()) { return(false); } has_task_return_type = return_type.IsGeneric; } else { PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> bs; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; PredefinedMember <MethodSpec> sm; var pred_members = Module.PredefinedMembers; if (return_type.Kind == MemberKind.Void) { builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; bf = pred_members.AsyncVoidMethodBuilderCreate; bs = pred_members.AsyncVoidMethodBuilderStart; sr = pred_members.AsyncVoidMethodBuilderSetResult; se = pred_members.AsyncVoidMethodBuilderSetException; sm = pred_members.AsyncVoidMethodBuilderSetStateMachine; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; bs = pred_members.AsyncTaskMethodBuilderStart; sr = pred_members.AsyncTaskMethodBuilderSetResult; se = pred_members.AsyncTaskMethodBuilderSetException; sm = pred_members.AsyncTaskMethodBuilderSetStateMachine; task = pred_members.AsyncTaskMethodBuilderTask.Get(); } else { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; bf = pred_members.AsyncTaskMethodBuilderGenericCreate; bs = pred_members.AsyncTaskMethodBuilderGenericStart; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; se = pred_members.AsyncTaskMethodBuilderGenericSetException; sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine; task = pred_members.AsyncTaskMethodBuilderGenericTask.Get(); has_task_return_type = true; } set_result = sr.Get(); set_exception = se.Get(); builder_factory = bf.Get(); builder_start = bs.Get(); set_statemachine = sm.Get(); if (!builder_type.Define() || !istate_machine.Define() || set_result == null || builder_factory == null || set_exception == null || set_statemachine == null || builder_start == null || !Module.PredefinedTypes.INotifyCompletion.Define()) { Report.Error(1993, Location, "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); return(base.DoDefineMembers()); } bt = builder_type.TypeSpec; } // // Inflate generic Task types // if (has_task_return_type) { var task_return_type = return_type.TypeArguments; if (mutator != null) { task_return_type = mutator.Mutate(task_return_type); } bt = bt.MakeGenericType(Module, task_return_type); set_result = MemberCache.GetMember(bt, set_result); set_exception = MemberCache.GetMember(bt, set_exception); set_statemachine = MemberCache.GetMember(bt, set_statemachine); if (task != null) { task = MemberCache.GetMember(bt, task); } } builder = AddCompilerGeneratedField("$builder", new TypeExpression(bt, Location)); Field rfield; if (has_task_return_type && HasAwaitInsideFinally) { // // Special case async block with return value from finally clause. In such case // we rewrite all return expresison stores to stfld to $return. Instead of treating // returns outside of finally and inside of finally differently. // rfield = AddCompilerGeneratedField("$return", new TypeExpression(bt.TypeArguments [0], Location)); } else { rfield = null; } var set_state_machine = new Method(this, new TypeExpression(Compiler.BuiltinTypes.Void, Location), Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC, new MemberName("SetStateMachine"), ParametersCompiled.CreateFullyResolved( new Parameter(new TypeExpression(istate_machine.TypeSpec, Location), "stateMachine", Parameter.Modifier.NONE, null, Location), istate_machine.TypeSpec), null); ToplevelBlock block = new ToplevelBlock(Compiler, set_state_machine.ParameterInfo, Location); block.IsCompilerGenerated = true; set_state_machine.Block = block; Members.Add(set_state_machine); if (!base.DoDefineMembers()) { return(false); } // // Fabricates SetStateMachine method // // public void SetStateMachine (IAsyncStateMachine stateMachine) // { // $builder.SetStateMachine (stateMachine); // } // var mg = MethodGroupExpr.CreatePredefined(set_statemachine, bt, Location); mg.InstanceExpression = new FieldExpr(builder, Location); var param_reference = block.GetParameterReference(0, Location); param_reference.Type = istate_machine.TypeSpec; param_reference.eclass = ExprClass.Variable; var args = new Arguments(1); args.Add(new Argument(param_reference)); set_state_machine.Block.AddStatement(new StatementExpression(new Invocation(mg, args))); if (has_task_return_type) { if (rfield != null) { HoistedReturnValue = new FieldExpr(rfield, Location) { InstanceExpression = new CompilerGeneratedThis(CurrentType, Location.Null) }; } else { HoistedReturnValue = TemporaryVariableReference.Create(bt.TypeArguments [0], StateMachineMethod.Block, Location); } } return(true); }
public static PropertySpec GetPredefinedProperty(TypeSpec t, string name, Location loc, TypeSpec type) { return(GetPredefinedMember(t, MemberFilter.Property(name, type), false, loc) as PropertySpec); }