Define() public method

public Define ( ) : bool
return bool
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;
		}
Example #2
0
		//
		// Creates a proxy base method call inside this container for hoisted base member calls
		//
		public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
		{
			Method proxy_method;

			//
			// One proxy per base method is enough
			//
			if (hoisted_base_call_proxies == null) {
				hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
				proxy_method = null;
			} else {
				hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
			}

			if (proxy_method == null) {
				string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
				var base_parameters = new Parameter[method.Parameters.Count];
				for (int i = 0; i < base_parameters.Length; ++i) {
					var base_param = method.Parameters.FixedParameters[i];
					base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
						base_param.Name, base_param.ModFlags, null, Location);
					base_parameters[i].Resolve (this, i);
				}

				var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
				if (method.Parameters.HasArglist) {
					cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
					cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (Location);
				}

				GenericMethod generic_method;
				MemberName member_name;
				if (method.IsGeneric) {
					//
					// Copy all base generic method type parameters info
					//
					var hoisted_tparams = method.GenericDefinition.TypeParameters;
					var targs = new TypeArguments ();
					var type_params = new TypeParameter[hoisted_tparams.Length];
					for (int i = 0; i < type_params.Length; ++i) {
						var tp = hoisted_tparams[i];
						targs.Add (new TypeParameterName (tp.Name, null, Location));
						type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null);
					}

					member_name = new MemberName (name, targs, Location);
					generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params,
						new TypeExpression (method.ReturnType, Location), cloned_params);
				} else {
					member_name = new MemberName (name);
					generic_method = null;
				}

				// Compiler generated proxy
				proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location),
					Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
					member_name, cloned_params, null);

				var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location);

				var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
				mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);

				// Get all the method parameters and pass them as arguments
				var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
				Statement statement;
				if (method.ReturnType == TypeManager.void_type)
					statement = new StatementExpression (real_base_call);
				else
					statement = new Return (real_base_call, Location);

				block.AddStatement (statement);
				proxy_method.Block = block;

				methods.Add (proxy_method);
				proxy_method.Define ();

				hoisted_base_call_proxies.Add (method, proxy_method);
			}

			return proxy_method.Spec;
		}
Example #3
0
		//
		// Creates a proxy base method call inside this container for hoisted base member calls
		//
		public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
		{
			Method proxy_method;

			//
			// One proxy per base method is enough
			//
			if (hoisted_base_call_proxies == null) {
				hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
				proxy_method = null;
			} else {
				hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
			}

			if (proxy_method == null) {
				string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);

				MemberName member_name;
				TypeArguments targs = null;
				TypeSpec return_type = method.ReturnType;
				var local_param_types = method.Parameters.Types;

				if (method.IsGeneric) {
					//
					// Copy all base generic method type parameters info
					//
					var hoisted_tparams = method.GenericDefinition.TypeParameters;
					var tparams = new TypeParameters ();

					targs = new TypeArguments ();
					targs.Arguments = new TypeSpec[hoisted_tparams.Length];
					for (int i = 0; i < hoisted_tparams.Length; ++i) {
						var tp = hoisted_tparams[i];
						var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
						tparams.Add (local_tp);

						targs.Add (new SimpleName (tp.Name, Location));
						targs.Arguments[i] = local_tp.Type;
					}

					member_name = new MemberName (name, tparams, Location);

					//
					// Mutate any method type parameters from original
					// to newly created hoisted version
					//
					var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
					return_type = mutator.Mutate (return_type);
					local_param_types = mutator.Mutate (local_param_types);
				} else {
					member_name = new MemberName (name);
				}

				var base_parameters = new Parameter[method.Parameters.Count];
				for (int i = 0; i < base_parameters.Length; ++i) {
					var base_param = method.Parameters.FixedParameters[i];
					base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
						base_param.Name, base_param.ModFlags, null, Location);
					base_parameters[i].Resolve (this, i);
				}

				var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
				if (method.Parameters.HasArglist) {
					cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
					cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
				}

				// Compiler generated proxy
				proxy_method = new Method (this, new TypeExpression (return_type, Location),
					Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
					member_name, cloned_params, null);

				var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
					IsCompilerGenerated = true
				};

				var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
				mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
				if (targs != null)
					mg.SetTypeArguments (rc, targs);

				// Get all the method parameters and pass them as arguments
				var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
				Statement statement;
				if (method.ReturnType.Kind == MemberKind.Void)
					statement = new StatementExpression (real_base_call);
				else
					statement = new Return (real_base_call, Location);

				block.AddStatement (statement);
				proxy_method.Block = block;

				members.Add (proxy_method);
				proxy_method.Define ();
				proxy_method.PrepareEmit ();

				hoisted_base_call_proxies.Add (method, proxy_method);
			}

			return proxy_method.Spec;
		}
