예제 #1
0
파일: async.cs 프로젝트: xiaotie/NRefactory
        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);
        }
예제 #2
0
파일: anonymous.cs 프로젝트: rabink/mono
		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),
				Mono.CSharp.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 BlockVariableDeclaration (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),
				Mono.CSharp.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 BlockVariableDeclaration (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;
		}
예제 #3
0
		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));
		}
예제 #4
0
파일: statement.cs 프로젝트: alisci01/mono
			public override bool Resolve (BlockContext ec)
			{
				bool is_dynamic = expr.Type == InternalType.Dynamic;

				if (is_dynamic) {
					expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);
				} else if (TypeManager.IsNullableType (expr.Type)) {
					expr = new Nullable.UnwrapCall (expr).Resolve (ec);
				}

				var get_enumerator_mg = ResolveGetEnumerator (ec);
				if (get_enumerator_mg == null) {
					return false;
				}

				var get_enumerator = get_enumerator_mg.BestCandidate;
				enumerator_variable = TemporaryVariableReference.Create (get_enumerator.ReturnType, variable.Block, loc);
				enumerator_variable.Resolve (ec);

				// Prepare bool MoveNext ()
				var move_next_mg = ResolveMoveNext (ec, get_enumerator);
				if (move_next_mg == null) {
					return false;
				}

				move_next_mg.InstanceExpression = enumerator_variable;

				// Prepare ~T~ Current { get; }
				var current_prop = ResolveCurrent (ec, get_enumerator);
				if (current_prop == null) {
					return false;
				}

				var current_pe = new PropertyExpr (current_prop, loc) { InstanceExpression = enumerator_variable }.Resolve (ec);
				if (current_pe == null)
					return false;

				VarExpr ve = var_type as VarExpr;
				if (ve != null) {
					if (is_dynamic) {
						// Source type is dynamic, set element type to dynamic too
						var_type = new TypeExpression (InternalType.Dynamic, var_type.Location);
					} else {
						// Infer implicitly typed local variable from foreach enumerable type
						var_type = new TypeExpression (current_pe.Type, var_type.Location);
					}
				} else if (is_dynamic) {
					// Explicit cast of dynamic collection elements has to be done at runtime
					current_pe = EmptyCast.Create (current_pe, InternalType.Dynamic);
				}

				var_type = var_type.ResolveAsTypeTerminal (ec, false);
				if (var_type == null)
					return false;

				variable.Type = var_type.Type;

				var init = new Invocation (get_enumerator_mg, null);

				statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)),
					new Body (var_type.Type, variable, current_pe, statement, loc), loc);

				var enum_type = enumerator_variable.Type;

				//
				// Add Dispose method call when enumerator can be IDisposable
				//
				if (!enum_type.ImplementsInterface (TypeManager.idisposable_type, false)) {
					if (!enum_type.IsSealed && !TypeManager.IsValueType (enum_type)) {
						//
						// Runtime Dispose check
						//
						var vd = new RuntimeDispose (enumerator_variable.LocalInfo, loc);
						vd.Initializer = init;
						statement = new Using (vd, statement, loc);
					} else {
						//
						// No Dispose call needed
						//
						this.init = new SimpleAssign (enumerator_variable, init);
						this.init.Resolve (ec);
					}
				} else {
					//
					// Static Dispose check
					//
					var vd = new Using.VariableDeclaration (enumerator_variable.LocalInfo, loc);
					vd.Initializer = init;
					statement = new Using (vd, statement, loc);
				}

				return statement.Resolve (ec);
			}
