Exemple #1
0
        /// <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];
                }
            }
        }
        /// <summary>
        /// Add at runtime a method to a type
        /// </summary>
        /// <param name="typedesc">Type to modify</param>
        /// <param name="attributes">New method attributes</param>
        /// <param name="func_name">Method name</param>
        /// <param name="callback">Method body</param>
        /// <remarks>Used by PDO_SQLITE</remarks>
        public void AddMethodToType(DTypeDesc typedesc, PhpMemberAttributes attributes, string func_name, Func <object, PhpStack, object> callback)
        {
            Debug.Assert(typedesc != null);

            var name        = new Name(func_name);
            var method_desc = new PhpRoutineDesc(typedesc, attributes);

            if (!typedesc.Methods.ContainsKey(name))
            {
                typedesc.Methods.Add(name, method_desc);

                // assign member:
                if (method_desc.Member == null)
                {
                    Func <ScriptContext, object> dummyArgFullCallback = DummyArgFull;
                    PhpMethod method = new PhpMethod(name, (PhpRoutineDesc)method_desc, dummyArgFullCallback.Method, (callback != null) ? callback.Method : null);
                    method.WriteUp(PhpRoutineSignature.FromArgfullInfo(method, dummyArgFullCallback.Method));
                    method_desc.Member = method;
                }
            }
        }