Example #4
0
		protected override bool DoDefineMembers ()
		{
			var builtin_types = Compiler.BuiltinTypes;

			var ctor_parameters = ParametersCompiled.CreateFullyResolved (
				new [] {
					new Parameter (new TypeExpression (builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location),
					new Parameter (new TypeExpression (builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location)
				},
				new [] {
					builtin_types.Object,
					builtin_types.IntPtr
				}
			);

			Constructor = new Constructor (this, Constructor.ConstructorName,
				Modifiers.PUBLIC, null, ctor_parameters, Location);
			Constructor.Define ();

			//
			// Here the various methods like Invoke, BeginInvoke etc are defined
			//
			// First, call the `out of band' special method for
			// defining recursively any types we need:
			//
			var p = parameters;

			if (!p.Resolve (this))
				return false;

			//
			// Invoke method
			//

			// Check accessibility
			foreach (var partype in p.Types) {
				if (!IsAccessibleAs (partype)) {
					Report.SymbolRelatedToPreviousError (partype);
					Report.Error (59, Location,
						"Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
						partype.GetSignatureForError (), GetSignatureForError ());
				}
			}

			var ret_type = ReturnType.ResolveAsType (this);
			if (ret_type == null)
				return false;

			//
			// We don't have to check any others because they are all
			// guaranteed to be accessible - they are standard types.
			//
			if (!IsAccessibleAs (ret_type)) {
				Report.SymbolRelatedToPreviousError (ret_type);
				Report.Error (58, Location,
						  "Inconsistent accessibility: return type `" +
						  ret_type.GetSignatureForError () + "' is less " +
						  "accessible than delegate `" + GetSignatureForError () + "'");
				return false;
			}

			CheckProtectedModifier ();

			if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) {
				Method.Error1599 (Location, ret_type, Report);
				return false;
			}

			VarianceDecl.CheckTypeVariance (ret_type, Variance.Covariant, this);

			var resolved_rt = new TypeExpression (ret_type, Location);
			InvokeBuilder = new Method (this, resolved_rt, MethodModifiers, new MemberName (InvokeMethodName), p, null);
			InvokeBuilder.Define ();

			//
			// Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
			//
			if (!IsCompilerGenerated) {
				DefineAsyncMethods (resolved_rt);
			}

			return true;
		}
Example #5
0
		void DefineAsyncMethods (TypeExpression returnType)
		{
			var iasync_result = Module.PredefinedTypes.IAsyncResult;
			var async_callback = Module.PredefinedTypes.AsyncCallback;

			//
			// It's ok when async types don't exist, the delegate will have Invoke method only
			//
			if (!iasync_result.Define () || !async_callback.Define ())
				return;

			//
			// BeginInvoke
			//
			ParametersCompiled async_parameters;
			if (Parameters.Count == 0) {
				async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
			} else {
				var compiled = new Parameter[Parameters.Count];
				for (int i = 0; i < compiled.Length; ++i) {
					var p = parameters[i];
					compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location),
						p.Name,
						p.ModFlags & Parameter.Modifier.RefOutMask,
						p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
				}

				async_parameters = new ParametersCompiled (compiled);
			}

			async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
				new Parameter[] {
					new Parameter (new TypeExpression (async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location),
					new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location)
				},
				new [] {
					async_callback.TypeSpec,
					Compiler.BuiltinTypes.Object
				}
			);

			BeginInvokeBuilder = new Method (this,
				new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers,
				new MemberName ("BeginInvoke"), async_parameters, null);
			BeginInvokeBuilder.Define ();

			//
			// EndInvoke is a bit more interesting, all the parameters labeled as
			// out or ref have to be duplicated here.
			//

			//
			// Define parameters, and count out/ref parameters
			//
			ParametersCompiled end_parameters;
			int out_params = 0;

			foreach (Parameter p in Parameters.FixedParameters) {
				if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0)
					++out_params;
			}

			if (out_params > 0) {
				Parameter[] end_params = new Parameter[out_params];

				int param = 0;
				for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
					Parameter p = parameters [i];
					if ((p.ModFlags & Parameter.Modifier.RefOutMask) == 0)
						continue;

					end_params [param++] = new Parameter (new TypeExpression (p.Type, Location),
						p.Name,
						p.ModFlags & Parameter.Modifier.RefOutMask,
						p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location);
				}

				end_parameters = new ParametersCompiled (end_params);
			} else {
				end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
			}

			end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
				new Parameter (
					new TypeExpression (iasync_result.TypeSpec, Location),
					"result", Parameter.Modifier.NONE, null, Location),
				iasync_result.TypeSpec);

			//
			// Create method, define parameters, register parameters with type system
			//
			EndInvokeBuilder = new Method (this, returnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
			EndInvokeBuilder.Define ();
		}
