Ejemplo n.º 1
0
            internal void AnalyzeMembers(FormalParam /*!*/ node, Analyzer /*!*/ analyzer, PhpRoutine /*!*/ routine, int index)
            {
                this.routine = routine;
                this.index   = index;

                PhpType referring_type;
                Scope   referring_scope;

                if (routine.IsMethod)
                {
                    referring_type  = routine.DeclaringPhpType;
                    referring_scope = referring_type.Declaration.Scope;
                }
                else if (routine.IsLambdaFunction)
                {
                    referring_type  = analyzer.CurrentType;
                    referring_scope = analyzer.CurrentScope;
                }
                else
                {
                    referring_type  = null;
                    referring_scope = ((PhpFunction)routine).Declaration.Scope;
                }

                var attributes = node.Attributes;

                if (attributes != null)
                {
                    attributes.AnalyzeMembers(analyzer, referring_scope);
                }

                resolvedTypeHint = analyzer.ResolveType(node.TypeHint, referring_type, routine, node.Span, false);
            }
Ejemplo n.º 2
0
        internal void AnalyzeMembers(Analyzer /*!*/ analyzer, PhpRoutine /*!*/ routine, int index)
        {
            this.routine = routine;
            this.index   = index;

            PhpType referring_type;
            Scope   referring_scope;

            if (routine.IsMethod)
            {
                referring_type  = routine.DeclaringPhpType;
                referring_scope = referring_type.Declaration.Scope;
            }
            else if (routine.IsLambdaFunction)
            {
                referring_type  = analyzer.CurrentType;
                referring_scope = analyzer.CurrentScope;
            }
            else
            {
                referring_type  = null;
                referring_scope = ((PhpFunction)routine).Declaration.Scope;
            }

            attributes.AnalyzeMembers(analyzer, referring_scope);

            resolvedTypeHint = analyzer.ResolveType(typeHint, referring_type, routine, position, false);
        }