예제 #5
0
파일: statement.cs 프로젝트: alisci01/mono
			public override bool Resolve (BlockContext ec)
			{
				Block variables_block = variable.local_info.Block;
				copy = TemporaryVariableReference.Create (for_each.expr.Type, variables_block, loc);
				copy.Resolve (ec);

				int rank = length_exprs.Length;
				Arguments list = new Arguments (rank);
				for (int i = 0; i < rank; i++) {
					var v = TemporaryVariableReference.Create (TypeManager.int32_type, variables_block, loc);
					variables[i] = v;
					counter[i] = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, v, loc));
					counter[i].Resolve (ec);

					if (rank == 1) {
						length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec);
					} else {
						lengths[i] = TemporaryVariableReference.Create (TypeManager.int32_type, variables_block, loc);
						lengths[i].Resolve (ec);

						Arguments args = new Arguments (1);
						args.Add (new Argument (new IntConstant (i, loc)));
						length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec);
					}

					list.Add (new Argument (v));
				}

				access = new ElementAccess (copy, list, loc).Resolve (ec);
				if (access == null)
					return false;

				Expression var_type = for_each.type;
				VarExpr ve = var_type as VarExpr;
				if (ve != null) {
					// Infer implicitly typed local variable from foreach array type
					var_type = new TypeExpression (access.Type, ve.Location);
				}

				var_type = var_type.ResolveAsTypeTerminal (ec, false);
				if (var_type == null)
					return false;

				conv = Convert.ExplicitConversion (ec, access, var_type.Type, loc);
				if (conv == null)
					return false;

				bool ok = true;

				ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
				ec.CurrentBranching.CreateSibling ();

				variable.local_info.Type = conv.Type;
				variable.Resolve (ec);

				ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
				if (!statement.Resolve (ec))
					ok = false;
				ec.EndFlowBranching ();

				// There's no direct control flow from the end of the embedded statement to the end of the loop
				ec.CurrentBranching.CurrentUsageVector.Goto ();

				ec.EndFlowBranching ();

				return ok;
			}
예제 #6
0
파일: statement.cs 프로젝트: alisci01/mono
		public override bool Resolve (BlockContext ec)
		{
			expr = expr.Resolve (ec);
			if (expr == null)
				return false;

			if (!TypeManager.IsReferenceType (expr.Type)){
				ec.Report.Error (185, loc,
					      "`{0}' is not a reference type as required by the lock statement",
					      TypeManager.CSharpName (expr.Type));
				return false;
			}

			ec.StartFlowBranching (this);
			bool ok = Statement.Resolve (ec);
			ec.EndFlowBranching ();

			ok &= base.Resolve (ec);

			temp = TemporaryVariableReference.Create (expr.Type, ec.CurrentBlock.Parent, loc);
			temp.Resolve (ec);

			if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
				TypeSpec monitor_type = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Monitor", MemberKind.Class, true);
				TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod (
					monitor_type, "Enter", loc, TypeManager.object_type);
				TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod (
					monitor_type, "Exit", loc, TypeManager.object_type);
			}
			
			return ok;
		}
예제 #7
0
		public override bool Resolve (BlockContext ec)
		{
			expr = expr.Resolve (ec);
			if (expr == null)
				return false;

			if (!TypeManager.IsReferenceType (expr.Type)){
				ec.Report.Error (185, loc,
					"`{0}' is not a reference type as required by the lock statement",
					expr.Type.GetSignatureForError ());
			}

			if (expr.Type.IsGenericParameter) {
				expr = Convert.ImplicitTypeParameterConversion (expr, TypeManager.object_type);
			}

			VariableReference lv = expr as VariableReference;
			bool locked;
			if (lv != null) {
				locked = lv.IsLockedByStatement;
				lv.IsLockedByStatement = true;
			} else {
				lv = null;
				locked = false;
			}

			ec.StartFlowBranching (this);
			Statement.Resolve (ec);
			ec.EndFlowBranching ();

			if (lv != null) {
				lv.IsLockedByStatement = locked;
			}

			base.Resolve (ec);

			//
			// Have to keep original lock value around to unlock same location
			// in the case the original has changed or is null
			//
			expr_copy = TemporaryVariableReference.Create (TypeManager.object_type, ec.CurrentBlock.Parent, loc);
			expr_copy.Resolve (ec);

			//
			// Ensure Monitor methods are available
			//
			if (ResolvePredefinedMethods (ec) > 1) {
				lock_taken = TemporaryVariableReference.Create (TypeManager.bool_type, ec.CurrentBlock.Parent, loc);
				lock_taken.Resolve (ec);
			}

			return true;
		}