예제 #1
0
		internal virtual void AddAbstractOverride(DMemberRef/*!*/ abstractMember)
		{
			Debug.Fail("N/A");
			throw null;
		}
예제 #2
0
파일: Members.cs 프로젝트: jiahao42/weverca
 internal virtual void AddAbstractOverride(DMemberRef /*!*/ abstractMember)
 {
     Debug.Fail("N/A");
     throw null;
 }
예제 #3
0
		internal override void AddAbstractOverride(DMemberRef/*!*/ abstractMethod)
		{
			// nop, we don't need to maintain information about abstract overrides
		}
예제 #4
0
		internal override void AddAbstractOverride(DMemberRef/*!*/ abstractProperty)
		{
			if (abstractProperty.Member.DeclaringType.IsInterface)
			{
				if (implements == null)
					implements = new List<DMemberRef>();

				implements.Add(abstractProperty);
			}
			else
				overrides = abstractProperty;
		}
예제 #5
0
		/// <summary>
		/// Emits stubs for one overridden or implemented PHP method.
		/// </summary>
		/// <param name="stubs">Already generated stubs.</param>
		/// <param name="target">The overriding/implementing method.</param>
		/// <param name="targetType">The type (perhaps constructed) that declared <paramref name="target"/>.</param>
		/// <param name="declaringType">The type where the stubs should be emitted.</param>
		/// <param name="template">The method being overridden/implemented (surely PHP).</param>
		/// <param name="newSlot"><B>True</B> if the stub should be assigned a new vtable slot,
		/// <B>false</B> otherwise.</param>
		/// <remarks>
		/// This method handles situations where method overriding/implementing does not work by itself because of
		/// the fact that method names in PHP are case insensitive.
		/// </remarks>
		private void EmitOverrideStubsForPhpTemplate(IDictionary<string, MethodBuilder>/*!*/ stubs,
			PhpMethod/*!*/ target, DType/*!*/ targetType, PhpType/*!*/ declaringType, DMemberRef/*!*/ template,
			bool newSlot)
		{
            PhpMethod php_template = (PhpMethod)template.Member;

            // Emit method stub if needed here ... (resolve .NET incompatibility of base method and overriding method)
            // 
            // Until now, several possible cases or their combination are known:
            // - base and overriding methods match, but their name letter-casing don't (need to define override explicitly to properly Bake the type)
            // - base and overriding methods name match exactly, but overriding methods has additional arguments (with default values) (in PHP it is allowed) (stub needed)
            // - ghost stub, where B extends A implements I, where A contains definition of method in I and casing does not match
            //
            // if signatures don't match, virtual sealed stub must be created, it only calls the target method
            // if signatures match, only explicit override must be stated

            if (target.Name.ToString() != php_template.Name.ToString() ||           // the names differ (perhaps only in casing)
                target.Signature.ParamCount != php_template.Signature.ParamCount || // signature was extended (additional arguments added, with implicit value only)
                target.Signature.AliasReturn != php_template.Signature.AliasReturn  // returns PhpReference instead of Object
                )
			{
				MethodInfo target_argfull = DType.MakeConstructed(target.ArgFullInfo, targetType as ConstructedType);
				TypeBuilder type_builder = declaringType.RealTypeBuilder;

				// we have to generate a pass-thru override stub that overrides the template based on
				// name since it is impossible to install an explicit override of a method declared by
				// a generic type in v2.0 SRE (feedback ID=97425)
				bool sre_bug_workaround = (template.Type is ConstructedType);

                if (target.DeclaringType == declaringType && !sre_bug_workaround &&
                    target.Signature.ParamCount == php_template.Signature.ParamCount &&
                    target.Signature.AliasReturn == php_template.Signature.AliasReturn)
				{
                    // signatures match, just install an explicit override if possible
					type_builder.DefineMethodOverride(target_argfull,
						DType.MakeConstructed(php_template.ArgFullInfo, template.Type as ConstructedType));
				}
				else
				{
					string stubs_key = null;
					MethodAttributes attrs;

                    if (sre_bug_workaround)
                    {
                        // check whether we have generated a stub having the template name before
                        if (stubs.ContainsKey(stubs_key = "," + php_template.ArgFullInfo.Name)) return;

                        attrs = php_template.ArgFullInfo.Attributes & ~MethodAttributes.Abstract;
                    }
                    else
                    {
                        attrs = MethodAttributes.PrivateScope | MethodAttributes.Virtual;
                    }

                    if (newSlot) attrs |= MethodAttributes.NewSlot; 
					else attrs &= ~MethodAttributes.NewSlot;

					// determine stub return and parameters type
					Type return_type;
					Type[] param_types = php_template.Signature.ToArgfullSignature(1, out return_type);
                    param_types[0] = Types.ScriptContext[0];

					MethodBuilder override_stub = type_builder.DefineMethod(
                        (sre_bug_workaround ? php_template.ArgFullInfo.Name : "<Override>"),
						attrs, return_type, param_types);

					ILEmitter il = new ILEmitter(override_stub);

                    //
                    // return target( [arg1, ...[, default, ...]] );
                    //

					// pass-thru all arguments, including this (arg0)
                    int pass_args = Math.Min(param_types.Length, target.Signature.ParamCount + 1);
					for (int i = 0; i <= pass_args; ++i) il.Ldarg(i);  // this, param1, ....
                    for (int i = pass_args; i <= target.Signature.ParamCount; ++i)
                    {
                        // ... // PhpException.MissingArgument(i, target.FullName); // but in some override it can be optional argument 
                        il.Emit(OpCodes.Ldsfld, PHP.Core.Emit.Fields.Arg_Default);  // paramN
                    }
                    il.Emit(OpCodes.Callvirt, target_argfull);

                    // return
                    if (target.Signature.AliasReturn != php_template.Signature.AliasReturn)
                        il.Emit(OpCodes.Call, target.Signature.AliasReturn
                            ? Methods.PhpVariable.Dereference       // PhpVariable.Deference(obj)                   
                            : Methods.PhpVariable.MakeReference);   // PhpVariable.MakeReference(obj)
                    il.Emit(OpCodes.Ret);

					if (sre_bug_workaround)
					{
						stubs.Add(stubs_key, override_stub);
					}
					else
					{
                        if (!php_template.ArgFullInfo.IsVirtual)
                            throw new InvalidOperationException(string.Format("Cannot override non-virtual method '{0}'!", php_template.ArgFullInfo.Name));

						type_builder.DefineMethodOverride(override_stub,
							DType.MakeConstructed(php_template.ArgFullInfo, template.Type as ConstructedType));
					}
				}
			}
		}
