Mono.CSharp.Method.Define C# (CSharp) Method

Define() public method

public Define ( ) : bool
return bool
        public override bool Define()
        {
            if (type_expr.Type == TypeManager.void_type && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
                Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
            }

            if (!base.Define ())
                return false;

            if (partialMethodImplementation != null && IsPartialDefinition)
                MethodBuilder = partialMethodImplementation.MethodBuilder;

            if (Compiler.Settings.StdLib && TypeManager.IsSpecialType (ReturnType)) {
                Error1599 (Location, ReturnType, Report);
                return false;
            }

            if (CurrentTypeParameters == null) {
                if (base_method != null) {
                    if (parameters.Count == 1 && ParameterTypes[0] == TypeManager.object_type && Name == "Equals")
                        Parent.PartialContainer.Mark_HasEquals ();
                    else if (parameters.IsEmpty && Name == "GetHashCode")
                        Parent.PartialContainer.Mark_HasGetHashCode ();
                }

            } else {
                DefineTypeParameters ();
            }

            if (block != null && block.IsIterator) {
                //
                // Current method is turned into automatically generated
                // wrapper which creates an instance of iterator
                //
                Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
                ModFlags |= Modifiers.DEBUGGER_HIDDEN;
            }

            if ((ModFlags & Modifiers.STATIC) == 0)
                return true;

            if (parameters.HasExtensionMethodType) {
                if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) {
                    if (!Parent.IsTopLevel)
                        Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
                            GetSignatureForError ());

                    PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
                    if (!pa.IsDefined) {
                        Report.Error (1110, Location,
                            "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
                            GetSignatureForError ());
                    }

                    ModFlags |= Modifiers.METHOD_EXTENSION;
                    Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
                    Spec.DeclaringType.SetExtensionMethodContainer ();
                    Parent.Module.HasExtensionMethod = true;
                } else {
                    Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
                        GetSignatureForError ());
                }
            }

            //
            // This is used to track the Entry Point,
            //
            var settings = Compiler.Settings;
            if (settings.NeedsEntryPoint && Name == "Main" && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) {
                if (IsEntryPoint ()) {
                    if (Parent.DeclaringAssembly.EntryPoint == null) {
                        if (Parent.IsGeneric || MemberName.IsGeneric) {
                            Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
                                GetSignatureForError ());
                        } else {
                            SetIsUsed ();
                            Parent.DeclaringAssembly.EntryPoint = this;
                        }
                    } else {
                        Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
                        Error_DuplicateEntryPoint (this);
                    }
                } else {
                    Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
                        GetSignatureForError ());
                }
            }

            return true;
        }

Usage Example

Example #1
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),
				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;
		}
All Usage Examples Of Mono.CSharp.Method::Define