Ejemplo n.º 3
0
        internal void EmitLoadTypeArgsOnEvalStack(CodeGenerator /*!*/ codeGenerator, PhpRoutine /*!*/ routine)
        {
            ILEmitter il = codeGenerator.IL;

            int mandatory_count = (routine.Signature != null) ? routine.Signature.MandatoryGenericParamCount : 0;
            int formal_count    = (routine.Signature != null) ? routine.Signature.GenericParamCount : 0;
            int actual_count    = genericParams.Count;

            // loads all actual parameters which are not superfluous:
            for (int i = 0; i < Math.Min(actual_count, formal_count); i++)
            {
                genericParams[i].EmitLoadTypeDesc(codeGenerator, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors);
            }

            // loads missing mandatory arguments:
            for (int i = actual_count; i < mandatory_count; i++)
            {
                // CALL PhpException.MissingTypeArgument(<i+1>,<name>);
                il.LdcI4(i + 1);
                il.Emit(OpCodes.Ldstr, routine.FullName);
                codeGenerator.EmitPhpException(Methods.PhpException.MissingTypeArgument);

                // LOAD DTypeDesc.ObjectTypeDesc;
                il.Emit(OpCodes.Ldsfld, Fields.DTypeDesc.ObjectTypeDesc);
            }

            // loads missing optional arguments:
            for (int i = Math.Max(mandatory_count, actual_count); i < formal_count; i++)
            {
                // LOAD Arg.DefaultType;
                il.Emit(OpCodes.Ldsfld, Fields.Arg_DefaultType);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Generates expression for a given argument to fit formal argument of the give routine.
        /// </summary>
        /// <param name="routine">Routine for which argument will be supplied.</param>
        /// <param name="scriptContext">ScriptContext DynamicMetaObject</param>
        /// <param name="arg">Actual argument to be supplied to be supplied to routine.</param>
        /// <param name="argIndex">Index of the argument in a routine(not counting ScriptContext argument).</param>
        /// <returns>The expression of an argument that is prepared to be supplied as an argument to the routine.</returns>
        private static Expression /*!*/ GeneratePeekArgument(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
        {
            bool optional            = argIndex >= routine.Signature.MandatoryParamCount;
            int  argIndexTransformed = argIndex + 1; // in PHP indexes of arguments starts from index 1

            if (routine.Signature.IsAlias(argIndex))
            {
                if (optional)
                {
                    return(PeekReferenceOptional(routine, scriptContext, arg, argIndexTransformed));
                }
                else
                {
                    return(PeekReference(routine, scriptContext, arg, argIndexTransformed));
                }
            }
            else
            {
                if (optional)
                {
                    return(PeekValueOptional(routine, scriptContext, arg, argIndexTransformed));
                }
                else
                {
                    return(PeekValue(routine, scriptContext, arg, argIndexTransformed));
                }
            }
        }
Ejemplo n.º 5
0
        private static Expression /*!*/ PeekReferenceUnchecked(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
        {
            // the caller may not pushed a reference although the formal argument is a reference:
            // it doesn't matter if called by callback:
            if (!Types.PhpReference[0].IsAssignableFrom(arg.LimitType))
            {
                // caller may have pushed a runtime chain => evaluate it:
                if (arg.LimitType == Types.PhpRuntimeChain[0])
                {
                    //result = php_chain.GetReference(Context);
                    return(Expression.Call(
                               Expression.Convert(arg.Expression, Types.PhpRuntimeChain[0]),
                               Methods.PhpRuntimeChain.GetReference,
                               scriptContext.Expression));
                }
                else
                {
                    // the reason of copy is not exactly known (it may be returning by copy as well as passing by copy):
                    // result = new PhpReference(PhpVariable.Copy(arg_i, CopyReason.Unknown));

                    ParameterExpression   resultVariable = Expression.Parameter(Types.PhpReference[0], "result");
                    ParameterExpression[] vars           = new ParameterExpression[] { resultVariable };

                    return(Expression.Block(vars,
                                            Expression.Assign(
                                                resultVariable,
                                                Expression.New(Constructors.PhpReference_Object, Expression.Call(Methods.PhpVariable.Copy, arg.Expression, Expression.Constant(CopyReason.Unknown)))),
                                            BinderHelper.ThrowArgumentNotPassedByRef(argIndex, routine.FullName),
                                            resultVariable));

                    //(MB) I'm not sure if it's necessary to execute these two in this order


                    //Original code
                    //
                    //(MB) I don't have to solve this now, PhpCallback is called in a old manner. So I can just throw exception always now.
                    //
                    // Reports an error in the case that we are not called by callback.
                    // Although, this error is fatal one can switch throwing exceptions off.
                    // If this is the case the afterwards behavior will be the same as if callback was called.
                    //if (!Callback)
                    //{
                    //    // warning (can invoke user code => we have to save and restore callstate):
                    //    CallState call_state = SaveCallState();

                    //    PhpException.ArgumentNotPassedByRef(i, CalleeName);
                    //    RestoreCallState(call_state);
                    //}
                }
            }
            else
            {
                return(Expression.Convert(arg.Expression, arg.LimitType));
            }
        }
Ejemplo n.º 6
0
 private static Expression /*!*/ PeekTypeOptional(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     if (arg != null)
     {
         // peeks the value:
         return(Expression.Convert(arg.Expression, arg.LimitType));
     }
     else
     {
         // default value:
         return(Expression.Constant(Arg.DefaultType, Types.DTypeDesc[0]));
     }
 }
Ejemplo n.º 7
0
 private static Expression /*!*/ PeekReferenceOptional(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     if (arg != null)
     {
         // peeks the value:
         return(PeekReferenceUnchecked(routine, scriptContext, arg, argIndex));
     }
     else
     {
         // default value:
         return(Expression.Constant(Arg.Default, Types.PhpReference[0]));
     }
 }
Ejemplo n.º 8
0
 private static Expression /*!*/ PeekType(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     if (arg != null)
     {
         // peeks the value:
         return(Expression.Convert(arg.Expression, arg.LimitType));
     }
     else
     {
         return(Expression.Block(
                    BinderHelper.ThrowMissingTypeArgument(argIndex, routine.FullName),
                    Expression.Constant(DTypeDesc.ObjectTypeDesc, Types.DTypeDesc[0])));
     }
 }
Ejemplo n.º 9
0
 private static Expression /*!*/ PeekReference(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     if (arg != null)
     {
         // peeks the reference:
         return(PeekReferenceUnchecked(routine, scriptContext, arg, argIndex));
     }
     else
     {
         return(Expression.Block(
                    BinderHelper.ThrowMissingArgument(argIndex, routine.FullName),
                    Expression.New(Constructors.PhpReference_Void)));
     }
 }
Ejemplo n.º 10
0
 private static Expression /*!*/ PeekValue(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     if (arg != null)
     {
         // peeks the value:
         return(PeekValueUnchecked(routine, scriptContext, arg, argIndex));
     }
     else
     {
         return(Expression.Block(
                    BinderHelper.ThrowMissingArgument(argIndex, routine.FullName),
                    Expression.Constant(null)));
     }
 }
Ejemplo n.º 11
0
        private static Expression /*!*/ GeneratePeekPseudoGenericArgument(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int index)
        {
            bool optional         = index >= routine.Signature.MandatoryGenericParamCount;
            int  indexTransformed = index + 1; // in PHP indexes of arguments starts from index 1

            if (optional)
            {
                return(PeekTypeOptional(routine, scriptContext, arg, indexTransformed));
            }
            else
            {
                return(PeekType(routine, scriptContext, arg, indexTransformed));
            }
        }
Ejemplo n.º 12
0
        internal void EmitLoadArgsOnEvalStack(CodeGenerator /*!*/ codeGenerator, PhpRoutine /*!*/ routine)
        {
            ILEmitter il = codeGenerator.IL;

            int         mandatory_count = (routine.Signature != null) ? routine.Signature.MandatoryParamCount : 0;
            int         formal_count    = (routine.Signature != null) ? routine.Signature.ParamCount : 0;
            int         actual_count    = parameters.Count;
            PhpTypeCode param_type;

            // loads all actual parameters which are not superfluous:
            for (int i = 0; i < Math.Min(actual_count, formal_count); i++)
            {
                codeGenerator.EmitBoxing(param_type = parameters[i].Emit(codeGenerator));

                // Actual param emitter should emit "boxing" to a reference if its access type is ReadRef.
                // That's why no operation is needed here and references should match.
                Debug.Assert((routine.Signature == null || routine.Signature.IsAlias(i)) == (param_type == PhpTypeCode.PhpReference));
            }

            // loads missing mandatory arguments:
            for (int i = actual_count; i < mandatory_count; i++)
            {
                // CALL PhpException.MissingArgument(<i+1>,<name>);
                il.LdcI4(i + 1);
                il.Emit(OpCodes.Ldstr, routine.FullName);
                codeGenerator.EmitPhpException(Methods.PhpException.MissingArgument);

                // LOAD null;
                if (routine.Signature.IsAlias(i))
                {
                    il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void);
                }
                else
                {
                    il.Emit(OpCodes.Ldnull);
                }
            }

            // loads missing optional arguments:
            for (int i = Math.Max(mandatory_count, actual_count); i < formal_count; i++)
            {
                // LOAD Arg.Default;
                il.Emit(OpCodes.Ldsfld, Fields.Arg_Default);
            }
        }
Ejemplo n.º 13
0
 private static Expression /*!*/ PeekValueUnchecked(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
 {
     // caller may have pushed a reference even if a formal argument is not reference => dereference it:
     if (Types.PhpReference[0].IsAssignableFrom(arg.LimitType)) // what about SmartReference
     {
         //object result = ((PhpReference)arg_i).Value;
         return(Expression.Field(Expression.Convert(arg.Expression, Types.PhpReference[0]), Fields.PhpReference_Value));
     }
     else
     // caller may have pushed a runtime chain => evaluate it:
     if (arg.LimitType == Types.PhpRuntimeChain[0])
     {
         //result = php_chain.GetValue(Context);
         return(Expression.Call(
                    Expression.Convert(arg.Expression, Types.PhpRuntimeChain[0]),
                    Methods.PhpRuntimeChain.GetValue,
                    scriptContext.Expression));
     }
     else
     {
         return(arg.Expression);
     }
 }
Ejemplo n.º 14
0
        internal void AnalyzeMembers(Analyzer /*!*/ analyzer, PhpRoutine /*!*/ routine)
        {
            int      last_mandatory_param_index = -1;
            bool     last_param_was_optional    = false;
            BitArray alias_mask = new BitArray(formalParams.Count);

            DType[] type_hints = new DType[formalParams.Count];

            for (int i = 0; i < formalParams.Count; i++)
            {
                FormalParam param = formalParams[i];

                param.AnalyzeMembers(analyzer, routine, i);

                alias_mask[i] = param.PassedByRef;
                type_hints[i] = param.ResolvedTypeHint;

                if (param.InitValue == null)
                {
                    if (last_param_was_optional)
                    {
                        analyzer.ErrorSink.Add(Warnings.MandatoryBehindOptionalParam, analyzer.SourceUnit,
                                               param.Position, param.Name);
                    }

                    last_mandatory_param_index = i;
                    last_param_was_optional    = false;
                }
                else
                {
                    last_param_was_optional = true;
                }
            }

            routine.Signature.WriteUp(aliasReturn, alias_mask, type_hints, last_mandatory_param_index + 1);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Prepares arguments for argfull overload.
        /// </summary>
        /// <param name="routine">Routine for which arguments should be prepared</param>
        /// <param name="arguments">Arguments to be prepared for the routine</param>
        /// <param name="genericArguments">Amount of generic arguments provided by call site.</param>
        /// <param name="regularArguments">Amount of value arguments provided by call site.</param>
        /// <param name="restrictions">Type restrictions for the arguments</param>
        /// <returns>Array of prepared arguments to be called with routine</returns>
        /// <remarks>
        /// This is basically substitute for everything important that was done in argless overload (except it doesn't use PhpStack but evaluation stack).
        /// It adopts the arguments according to routine. e.g. dereference reference if value is needed, supplies default argument, etc.
        /// </remarks>
        public static Expression[] PrepareArguments(this PhpRoutine routine, DynamicMetaObject[] arguments, int genericArguments, int regularArguments, out BindingRestrictions restrictions)
        {
            const int         scriptContextIndex = 0;
            DynamicMetaObject arg;
            int result_offset   = 0;
            int argument_offset = 0;

            Expression[] result = new Expression[1 + routine.Signature.GenericParamCount + routine.Signature.ParamCount];//ScriptContext + all arguments = actual arguments to be passed to argfull overload
            restrictions = BindingRestrictions.Empty;

            result[scriptContextIndex] = arguments[scriptContextIndex].Expression;
            ++result_offset;
            ++argument_offset;

            // peek pseudo-generic arguments:
            for (int i = 0; i < routine.Signature.GenericParamCount; ++i)
            {
                if (i < genericArguments)
                {
                    arg = arguments[argument_offset + i];
                }
                else
                {
                    arg = null;
                }

                result[result_offset + i] = GeneratePeekPseudoGenericArgument(routine, arguments[scriptContextIndex], arg, i);

                // it isn't necessary to add restriction for type argument, it is always DTypeDesc
            }

            result_offset   += routine.Signature.GenericParamCount;
            argument_offset += genericArguments;

            // peek regular arguments:
            // skip first one ScriptContext and generic parameters
            for (int i = 0; i < routine.Signature.ParamCount; ++i)
            {
                if (i < regularArguments)
                {
                    arg = arguments[argument_offset + i];

                    if (arg.RuntimeType != null)
                    {
                        restrictions = restrictions.Merge(BindingRestrictions.GetTypeRestriction(arguments[argument_offset + i].Expression, arguments[argument_offset + i].LimitType));
                    }
                    else
                    {
                        restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(arguments[argument_offset + i].Expression, null));//(MB) is it necessary?
                    }
                }
                else
                {
                    arg = null;
                }

                result[result_offset + i] = GeneratePeekArgument(routine, arguments[scriptContextIndex], arg, i);
            }

            return(result);
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Emits IL instructions that load actual parameters on the evaluation stack.
 /// </summary>
 /// <param name="codeGenerator">Code generator.</param>
 /// <param name="routine">PHP method being called.</param>
 /// <remarks>
 /// <para>
 /// The function has mandatory and optional formal arguments.
 /// Mandatory arguments are those formal arguments which are not preceded by
 /// any formal argument with default value. The others are optional.
 /// If a formal argument without default value is declared beyond the last mandatory argument
 /// it is treated as optional one by the caller. The callee checks this and throws warning.
 /// </para>
 /// Missing arguments handling:
 /// <list type="bullet">
 ///   <item>missing mandatory argument - WARNING; LOAD(null);</item>
 ///   <item>missing optional argument - LOAD(Arg.Default);</item>
 ///   <item>superfluous arguments are ignored</item>
 /// </list>
 /// </remarks>
 internal void EmitLoadOnEvalStack(CodeGenerator /*!*/ codeGenerator, PhpRoutine /*!*/ routine)
 {
     EmitLoadTypeArgsOnEvalStack(codeGenerator, routine);
     EmitLoadArgsOnEvalStack(codeGenerator, routine);
 }
Ejemplo n.º 17
0
            internal static void AnalyzeMembers(Signature node, Analyzer /*!*/ analyzer, PhpRoutine /*!*/ routine)
            {
                int      last_mandatory_param_index = -1;
                bool     last_param_was_optional    = false;
                var      formalParams = node.FormalParams;
                BitArray alias_mask   = new BitArray(formalParams.Length);

                DType[] type_hints = new DType[formalParams.Length];

                for (int i = 0; i < formalParams.Length; i++)
                {
                    var param         = formalParams[i];
                    var paramcompiler = param.NodeCompiler <FormalParamCompiler>();

                    paramcompiler.AnalyzeMembers(param, analyzer, routine, i);

                    alias_mask[i] = param.PassedByRef;
                    type_hints[i] = paramcompiler.ResolvedTypeHint;

                    if (param.InitValue == null && !param.IsVariadic)   // optional parameters
                    {
                        if (last_param_was_optional)
                        {
                            analyzer.ErrorSink.Add(Warnings.MandatoryBehindOptionalParam, analyzer.SourceUnit,
                                                   param.Span, param.Name);
                        }

                        last_mandatory_param_index = i;
                        last_param_was_optional    = false;
                    }
                    else
                    {
                        last_param_was_optional = true;
                    }
                }

                routine.Signature.WriteUp(node.AliasReturn, alias_mask, type_hints, last_mandatory_param_index + 1);
            }
Ejemplo n.º 18
0
 /// <summary>
 /// Emits IL instructions that load actual parameters on the evaluation stack.
 /// </summary>
 /// <param name="node">Instance.</param>
 /// <param name="codeGenerator">Code generator.</param>
 /// <param name="routine">PHP method being called.</param>
 /// <remarks>
 /// <para>
 /// The function has mandatory and optional formal arguments.
 /// Mandatory arguments are those formal arguments which are not preceded by
 /// any formal argument with default value. The others are optional.
 /// If a formal argument without default value is declared beyond the last mandatory argument
 /// it is treated as optional one by the caller. The callee checks this and throws warning.
 /// </para>
 /// Missing arguments handling:
 /// <list type="bullet">
 ///   <item>missing mandatory argument - WARNING; LOAD(null);</item>
 ///   <item>missing optional argument - LOAD(Arg.Default);</item>
 ///   <item>superfluous arguments are ignored</item>
 /// </list>
 /// </remarks>
 public void EmitLoadOnEvalStack(CallSignature /*!*/ node, CodeGenerator /*!*/ codeGenerator, PhpRoutine /*!*/ routine)
 {
     EmitLoadTypeArgsOnEvalStack(node, codeGenerator, routine);
     EmitLoadArgsOnEvalStack(node, codeGenerator, routine);
 }
Ejemplo n.º 19
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));
                }
            }
        }