예제 #6
0
		/// <summary>
		/// Emits stubs for all overloads of one overridden or implemented method.
		/// </summary>
		/// <param name="stubs">Already generated stubs.</param>
		/// <param name="target">The overriding/implementing method.</param>
		/// <param name="targetType">The type (perhaps constructed) that declared <paramref name="target"/>.</param>
		/// <param name="declaringType">The type where the stubs should be emitted.</param>
		/// <param name="template">The method being overridden/implemented.</param>
		/// <param name="newSlot"><B>True</B> if the stub should be assigned a new vtable slot,
		/// <B>false</B> otherwise.</param>
		private void EmitOverrideStubs(IDictionary<string, MethodBuilder>/*!*/ stubs, PhpMethod/*!*/ target,
			DType/*!*/ targetType, PhpType/*!*/ declaringType, DMemberRef/*!*/ template, bool newSlot)
		{
			ClrMethod clr_template = template.Member as ClrMethod;
			if (clr_template == null)
			{
                if (!target.IsStatic)
				    EmitOverrideStubsForPhpTemplate(stubs, target, targetType, declaringType, template, newSlot);

				return;
			}

            //
            // following code emits stubs in case of CLR base method
            //

			ConstructedType constructed_type = template.Type as ConstructedType;
			TypeBuilder type_builder = declaringType.RealTypeBuilder;

			// override all virtual non-final overloads
			foreach (ClrMethod.Overload overload in clr_template.Overloads)
			{
				if (overload.Method.IsVirtual && !overload.Method.IsFinal)
				{
					// map generic type parameters according to the constructed type
					Type constructed_return_type;
					ParameterInfo[] constructed_params = overload.MakeConstructed(constructed_type, out constructed_return_type);

					// check whether we have not generated this signature before
					string clr_sig = ClrMethod.Overload.ClrSignatureToString(
						overload.GenericParamCount,
						constructed_params,
						constructed_return_type);

					if (stubs.ContainsKey(clr_sig)) continue;

					Type[] param_types = new Type[constructed_params.Length];

					for (int j = 0; j < param_types.Length; j++)
					{
						param_types[j] = constructed_params[j].ParameterType;
					}

					// determine the stub attributes
					MethodAttributes attr;
					string name;

					name = overload.Method.Name;
					attr = Reflection.Enums.ToMethodAttributes(target.MemberDesc.MemberAttributes);
					attr |= (MethodAttributes.Virtual | MethodAttributes.HideBySig);

					if (newSlot) attr |= MethodAttributes.NewSlot;

					MethodBuilder overload_builder = type_builder.DefineMethod(name, attr);

					if (overload.MandatoryGenericParamCount > 0)
					{
						// define the same generic parameters that are defined for the overridden method
						// (the same constraints but possibly having different names)
						ClrStubBuilder.DefineStubGenericParameters(
							overload_builder,
							overload.GenericParameters,
							target.Signature,
							param_types);
					}

					overload_builder.SetReturnType(constructed_return_type);
					overload_builder.SetParameters(param_types);

					// set parameter names and attributes
					ClrStubBuilder.DefineStubParameters(overload_builder,
						target.Builder.Signature.FormalParams, constructed_params);

					if (!overload_builder.IsAbstract)
					{
						EmissionContext emission_context = SetupStubPlaces(target.DeclaringPhpType, false);

						try
						{
							// convert parameters and invoke the target
							ClrStubBuilder.EmitMethodStubBody(
								new ILEmitter(overload_builder),
								ScriptContextPlace,
								constructed_params,
								overload.GenericParameters,
								constructed_return_type,
								target,
								targetType);
						}
						finally
						{
							RestorePlaces(emission_context);
						}
					}

					stubs.Add(clr_sig, overload_builder);
				}
			}
		}
