public ExpressionStatement CreateExpressionTreeVariable(BlockContext ec) { if ((modFlags & Modifier.RefOutMask) != 0) { ec.Report.Error(1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); } expr_tree_variable = TemporaryVariableReference.Create(ResolveParameterExpressionType(ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); expr_tree_variable = (TemporaryVariableReference)expr_tree_variable.Resolve(ec); Arguments arguments = new Arguments(2); arguments.Add(new Argument(new TypeOf(parameter_type, Location))); arguments.Add(new Argument(new StringConstant(ec.BuiltinTypes, Name, Location))); return(new SimpleAssign(ExpressionTreeVariableReference(), Expression.CreateExpressionFactoryCall(ec, "Parameter", null, arguments, Location))); }
protected override bool DoDefineMembers() { PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> bs; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; PredefinedMember <MethodSpec> sm; bool has_task_return_type = false; 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(); var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; var 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()); } var 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)); 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) { HoistedReturnValue = TemporaryVariableReference.Create(bt.TypeArguments [0], StateMachineMethod.Block, Location); } 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); }