private static object[] GetStubParameterTypes( int paramCount, int typeParamCount, PhpRoutineSignature/*!*/ signature, PHP.Core.AST.FormalTypeParam[]/*!*/ formalTypeParams) { object[] parameter_types = new object[paramCount]; for (int i = 0; i < paramCount; i++) { DType type_hint = signature.TypeHints[i]; if (type_hint != null && !type_hint.IsUnknown) { GenericParameter gen_type_hint = type_hint as GenericParameter; if (gen_type_hint != null) { // this is a generic parameter - declared by either the method or type if (gen_type_hint.DeclaringMember is PhpRoutine) { if (gen_type_hint.Index < typeParamCount) { // unknown at this point - fixed-up later parameter_types[i] = gen_type_hint.Index; } else { // default generic parameter var typeparam = formalTypeParams[gen_type_hint.Index].DefaultType; DType default_type = typeparam as DType; if (default_type == null && typeparam is GenericQualifiedName) default_type = PrimitiveType.GetByName((GenericQualifiedName)typeparam); parameter_types[i] = (default_type == null ? Types.Object[0] : default_type.RealType); } } else parameter_types[i] = gen_type_hint.RealGenericTypeParameterBuilder; } else parameter_types[i] = type_hint.RealType; } else parameter_types[i] = Types.Object[0]; // make it byref if declared with & if (signature.AliasMask[i]) { Type type = parameter_types[i] as Type; if (type != null) parameter_types[i] = type.MakeByRefType(); else parameter_types[i] = -((int)parameter_types[i] + 1); } Debug.Assert(parameter_types[i] != null); } return parameter_types; }
/// <summary> /// Defines generic parameters according to the given template and re-maps relevant parameters. /// </summary> public static void DefineStubGenericParameters(MethodBuilder/*!*/ stub, Type[]/*!!*/ genericParameters, PhpRoutineSignature/*!*/ targetSignature, Type[]/*!!*/ parameters) { // determine generic parameter names string[] generic_param_names = new string[genericParameters.Length]; for (int j = 0; j < generic_param_names.Length; j++) { if (j < targetSignature.GenericParamCount) { generic_param_names[j] = targetSignature.GenericParams[j].Name.ToString(); } else generic_param_names[j] = genericParameters[j].Name; } GenericTypeParameterBuilder[] generic_params = stub.DefineGenericParameters(generic_param_names); // determine generic parameter attributes and constraints for (int j = 0; j < generic_params.Length; j++) { Type template_type = genericParameters[j]; // attributes generic_params[j].SetGenericParameterAttributes(template_type.GenericParameterAttributes); // constraints Type[] template_constraints = template_type.GetGenericParameterConstraints(); List<Type> interface_constraints = new List<Type>(); for (int k = 0; k < template_constraints.Length; k++) { if (template_constraints[k].IsClass) generic_params[j].SetBaseTypeConstraint(template_constraints[k]); else interface_constraints.Add(template_constraints[k]); } generic_params[j].SetInterfaceConstraints(interface_constraints.ToArray()); } // re-map base method generic parameters to the newly defined generic parameters for (int j = 0; j < parameters.Length; j++) { if (parameters[j].IsGenericParameter && parameters[j].DeclaringMethod != null) { // method generic parameter parameters[j] = generic_params[parameters[j].GenericParameterPosition]; } } }
internal void WriteUp(PhpRoutineSignature/*!*/ signature) { Debug.Assert(signature != null); Debug.Assert(this.signature == null, "Already written up."); this.signature = signature; }
/// <summary> /// Used by the reflection. /// </summary> public PhpRoutine(DRoutineDesc/*!*/ functionDesc) : base(functionDesc) { this.signature = null; // to be written up this.builder = null; // unused }
/// <summary> /// Used by the compiler. /// </summary> internal PhpRoutine(DRoutineDesc/*!*/ functionDesc, Signature astSignature, TypeSignature astTypeSignature) : base(functionDesc) { this.signature = null; // to be written up this.builder = new PhpRoutineBuilder(this, astSignature, astTypeSignature); }