Example #6
0
		void DefineAsyncMethods (CallingConventions cc)
		{
			//
			// BeginInvoke
			//
			ParametersCompiled async_parameters;
			if (Parameters.Count == 0) {
				async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
			} else {
				var compiled = new Parameter[Parameters.Count];
				for (int i = 0; i < compiled.Length; ++i)
					compiled[i] = new Parameter (new TypeExpression (Parameters.Types[i], Location),
						Parameters.FixedParameters[i].Name,
						Parameters.FixedParameters[i].ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT),
						null, Location);

				async_parameters = new ParametersCompiled (compiled);
			}

			async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
				new Parameter[] {
					new Parameter (new TypeExpression (TypeManager.asynccallback_type, Location), "callback", Parameter.Modifier.NONE, null, Location),
					new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location)
				},
				new [] {
					TypeManager.asynccallback_type,
					TypeManager.object_type
				}
			);

			BeginInvokeBuilder = new Method (this, null,
				new TypeExpression (TypeManager.iasyncresult_type, Location), MethodModifiers,
				new MemberName ("BeginInvoke"), async_parameters, null);
			BeginInvokeBuilder.Define ();

			//
			// EndInvoke is a bit more interesting, all the parameters labeled as
			// out or ref have to be duplicated here.
			//

			//
			// Define parameters, and count out/ref parameters
			//
			ParametersCompiled end_parameters;
			int out_params = 0;

			foreach (Parameter p in Parameters.FixedParameters) {
				if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
					++out_params;
			}

			if (out_params > 0) {
				var end_param_types = new TypeSpec [out_params];
				Parameter[] end_params = new Parameter[out_params];

				int param = 0;
				for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
					Parameter p = Parameters [i];
					if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
						continue;

					end_param_types[param] = Parameters.Types[i];
					end_params[param] = p;
					++param;
				}
				end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types);
			} else {
				end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
			}

			end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
				new Parameter (
					new TypeExpression (TypeManager.iasyncresult_type, Location),
					"result", Parameter.Modifier.NONE, null, Location),
				TypeManager.iasyncresult_type);

			//
			// Create method, define parameters, register parameters with type system
			//
			EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
			EndInvokeBuilder.Define ();
		}