Exemple #3
0
        /// <summary>
        ///	reflect global functions in &lt;Script&gt; class
        /// TODO: consider merging with PhpTypeDesc.FullReflectMethods
        /// </summary>
        /// <param name="functions">Dictionary for functions</param>
        /// <param name="scriptType">The type to reflect from.</param>
        private static void ReflectScriptTypeFunctions(Type scriptType, Dictionary <string, DRoutineDesc> functions)
        {
            MethodInfo[] real_methods = scriptType.GetMethods(DTypeDesc.MembersReflectionBindingFlags);
            Dictionary <string, MethodInfo> argless_stubs = new Dictionary <string, MethodInfo>(real_methods.Length / 3);

            // first pass - fill argless_stubs
            for (int i = 0; i < real_methods.Length; i++)
            {
                MethodInfo info = real_methods[i];
                if ((info.Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.PrivateScope)
                {
                    if (PhpFunctionUtils.IsArglessStub(info, null))
                    {
                        argless_stubs.Add(info.Name, info);
                        real_methods[i] = null;
                    }
                }
                else
                {
                    real_methods[i] = null;                  // expunge private scope methods
                }
            }

            // second pass - match argfulls
            foreach (MethodInfo info in real_methods)
            {
                // argfull detection:
                if (info == null || !PhpFunctionUtils.IsArgfullOverload(info, null))
                {
                    continue;
                }

                // TODO: namespaces!!

                if (functions.ContainsKey(info.Name))
                {
                    throw new InvalidOperationException("Function '" + info.Name + "' redeclaration.");   // compilation unit contains more functions with the same name
                }
                // find the argless:
                MethodInfo argless_info = null;
                if (!argless_stubs.TryGetValue(info.Name, out argless_info))
                {
                    // argless has to be generated on-the-fly
                    throw new NotImplementedException("Generating argless stubs for imported PHP types is not yet implemented");
                }

                if (!PhpFunctionUtils.IsRealConditionalDefinition(info.Name))
                {
                    Name                name = new Name(info.Name);
                    DRoutineDesc        func_desc;
                    PhpMemberAttributes attrs = Enums.GetMemberAttributes(info);

                    // this method has not been populated -> create a new PhpRoutineDesc
                    func_desc = new PhpRoutineDesc(attrs, (RoutineDelegate)Delegate.CreateDelegate(Types.RoutineDelegate, argless_info), true);
                    functions.Add(info.Name, func_desc);

                    //
                    if (func_desc.Member == null)
                    {
                        PhpFunction func = new PhpFunction(new QualifiedName(name), (PhpRoutineDesc)func_desc, info, argless_info);
                        func.WriteUp(PhpRoutineSignature.FromArgfullInfo(func, info));
                        func_desc.Member = func;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Enumerates all export overloads for the given target PHP method.
        /// </summary>
        public static IEnumerable <StubInfo> DefineMethodExportStubs(
            PhpRoutine /*!*/ target,
            MethodAttributes attributes,
            bool defineConstructors,
            StubSignatureFilter /*!*/ signatureFilter)
        {
            Debug.Assert(target.Builder != null);

            Type return_type = Types.Object[0];

            PhpRoutineSignature        signature          = target.Signature;
            List <AST.FormalParam>     formal_params      = target.Builder.Signature.FormalParams;
            List <AST.FormalTypeParam> formal_type_params = target.Builder.TypeSignature.TypeParams;

            int gen_sig_count = signature.GenericParamCount - signature.MandatoryGenericParamCount + 1;
            int arg_sig_count = signature.ParamCount - signature.MandatoryParamCount + 1;

            // TODO: return type hints
            // HACK: change return type to void for methods that are apparently event handlers
            if (signature.GenericParamCount == 0 && arg_sig_count == 1 && signature.ParamCount == 2 &&
                (signature.TypeHints[0] == null || signature.TypeHints[0].RealType == Types.Object[0]) &&
                (signature.TypeHints[1] != null && typeof(EventArgs).IsAssignableFrom(signature.TypeHints[1].RealType)))
            {
                return_type = Types.Void;
            }

            for (int gen_sig = 0; gen_sig < gen_sig_count; gen_sig++)
            {
                for (int arg_sig = 0; arg_sig < arg_sig_count; arg_sig++)
                {
                    // determine parameter types (except for method mandatory generic parameters)
                    object[] parameter_types = GetStubParameterTypes(
                        arg_sig + signature.MandatoryParamCount,
                        gen_sig + signature.MandatoryGenericParamCount,
                        signature,
                        formal_type_params);

                    // determine generic parameter names
                    string[] generic_param_names = new string[target.Signature.MandatoryGenericParamCount + gen_sig];
                    for (int i = 0; i < generic_param_names.Length; i++)
                    {
                        generic_param_names[i] = formal_type_params[i].Name.ToString();
                    }

                    // are we allowed to generate this signature?
                    if (!signatureFilter(generic_param_names, parameter_types, return_type))
                    {
                        continue;
                    }

                    GenericTypeParameterBuilder[] generic_params = StubInfo.EmptyGenericParameters;
                    MethodBase    method_base = null;
                    MethodBuilder method      = null;

                    if (!defineConstructors)
                    {
                        method = target.DeclaringType.RealTypeBuilder.DefineMethod(target.FullName, attributes);

                        // determine generic parameters
                        if (generic_param_names.Length > 0)
                        {
                            generic_params = method.DefineGenericParameters(generic_param_names);
                        }

                        method_base = method;
                    }

                    ParameterInfo[] parameters = new ParameterInfo[parameter_types.Length];

                    // fill in parameter infos
                    Type[] real_parameter_types = new Type[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        Type type = parameter_types[i] as Type;

                        // generic method parameter fixup
                        if (type == null)
                        {
                            int index = (int)parameter_types[i];
                            if (index < 0)
                            {
                                type = generic_params[-(index + 1)].MakeByRefType();
                            }
                            else
                            {
                                type = generic_params[index];
                            }
                        }

                        string param_name;
                        ParameterAttributes param_attrs;
                        if (i < formal_params.Count)
                        {
                            param_name  = formal_params[i].Name.ToString();
                            param_attrs = (formal_params[i].IsOut ? ParameterAttributes.Out : ParameterAttributes.None);
                        }
                        else
                        {
                            param_name  = "args" + (i + 1);
                            param_attrs = ParameterAttributes.None;
                        }

                        parameters[i]           = new StubParameterInfo(i, type, param_attrs, param_name);
                        real_parameter_types[i] = type;
                    }

                    if (method != null)
                    {
                        method.SetParameters(real_parameter_types);
                        method.SetReturnType(return_type);

                        method.SetCustomAttribute(AttributeBuilders.DebuggerHidden);
                    }
                    else
                    {
                        // constructor is never a generic method
                        attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
                        attributes &= ~MethodAttributes.Virtual;

                        ConstructorBuilder constructor = target.DeclaringType.RealTypeBuilder.DefineConstructor(
                            attributes, CallingConventions.Standard, real_parameter_types);
                        constructor.SetCustomAttribute(AttributeBuilders.DebuggerHidden);

                        method_base = constructor;
                    }

                    yield return(new StubInfo(method_base, parameters, generic_params, return_type));
                }
            }
        }
Exemple #5
0
        private static object[] GetStubParameterTypes(
            int paramCount,
            int typeParamCount,
            PhpRoutineSignature /*!*/ signature,
            List <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
                                DType default_type = formalTypeParams[gen_type_hint.Index].DefaultType as DType;
                                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);
        }