Ejemplo n.º 20
0
 public static void EmitLoadOnEvalStack(this CallSignature /*!*/ node, CodeGenerator /*!*/ codeGenerator, PhpRoutine /*!*/ routine)
 {
     node.NodeCompiler <ICallSignatureCompiler>().EmitLoadOnEvalStack(node, codeGenerator, routine);
 }
Ejemplo n.º 21
0
        /// <summary>
        /// This method binds rules for PhpMethod
        /// </summary>
        private void InvokePhpMethod(DynamicMetaObject /*!*/ target, DynamicMetaObject[] /*!!*/ args, /*object targetObj,*/ PhpRoutine /*!*/ routine, out BindingRestrictions restrictions, out Expression invokeMethodExpr)
        {
            Debug.Assert(target != null && target.Value != null);
            Debug.Assert(!(target.Value is IClrValue), "PhpRoutine should not be declared on CLR value type!");

            /*if (target.Value is PhpObject)
             * {
             *  // Restriction: typeof(target) == |target.TypeDesc.RealType|
             *  var targetPhpObj = (PhpObject)target.Value;
             *  Debug.Assert(targetPhpObj.TypeDesc.RealType == target.LimitType);
             *  Debug.Assert(target.Value.GetType() == target.LimitType);
             *  restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, targetPhpObj.TypeDesc.RealType);
             * }
             * else*/
            Debug.Assert(typeof(ClrObject).IsSealed);   // just to ensure following condition is correct
            if (target.Value.GetType() == typeof(ClrObject))
            {
                target       = new ClrDynamicMetaObject(target); // unwrap the real object, get restrictions
                restrictions = target.Restrictions;
            }
            else
            {
                Debug.Assert(target.Value.GetType() == target.LimitType);   // just for sure
                Debug.Assert(!(target.Value is PhpObject) || ((PhpObject)target.Value).TypeDesc.RealType == target.LimitType);

                restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);
            }

            BindingRestrictions argumentsRestrictions;

            Expression[] arguments;

            if (routine.Name != PHP.Core.Reflection.DObject.SpecialMethodNames.Call)
            {
                args = GetArgumentsRange(args, 0, RealMethodArgumentCount);// This can't be done when _call method is invoked

                //Check if method has ArgAware attribute
                if ((routine.Properties & RoutineProperties.IsArgsAware) != 0 ||
                    routine.IsStatic)// this is because of hack in PHP.Library.XML library static methods that can be also called like instance methods
                {
                    DynamicMetaObject scriptContext = args[0];

                    //Select arguments without scriptContext
                    DynamicMetaObject[] realArgs = GetArgumentsRange(args, 1, RealMethodArgumentCount - 1);

                    InvokeArgLess(target, scriptContext, routine.RoutineDesc, realArgs, out argumentsRestrictions, out invokeMethodExpr);
                    restrictions = restrictions.Merge(argumentsRestrictions);
                    return;
                }

                arguments    = routine.PrepareArguments(args, _genericParamsCount, _paramsCount, out argumentsRestrictions);
                restrictions = restrictions.Merge(argumentsRestrictions);
            }
            else
            {
                arguments = BinderHelper.PackToExpressions(args);
            }

            //((PhpObject)target))
            var realObjEx = Expression.Convert(target.Expression, routine.ArgFullInfo.DeclaringType);//targetObj.TypeDesc.RealType);

            //ArgFull( ((PhpObject)target), ScriptContext, args, ... )
            invokeMethodExpr = Expression.Call(BinderHelper.WrapInstanceMethodCall(routine.ArgFullInfo),
                                               BinderHelper.CombineArguments(realObjEx, arguments));

            invokeMethodExpr = ReturnArgumentHelpers.ReturnValueConversion(routine.ArgFullInfo, invokeMethodExpr);

            invokeMethodExpr = HandleResult(invokeMethodExpr, routine.ArgFullInfo.ReturnType, false);
        }