Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
            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);
            }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }