Example #1
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)
            {
                HoistedReturnValue = TemporaryVariableReference.Create(bt.TypeArguments [0], StateMachineMethod.Block, Location);
            }

            return(true);
        }
Example #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);
            }
Example #3
0
		protected override bool DoDefineMembers ()
		{
			if (!base.DoDefineMembers ())
				return false;

			Location loc = Location;

			var equals_parameters = ParametersCompiled.CreateFullyResolved (
				new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object);

			Method equals = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc),
				Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc),
				equals_parameters, null);

			equals_parameters[0].Resolve (equals, 0);

			Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc),
				Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
				ParametersCompiled.EmptyReadOnlyParameters, null);

			ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc);

			TypeExpr current_type;
			if (CurrentTypeParameters != null) {
				var targs = new TypeArguments ();
				for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
					targs.Add (new TypeParameterExpr (CurrentTypeParameters[i], Location));
				}

				current_type = new GenericTypeExpr (Definition, targs, loc);
			} else {
				current_type = new TypeExpression (Definition, loc);
			}

			var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc);
			equals_block.AddStatement (new BlockVariable (new TypeExpression (li_other.Type, loc), li_other));
			var other_variable = new LocalVariableReference (li_other, loc);

			MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
				new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc);

			Expression rs_equals = null;
			Expression string_concat = new StringConstant (Compiler.BuiltinTypes, "{", loc);
			Expression rs_hashcode = new IntConstant (Compiler.BuiltinTypes, -2128831035, loc);
			for (int i = 0; i < parameters.Count; ++i) {
				var p = parameters [i];
				var f = (Field) Members [i * 2];

				MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
					system_collections_generic, "EqualityComparer",
						new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc),
						"Default", loc);

				Arguments arguments_equal = new Arguments (2);
				arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
				arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name)));

				Expression field_equal = new Invocation (new MemberAccess (equality_comparer,
					"Equals", loc), arguments_equal);

				Arguments arguments_hashcode = new Arguments (1);
				arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
				Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
					"GetHashCode", loc), arguments_hashcode);

				IntConstant FNV_prime = new IntConstant (Compiler.BuiltinTypes, 16777619, loc);				
				rs_hashcode = new Binary (Binary.Operator.Multiply,
					new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode),
					FNV_prime);

				Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality,
					new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc))),
					new Invocation (new MemberAccess (
						new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
					new StringConstant (Compiler.BuiltinTypes, string.Empty, loc), loc);

				if (rs_equals == null) {
					rs_equals = field_equal;
					string_concat = new Binary (Binary.Operator.Addition,
						string_concat,
						new Binary (Binary.Operator.Addition,
							new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc),
							field_to_string));
					continue;
				}

				//
				// Implementation of ToString () body using string concatenation
				//				
				string_concat = new Binary (Binary.Operator.Addition,
					new Binary (Binary.Operator.Addition,
						string_concat,
						new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc)),
					field_to_string);

				rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal);
			}

			string_concat = new Binary (Binary.Operator.Addition,
				string_concat,
				new StringConstant (Compiler.BuiltinTypes, " }", loc));

			//
			// Equals (object obj) override
			//		
			var other_variable_assign = new TemporaryVariableReference (li_other, loc);
			equals_block.AddStatement (new StatementExpression (
				new SimpleAssign (other_variable_assign,
					new As (equals_block.GetParameterReference (0, loc),
						current_type, loc), loc)));

			Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc));
			if (rs_equals != null)
				equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals);
			equals_block.AddStatement (new Return (equals_test, loc));

			equals.Block = equals_block;
			equals.Define ();
			Members.Add (equals);

			//
			// GetHashCode () override
			//
			Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc),
				Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN,
				new MemberName ("GetHashCode", loc),
				ParametersCompiled.EmptyReadOnlyParameters, null);

			//
			// Modified FNV with good avalanche behavior and uniform
			// distribution with larger hash sizes.
			//
			// const int FNV_prime = 16777619;
			// int hash = (int) 2166136261;
			// foreach (int d in data)
			//     hash = (hash ^ d) * FNV_prime;
			// hash += hash << 13;
			// hash ^= hash >> 7;
			// hash += hash << 3;
			// hash ^= hash >> 17;
			// hash += hash << 5;

			ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc);
			Block hashcode_block = new Block (hashcode_top, loc, loc);
			hashcode_top.AddStatement (new Unchecked (hashcode_block, loc));

			var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc);
			hashcode_block.AddStatement (new BlockVariable (new TypeExpression (li_hash.Type, loc), li_hash));
			LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc);
			hashcode_block.AddStatement (new StatementExpression (
				new SimpleAssign (hash_variable_assign, rs_hashcode)));

			var hash_variable = new LocalVariableReference (li_hash, loc);
			hashcode_block.AddStatement (new StatementExpression (
				new CompoundAssign (Binary.Operator.Addition, hash_variable,
					new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc)))));
			hashcode_block.AddStatement (new StatementExpression (
				new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
					new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc)))));
			hashcode_block.AddStatement (new StatementExpression (
				new CompoundAssign (Binary.Operator.Addition, hash_variable,
					new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc)))));
			hashcode_block.AddStatement (new StatementExpression (
				new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
					new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc)))));
			hashcode_block.AddStatement (new StatementExpression (
				new CompoundAssign (Binary.Operator.Addition, hash_variable,
					new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc)))));

			hashcode_block.AddStatement (new Return (hash_variable, loc));
			hashcode.Block = hashcode_top;
			hashcode.Define ();
			Members.Add (hashcode);

			//
			// ToString () override
			//

			ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc);
			tostring_block.AddStatement (new Return (string_concat, loc));
			tostring.Block = tostring_block;
			tostring.Define ();
			Members.Add (tostring);

			return true;
		}
Example #4
0
        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);
        }
Example #5
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;
			}