Example #7
0
		protected override bool DoDefineMembers ()
		{
			var ctor_parameters = ParametersCompiled.CreateFullyResolved (
				new [] {
					new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location),
					new Parameter (new TypeExpression (TypeManager.intptr_type, Location), "method", Parameter.Modifier.NONE, null, Location)
				},
				new [] {
					TypeManager.object_type,
					TypeManager.intptr_type
				}
			);

			Constructor = new Constructor (this, System.Reflection.ConstructorInfo.ConstructorName,
				Modifiers.PUBLIC, null, ctor_parameters, null, Location);
			Constructor.Define ();

			//
			// Here the various methods like Invoke, BeginInvoke etc are defined
			//
			// First, call the `out of band' special method for
			// defining recursively any types we need:
			//
			var p = Parameters;

			if (!p.Resolve (this))
				return false;

			//
			// Invoke method
			//

			// Check accessibility
			foreach (var partype in p.Types) {
				if (!IsAccessibleAs (partype)) {
					Report.SymbolRelatedToPreviousError (partype);
					Report.Error (59, Location,
						"Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
						TypeManager.CSharpName (partype), GetSignatureForError ());
				}
			}

			ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
			if (ReturnType == null)
				return false;

			var ret_type = ReturnType.Type;

			//
			// We don't have to check any others because they are all
			// guaranteed to be accessible - they are standard types.
			//
			if (!IsAccessibleAs (ret_type)) {
				Report.SymbolRelatedToPreviousError (ret_type);
				Report.Error (58, Location,
						  "Inconsistent accessibility: return type `" +
						  TypeManager.CSharpName (ret_type) + "' is less " +
						  "accessible than delegate `" + GetSignatureForError () + "'");
				return false;
			}

			CheckProtectedModifier ();

			if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) {
				Method.Error1599 (Location, ret_type, Report);
				return false;
			}

			TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);

			InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null);
			InvokeBuilder.Define ();

			//
			// Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
			//
			if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) {
				DefineAsyncMethods (Parameters.CallingConvention);
			}

			return true;
		}
Example #8
0
		public override bool Define (TypeContainer parent)
		{
			int length = 1;
			MethodName = "op_" + OperatorType;
			
			if (SecondArgType != null)
				length = 2;
			
			Parameter [] param_list = new Parameter [length];

			if ((ModFlags & RequiredModifiers) != RequiredModifiers){
				Report.Error (
					558, Location, 
					"User defined operators `" +
					Prototype (parent) +
					"' must be declared static and public");
				return false;
			}

			param_list[0] = new Parameter (FirstArgType, FirstArgName,
						       Parameter.Modifier.NONE, null);
			if (SecondArgType != null)
				param_list[1] = new Parameter (SecondArgType, SecondArgName,
							       Parameter.Modifier.NONE, null);
			
			OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
						     new Parameters (param_list, null, Location),
						     OptAttributes, Mono.CSharp.Location.Null);

			OperatorMethod.IsOperator = true;			
			OperatorMethod.Define (parent);

			if (OperatorMethod.MethodBuilder == null)
				return false;
			
			OperatorMethodBuilder = OperatorMethod.MethodBuilder;

			Type [] param_types = OperatorMethod.ParameterTypes;
			Type declaring_type = OperatorMethodBuilder.DeclaringType;
			Type return_type = OperatorMethod.GetReturnType ();
			Type first_arg_type = param_types [0];

			// Rules for conversion operators
			
			if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
				if (first_arg_type == return_type && first_arg_type == declaring_type){
					Report.Error (
						555, Location,
						"User-defined conversion cannot take an object of the " +
						"enclosing type and convert to an object of the enclosing" +
						" type");
					return false;
				}
				
				if (first_arg_type != declaring_type && return_type != declaring_type){
					Report.Error (
						556, Location, 
						"User-defined conversion must convert to or from the " +
						"enclosing type");
					return false;
				}
				
				if (first_arg_type == TypeManager.object_type ||
				    return_type == TypeManager.object_type){
					Report.Error (
						-8, Location,
						"User-defined conversion cannot convert to or from " +
						"object type");
					return false;
				}

				if (first_arg_type.IsInterface || return_type.IsInterface){
					Report.Error (
						552, Location,
						"User-defined conversion cannot convert to or from an " +
						"interface type");
					return false;
				}
				
				if (first_arg_type.IsSubclassOf (return_type) ||
				    return_type.IsSubclassOf (first_arg_type)){
					Report.Error (
						-10, Location,
						"User-defined conversion cannot convert between types " +
						"that derive from each other");
					return false;
				}
			} else if (SecondArgType == null) {
				// Checks for Unary operators
				
				if (first_arg_type != declaring_type){
					Report.Error (
						562, Location,
						"The parameter of a unary operator must be the " +
						"containing type");
					return false;
				}
				
				if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
					if (return_type != declaring_type){
						Report.Error (
							559, Location,
							"The parameter and return type for ++ and -- " +
							"must be the containing type");
						return false;
					}
					
				}
				
				if (OperatorType == OpType.True || OperatorType == OpType.False) {
					if (return_type != TypeManager.bool_type){
						Report.Error (
							215, Location,
							"The return type of operator True or False " +
							"must be bool");
						return false;
					}
				}
				
			} else {
				// Checks for Binary operators
				
				if (first_arg_type != declaring_type &&
				    param_types [1] != declaring_type){
					Report.Error (
						563, Location,
						"One of the parameters of a binary operator must " +
						"be the containing type");
					return false;
				}
			}

			return true;
		}
