void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec); return; } current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); Label[] labels = new Label[1 + resume_points.Count]; labels[0] = ec.DefineLabel(); bool need_skip_finally = false; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; need_skip_finally |= s is ExceptionStatement; labels[i + 1] = s.PrepareForEmit(ec); } if (need_skip_finally) { skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool); ec.EmitInt(0); ec.Emit(OpCodes.Stloc, skip_finally); } var async_init = this as AsyncInitializer; if (async_init != null) { ec.BeginExceptionBlock(); } ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.MarkLabel(labels[0]); iterator_body_end = ec.DefineLabel(); if (ec.EmitAccurateDebugInfo && ec.Mark(Block.Original.StartLocation)) { ec.Emit(OpCodes.Nop); } block.Emit(ec); ec.MarkLabel(iterator_body_end); if (async_init != null) { var catch_value = LocalVariable.CreateCompilerGenerated(ec.Module.Compiler.BuiltinTypes.Exception, block, Location); ec.BeginCatchBlock(catch_value.Type); catch_value.EmitAssign(ec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); ((AsyncTaskStorey)async_init.Storey).EmitSetException(ec, new LocalVariableReference(catch_value, Location)); ec.Emit(OpCodes.Leave, move_next_ok); ec.EndExceptionBlock(); } ec.Mark(Block.Original.EndLocation); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); EmitMoveNextEpilogue(ec); ec.MarkLabel(move_next_error); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(0); ec.Emit(OpCodes.Ret); } ec.MarkLabel(move_next_ok); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(1); ec.Emit(OpCodes.Ret); } }
Method GenerateNumberMatcher() { var loc = Location; var parameters = ParametersCompiled.CreateFullyResolved( new [] { new Parameter(new TypeExpression(Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), new Parameter(new TypeExpression(Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc), new Parameter(new TypeExpression(Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc), }, new [] { Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Bool }); var m = new Method(this, new TypeExpression(Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName("NumberMatcher", loc), parameters, null); parameters [0].Resolve(m, 0); parameters [1].Resolve(m, 1); parameters [2].Resolve(m, 2); ToplevelBlock top_block = new ToplevelBlock(Compiler, parameters, loc); m.Block = top_block; // // if (enumType) // return Equals (obj, value); // var equals_args = new Arguments(2); equals_args.Add(new Argument(top_block.GetParameterReference(0, loc))); equals_args.Add(new Argument(top_block.GetParameterReference(1, loc))); var if_type = new If( top_block.GetParameterReference(2, loc), new Return(new Invocation(new SimpleName("Equals", loc), equals_args), loc), loc); top_block.AddStatement(if_type); // // if (obj is Enum || obj == null) // return false; // var if_enum = new If( new Binary(Binary.Operator.LogicalOr, new Is(top_block.GetParameterReference(0, loc), new TypeExpression(Compiler.BuiltinTypes.Enum, loc), loc), new Binary(Binary.Operator.Equality, top_block.GetParameterReference(0, loc), new NullLiteral(loc))), new Return(new BoolLiteral(Compiler.BuiltinTypes, false, loc), loc), loc); top_block.AddStatement(if_enum); var system_convert = new MemberAccess(new QualifiedAliasMember("global", "System", loc), "Convert", loc); var expl_block = new ExplicitBlock(top_block, loc, loc); // // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value)); // var lv_converted = LocalVariable.CreateCompilerGenerated(Compiler.BuiltinTypes.Object, top_block, loc); var arguments_gettypecode = new Arguments(1); arguments_gettypecode.Add(new Argument(top_block.GetParameterReference(1, loc))); var gettypecode = new Invocation(new MemberAccess(system_convert, "GetTypeCode", loc), arguments_gettypecode); var arguments_changetype = new Arguments(1); arguments_changetype.Add(new Argument(top_block.GetParameterReference(0, loc))); arguments_changetype.Add(new Argument(gettypecode)); var changetype = new Invocation(new MemberAccess(system_convert, "ChangeType", loc), arguments_changetype); expl_block.AddStatement(new StatementExpression(new SimpleAssign(new LocalVariableReference(lv_converted, loc), changetype, loc))); // // return converted.Equals (value) // var equals_arguments = new Arguments(1); equals_arguments.Add(new Argument(top_block.GetParameterReference(1, loc))); var equals_invocation = new Invocation(new MemberAccess(new LocalVariableReference(lv_converted, loc), "Equals"), equals_arguments); expl_block.AddStatement(new Return(equals_invocation, loc)); var catch_block = new ExplicitBlock(top_block, loc, loc); catch_block.AddStatement(new Return(new BoolLiteral(Compiler.BuiltinTypes, false, loc), loc)); top_block.AddStatement(new TryCatch(expl_block, new List <Catch> () { new Catch(catch_block, loc) }, loc, false)); m.Define(); m.PrepareEmit(); AddMember(m); return(m); }
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) { hoisted_return = LocalVariable.CreateCompilerGenerated(bt.TypeArguments[0], StateMachineMethod.Block, Location); } return(true); }
protected override bool DoDefineMembers() { var action = Module.PredefinedTypes.Action.Resolve(); if (action != null) { continuation = AddCompilerGeneratedField("$continuation", new TypeExpression(action, Location), true); continuation.ModFlags |= Modifiers.READONLY; } PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; 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; sr = pred_members.AsyncVoidMethodBuilderSetResult; se = pred_members.AsyncVoidMethodBuilderSetException; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; sr = pred_members.AsyncTaskMethodBuilderSetResult; se = pred_members.AsyncTaskMethodBuilderSetException; 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.Get(); has_task_return_type = true; } 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 // 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); builder_factory = MemberCache.GetMember <MethodSpec> (bt, builder_factory); set_result = MemberCache.GetMember <MethodSpec> (bt, set_result); set_exception = MemberCache.GetMember <MethodSpec> (bt, set_exception); if (task != null) { task = MemberCache.GetMember <PropertySpec> (bt, task); } } builder = AddCompilerGeneratedField("$builder", new TypeExpression(bt, Location)); builder.ModFlags |= Modifiers.READONLY; if (!base.DoDefineMembers()) { return(false); } MethodGroupExpr mg; var block = instance_constructors[0].Block; // // Initialize continuation with state machine method // if (continuation != null) { var args = new Arguments(1); mg = MethodGroupExpr.CreatePredefined(StateMachineMethod.Spec, spec, Location); args.Add(new Argument(mg)); block.AddStatement( new StatementExpression(new SimpleAssign( new FieldExpr(continuation, Location), new NewDelegate(action, args, Location), Location ))); } mg = MethodGroupExpr.CreatePredefined(builder_factory, bt, Location); block.AddStatement( new StatementExpression(new SimpleAssign( new FieldExpr(builder, Location), new Invocation(mg, new Arguments(0)), Location))); if (has_task_return_type) { hoisted_return = LocalVariable.CreateCompilerGenerated(bt.TypeArguments[0], block, Location); } return(true); }