예제 #7
0
		/// <summary>
		/// Emits property stubs for a overriden or implemented CLR property.
		/// </summary>
		/// <param name="stubs">Already generated stubs.</param>
		/// <param name="target">The overriding/implementing field.</param>
		/// <param name="declaringType">The type where the stubs should be emitted.</param>
		/// <param name="template">The property being overriden/implemented.</param>
		/// <param name="newSlot"><B>True</B> if the stub should be assigned a new vtable slot,
		/// <B>false</B> otherwise.</param>
		private void EmitOverrideStubs(IDictionary<Type, PropertyBuilder>/*!*/ stubs, PhpField/*!*/ target,
			PhpType/*!*/ declaringType, DMemberRef/*!*/ template, bool newSlot)
		{
			ClrProperty clr_template = template.Member as ClrProperty;
			if (clr_template == null) return;

			MethodInfo getter = clr_template.Getter;
			MethodInfo setter = clr_template.Setter;

			// we're only interested in non-final virtual getters/setters
			if (getter != null && (!getter.IsVirtual || getter.IsFinal)) getter = null;
			if (setter != null && (!setter.IsVirtual || setter.IsFinal)) setter = null;

			ConstructedType constructed_type = template.Type as ConstructedType;

			// map property type according to constructed type
			Type property_type = clr_template.RealProperty.PropertyType;
			if (constructed_type != null) property_type = constructed_type.MapRealType(property_type);

			// do we already have getter/setter of this type?
			PropertyBuilder prop_builder;
			if (stubs.TryGetValue(property_type, out prop_builder))
			{
				if (prop_builder.GetGetMethod(true) != null) getter = null;
				if (prop_builder.GetSetMethod(true) != null) setter = null;
			}

			if (getter != null || setter != null)
			{
				if (prop_builder == null)
				{
					// the property might already exist - we could be just adding an accessor
					TypeBuilder type_builder = declaringType.RealTypeBuilder;

					prop_builder = type_builder.DefineProperty(
						clr_template.Name.ToString(),
						Reflection.Enums.ToPropertyAttributes(target.MemberDesc.MemberAttributes),
						property_type,
						Type.EmptyTypes);

					stubs.Add(property_type, prop_builder);
				}

				if (getter != null)
				{
					// add getter
					MethodBuilder getter_builder = DefineOverrideAccessor(
						declaringType,
						target,
						getter,
						newSlot,
						property_type,
						Type.EmptyTypes);

					prop_builder.SetGetMethod(getter_builder);

					EmitFieldExportGetter(target, prop_builder, getter_builder);
				}

				if (setter != null)
				{
					// add setter
					MethodBuilder setter_builder = DefineOverrideAccessor(
						declaringType,
						target,
						setter,
						newSlot,
						Types.Void,
						new Type[] { property_type });

					prop_builder.SetSetMethod(setter_builder);

					EmitFieldExportSetter(target, prop_builder, setter_builder);
				}
			}
		}
예제 #8
0
 internal override void AddAbstractOverride(DMemberRef/*!*/ abstractMethod)
 {
     throw new NotSupportedException();
 }
예제 #9
0
		internal override void AddAbstractOverride(DMemberRef/*!*/ abstractMethod)
		{
			if (abstractMethod.Member.DeclaringType.IsInterface)
			{
				if (implements == null)
					implements = new List<DMemberRef>();

				implements.Add(abstractMethod);

				Debug.WriteLine("F-ANALYSIS", "GetUserEntryPoint '{0}::{1}': implemens += '{2}::{3}'",
					DeclaringType.FullName, FullName, abstractMethod.Type.MakeFullGenericName(), abstractMethod.Member.FullName);
			}
			else
			{
				overrides = abstractMethod;
				Debug.WriteLine("F-ANALYSIS", "GetUserEntryPoint '{0}::{1}': overrides = '{2}::{3}'",
					DeclaringType.FullName, FullName, overrides.Type.MakeFullGenericName(), overrides.Member.FullName);
			}
		}