Example #9
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;
			}
		void DefineOverrides ()
		{
			Location loc = Location;

			Method equals = new Method (this, null, TypeManager.system_boolean_expr,
				Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc),
				Mono.CSharp.ParametersCompiled.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null);

			Method tostring = new Method (this, null, TypeManager.system_string_expr,
				Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
				Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);

			ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.Parameters, loc);
			TypeExpr current_type;
			if (IsGeneric)
				current_type = new GenericTypeExpr (this, loc);
			else
				current_type = new TypeExpression (TypeBuilder, loc);

			equals_block.AddVariable (current_type, "other", loc);
			LocalVariableReference other_variable = new LocalVariableReference (equals_block, "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 ("{", loc);
			Expression rs_hashcode = new IntConstant (-2128831035, loc);
			for (int i = 0; i < parameters.Count; ++i) {
				AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
				Field f = (Field) Fields [i];

				MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
					system_collections_generic, "EqualityComparer",
						new TypeArguments (new SimpleName (TypeParameters [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 (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 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 (string.Empty, 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 (" " + 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 (", " + 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 (" }", loc));

			//
			// Equals (object obj) override
			//		
			LocalVariableReference other_variable_assign = new LocalVariableReference (equals_block, "other", loc);
			equals_block.AddStatement (new StatementExpression (
				new SimpleAssign (other_variable_assign,
					new As (equals_block.GetParameterReference ("obj", 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 ();
			AddMethod (equals);

			//
			// GetHashCode () override
			//
			Method hashcode = new Method (this, null, TypeManager.system_int32_expr,
				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);
			hashcode_top.AddStatement (new Unchecked (hashcode_block));

			hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc);
			LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc);
			LocalVariableReference hash_variable_assign = new LocalVariableReference (hashcode_block, "hash", loc);
			hashcode_block.AddStatement (new StatementExpression (
				new SimpleAssign (hash_variable_assign, rs_hashcode)));

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

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

			//
			// ToString () override
			//

			ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc);
			tostring_block.AddStatement (new Return (string_concat, loc));
			tostring.Block = tostring_block;
			tostring.Define ();
			AddMethod (tostring);
		}
Example #11
0
        void DefineAsyncMethods(CallingConventions cc, TypeExpression returnType)
        {
            var iasync_result  = Module.PredefinedTypes.IAsyncResult;
            var async_callback = Module.PredefinedTypes.AsyncCallback;

            //
            // It's ok when async types don't exist, the delegate will have Invoke method only
            //
            if (!iasync_result.Define() || !async_callback.Define())
            {
                return;
            }

            //
            // BeginInvoke
            //
            ParametersCompiled async_parameters;

            if (Parameters.Count == 0)
            {
                async_parameters = ParametersCompiled.EmptyReadOnlyParameters;
            }
            else
            {
                var compiled = new Parameter[Parameters.Count];
                for (int i = 0; i < compiled.Length; ++i)
                {
                    var p = parameters[i];
                    compiled[i] = new Parameter(new TypeExpression(parameters.Types[i], Location),
                                                p.Name,
                                                p.ModFlags & Parameter.Modifier.RefOutMask,
                                                p.OptAttributes == null ? null : p.OptAttributes.Clone(), Location);
                }

                async_parameters = new ParametersCompiled(compiled);
            }

            async_parameters = ParametersCompiled.MergeGenerated(Compiler, async_parameters, false,
                                                                 new Parameter[] {
                new Parameter(new TypeExpression(async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location),
                new Parameter(new TypeExpression(Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location)
            },
                                                                 new [] {
                async_callback.TypeSpec,
                Compiler.BuiltinTypes.Object
            }
                                                                 );

            BeginInvokeBuilder = new Method(this,
                                            new TypeExpression(iasync_result.TypeSpec, Location), MethodModifiers,
                                            new MemberName("BeginInvoke"), async_parameters, null);
            BeginInvokeBuilder.Define();

            //
            // EndInvoke is a bit more interesting, all the parameters labeled as
            // out or ref have to be duplicated here.
            //

            //
            // Define parameters, and count out/ref parameters
            //
            ParametersCompiled end_parameters;
            int out_params = 0;

            foreach (Parameter p in Parameters.FixedParameters)
            {
                if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0)
                {
                    ++out_params;
                }
            }

            if (out_params > 0)
            {
                Parameter[] end_params = new Parameter[out_params];

                int param = 0;
                for (int i = 0; i < Parameters.FixedParameters.Length; ++i)
                {
                    Parameter p = parameters [i];
                    if ((p.ModFlags & Parameter.Modifier.RefOutMask) == 0)
                    {
                        continue;
                    }

                    end_params [param++] = new Parameter(new TypeExpression(p.Type, Location),
                                                         p.Name,
                                                         p.ModFlags & Parameter.Modifier.RefOutMask,
                                                         p.OptAttributes == null ? null : p.OptAttributes.Clone(), Location);
                }

                end_parameters = new ParametersCompiled(end_params);
            }
            else
            {
                end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
            }

            end_parameters = ParametersCompiled.MergeGenerated(Compiler, end_parameters, false,
                                                               new Parameter(
                                                                   new TypeExpression(iasync_result.TypeSpec, Location),
                                                                   "result", Parameter.Modifier.NONE, null, Location),
                                                               iasync_result.TypeSpec);

            //
            // Create method, define parameters, register parameters with type system
            //
            EndInvokeBuilder = new Method(this, returnType, MethodModifiers, new MemberName("EndInvoke"), end_parameters, null);
            EndInvokeBuilder.Define();
        }
Example #12
0
        protected override bool DoDefineMembers()
        {
            var builtin_types = Compiler.BuiltinTypes;

            var ctor_parameters = ParametersCompiled.CreateFullyResolved(
                new [] {
                new Parameter(new TypeExpression(builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location),
                new Parameter(new TypeExpression(builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location)
            },
                new [] {
                builtin_types.Object,
                builtin_types.IntPtr
            }
                );

            Constructor = new Constructor(this, Constructor.ConstructorName,
                                          Modifiers.PUBLIC, null, ctor_parameters, Location);
            Constructor.Define();

            //
            // Here the various methods like Invoke, BeginInvoke etc are defined
            //
            // First, call the `out of band' special method for
            // defining recursively any types we need:
            //
            var p = parameters;

            if (!p.Resolve(this))
            {
                return(false);
            }

            //
            // Invoke method
            //

            // Check accessibility
            foreach (var partype in p.Types)
            {
                if (!IsAccessibleAs(partype))
                {
                    Report.SymbolRelatedToPreviousError(partype);
                    Report.Error(59, Location,
                                 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
                                 partype.GetSignatureForError(), GetSignatureForError());
                }
            }

            var ret_type = ReturnType.ResolveAsType(this);

            if (ret_type == null)
            {
                return(false);
            }

            //
            // We don't have to check any others because they are all
            // guaranteed to be accessible - they are standard types.
            //
            if (!IsAccessibleAs(ret_type))
            {
                Report.SymbolRelatedToPreviousError(ret_type);
                Report.Error(58, Location,
                             "Inconsistent accessibility: return type `" +
                             ret_type.GetSignatureForError() + "' is less " +
                             "accessible than delegate `" + GetSignatureForError() + "'");
                return(false);
            }

            CheckProtectedModifier();

            if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType)
            {
                Method.Error1599(Location, ret_type, Report);
                return(false);
            }

            VarianceDecl.CheckTypeVariance(ret_type, Variance.Covariant, this);

            var resolved_rt = new TypeExpression(ret_type, Location);

            InvokeBuilder = new Method(this, resolved_rt, MethodModifiers, new MemberName(InvokeMethodName), p, null);
            InvokeBuilder.Define();

            //
            // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
            //
            if (!IsCompilerGenerated)
            {
                DefineAsyncMethods(Parameters.CallingConvention, resolved_rt);
            }

            return(true);
        }
Example #13
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 #14
0
        //
        // Fabricates stack forwarder based on stack types which copies all
        // parameters to type fields
        //
        public MethodSpec GetStackForwarder(TypeSpec[] types, out FieldSpec[] fields)
        {
            if (stack_forwarders == null)
            {
                stack_forwarders = new Dictionary <TypeSpec[], Tuple <MethodSpec, FieldSpec[]> > (TypeSpecComparer.Default);
            }
            else
            {
                //
                // Does same forwarder method with same types already exist
                //
                Tuple <MethodSpec, FieldSpec[]> method;
                if (stack_forwarders.TryGetValue(types, out method))
                {
                    fields = method.Item2;
                    return(method.Item1);
                }
            }

            Parameter[] p      = new Parameter[types.Length + 1];
            TypeSpec[]  ptypes = new TypeSpec[p.Length];
            fields = new FieldSpec[types.Length];

            for (int i = 0; i < types.Length; ++i)
            {
                var t = types[i];

                TypeSpec parameter_type = t;
                if (parameter_type == InternalType.CurrentTypeOnStack)
                {
                    parameter_type = CurrentType;
                }

                p[i]      = new Parameter(new TypeExpression(parameter_type, Location), null, 0, null, Location);
                ptypes[i] = parameter_type;

                if (t == InternalType.CurrentTypeOnStack)
                {
                    // Null means the type is `this' we can optimize by ignoring
                    continue;
                }

                var reference = t as ReferenceContainer;
                if (reference != null)
                {
                    t = reference.Element;
                }

                fields[i] = CreateStackValueField(t);
            }

            var this_parameter = new Parameter(new TypeExpression(CurrentType, Location), null, 0, null, Location);

            p[types.Length]      = this_parameter;
            ptypes[types.Length] = CurrentType;

            var parameters = ParametersCompiled.CreateFullyResolved(p, ptypes);

            var m = new Method(this, null, new TypeExpression(Compiler.BuiltinTypes.Void, Location),
                               Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
                               new MemberName("<>s__" + stack_forwarders.Count.ToString("X")), parameters, null);

            m.Block = new ToplevelBlock(Compiler, parameters, Location);
            m.Block.AddScopeStatement(new ParametersLoadStatement(fields, ptypes));

            m.Define();
            Methods.Add(m);

            stack_forwarders.Add(types, Tuple.Create(m.Spec, fields));

            return(m.Spec);
        }