Exemple #1
0
        /// <summary>
        /// Generates Expression that throws a 'Protected method called' or 'Private method called' <see cref="PhpException"/>.
        /// </summary>
        /// <param name="method">The <see cref="DRoutineDesc"/>.</param>
        /// <param name="callerContext">The caller that was passed to method lookup or <B>null</B>
        /// if it should be determined by this method (by tracing the stack).</param>
        /// <remarks>
        /// This method is intended to be called after <see cref="DTypeDesc.GetMethod"/> has returned
        /// <see cref="GetMemberResult.BadVisibility"/> while performing a method lookup.
        /// </remarks>
        public static Expression/*!*/ ThrowVisibilityError(DRoutineDesc/*!*/ method, DTypeDesc/*!*/ callerContext)
        {
            if (method.IsProtected)
            {
                return ThrowError("protected_method_called",
                                  method.DeclaringType.MakeFullName(),
                                  method.MakeFullName(),
                                  callerContext == null ? String.Empty : callerContext.MakeFullName());
            }
            else if (method.IsPrivate)
            {
                return ThrowError("private_method_called",
                                  method.DeclaringType.MakeFullName(),
                                  method.MakeFullName(),
                                  callerContext == null ? String.Empty : callerContext.MakeFullName());
            }

            throw new NotImplementedException();
        }
        public virtual object __construct(ScriptContext context, object @class, object methodname)
        {
            string methodnameStr = PhpVariable.AsString(methodname);

            this.dtype = null;
            this.method = null;

            DObject dobj;
            
            if ((dobj = (@class as DObject)) != null)
            {
                this.dtype = dobj.TypeDesc;
            }
            else
            {
                var str = PhpVariable.AsString(@class);
                if (str != null)
                    this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload);

                if (this.dtype == null)
                {
                    PhpException.Throw(PhpError.Error, string.Format("Class {0} does not exist", str));
                    return false;
                }
            }
            
            if (this.dtype.GetMethod(new Name(methodnameStr), dtype, out this.method) == GetMemberResult.NotFound)
            {
                PhpException.Throw(PhpError.Error, string.Format("Method {0}::{1}() does not exist", dtype.MakeFullName(), methodnameStr));  
                return false;
            }

            return null;
        }
        public virtual object __construct(ScriptContext context, object arg)
        {
            string name = PhpVariable.AsString(arg);
            if (!string.IsNullOrEmpty(name))
            {
                routine = context.ResolveFunction(name, null, false);
            }
            else
            {
                PhpException.InvalidArgument("arg");
            }

            if (routine == null)
                PhpException.Throw(PhpError.Error, string.Format("Function {0}() does not exist", name));
            
            return null;
        }
Exemple #4
0
		/// <summary>
		/// Used by the reflection.
		/// </summary>
		public PhpRoutine(DRoutineDesc/*!*/ functionDesc)
			: base(functionDesc)
		{
			this.signature = null; // to be written up
			this.builder = null; // unused
		}
Exemple #5
0
		/// <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);
		}
Exemple #6
0
		/// <summary>
		/// Used by the compiler and the reflector.
		/// </summary>
		public KnownRoutine(DRoutineDesc/*!*/ routineDesc)
			: base(routineDesc)
		{
		}
Exemple #7
0
        /// <summary>
        /// Creates bounded PHP instance method callback. Used when we already know the routine.
        /// </summary>
        /// <param name="instance">The target PHP object.</param>
        /// <param name="routine">The target PHP method.</param>
        internal PhpCallback(DObject instance, DRoutineDesc routine)
        {
            Debug.Assert(instance != null);
            Debug.Assert(routine != null);

            this.instance = instance;
            this.targetName = routine.Member.FullName;
            this.state = State.Bound;
            this.routineDesc = routine;
            this.lateStaticBindType = instance.TypeDesc;
        }
Exemple #8
0
		/// <summary>
		/// Attempts to bind this callback to its target.
		/// </summary>
		/// <param name="quiet"><B>true</B> of no errors should be thrown, <B>false</B> otherwise.</param>
		/// <param name="nameContext">Current <see cref="NamingContext"/> for function and class name resolution.</param>
		/// <param name="caller">Current class context or a <see cref="UnknownTypeDesc"/> if the class context
		/// should be determined ad-hoc.</param>
		/// <returns><B>True</B> if the callback was successfully bound, <B>false</B> if an error occured.</returns>
		public bool Bind(bool quiet, DTypeDesc caller, NamingContext nameContext)
		{
			if (IsInvalid) return false;

			switch (state)
			{
				case State.UnboundFunction:
					{
						if (context == null) context = ScriptContext.CurrentContext;

						routineDesc = context.ResolveFunction(targetName, nameContext, quiet);
						if (routineDesc == null) return false;

						state = State.Bound;
						return true;
					}

				case State.UnboundStaticMethod:
					{
						if (context == null) context = ScriptContext.CurrentContext;

                        if (caller != null && caller.IsUnknown) callingContext = PhpStackTrace.GetClassContext();
                        else callingContext = caller;

						// try to find the CLR method

						// find the class according to className
						ResolveTypeFlags flags = ResolveTypeFlags.UseAutoload;
						if (!quiet) flags |= ResolveTypeFlags.ThrowErrors;

						DTypeDesc type = context.ResolveType(className, nameContext, callingContext, null, flags);
						if (type == null) return false;

						// find the method
                        bool is_caller_method;
                        lateStaticBindType = type;
						routineDesc = Operators.GetStaticMethodDesc(type, targetName,
                            ref instance, callingContext, context, quiet, false, out is_caller_method);

						if (routineDesc == null) return false;

						if (instance != null) dummyInstance = true;
                        state = is_caller_method ? State.BoundToCaller : State.Bound;
						return true;
					}

				case State.UnboundInstanceMethod:
					{
                        if (caller != null && caller.IsUnknown) callingContext = PhpStackTrace.GetClassContext();
                        else callingContext = caller;

						// ask the instance for a handle to the method
						bool is_caller_method;
						routineDesc = instance.GetMethodDesc(targetName, callingContext, quiet, out is_caller_method);
						if (routineDesc == null) return false;

						state = (is_caller_method ? State.BoundToCaller : State.Bound);
						return true;
					}
			}
			return true;
		}
Exemple #9
0
		public PhpCallback(RoutineDelegate functionDelegate, ScriptContext context)
		{
			// create a new DRoutineDesc based on the passed delegate
			routineDesc = new PhpRoutineDesc(PhpMemberAttributes.Static | PhpMemberAttributes.NamespacePrivate, functionDelegate, false);

			this.context = context;
			this.state = State.Bound;
		}
Exemple #10
0
		/// <summary>
		/// Creates a callback bound to the specified PHP method represented by a <see cref="DRoutineDesc"/>.
		/// </summary>
		/// <param name="instance">The target PHP object.</param>
		/// <param name="handle">The handle of the target PHP method.</param>
		/// <param name="context">The script context to call the method with.</param>
		public PhpCallback(DObject instance, DRoutineDesc handle, ScriptContext context)
		{
			if (handle == null) throw new ArgumentNullException("handle");
            if (!handle.IsStatic)
            {
				if (instance == null) throw new ArgumentNullException("instance");
				this.instance = instance;
			}

			this.context = context;
			this.routineDesc = handle;
			this.state = State.Bound;

            if (instance != null)
                this.lateStaticBindType = instance.TypeDesc;
		}
        private void InvokeCallMethod(DynamicMetaObject target,
            DynamicMetaObject/*!*/[] args,
            DObject/*!*/ obj,
            DRoutineDesc/*!*/ method,
            out BindingRestrictions restrictions,
            out Expression invokeMethodExpr)
        {
            var insideCaller = Expression.Property(
                                        Expression.Convert(target.Expression, Types.DObject[0]),
                                         Properties.DObject_InsideCaller);

            if (argsArrayVariable == null)
                argsArrayVariable = Expression.Parameter(Types.PhpArray[0], "args");

            if (retValVariable == null)
                retValVariable = Expression.Parameter(Types.Object[0], "retVal");

            ParameterExpression[] vars = new ParameterExpression[] { argsArrayVariable, retValVariable };

            // Just select real method arguments without ScriptContext and generic type arguments
            var justParams = BinderHelper.PackToExpressions(args, 1 + _genericParamsCount, _paramsCount);

            // Expression which calls ((PhpArray)argArray).add method on each real method argument.
            var initArgsArray = Array.ConvertAll<Expression, Expression>(justParams, (x) => Expression.Call(argsArrayVariable, Methods.PhpHashtable_Add, x));

            // Argfull __call signature: (ScriptContext, object, object)->object
            var callerMethodArgs = new DynamicMetaObject[3] {   args[0], 
                                                                new DynamicMetaObject(Expression.Constant(ActualMethodName),BindingRestrictions.Empty),
                                                                new DynamicMetaObject(argsArrayVariable, BindingRestrictions.Empty) };
            // what if method.PhpRoutine is null 
            InvokePhpMethod(target, callerMethodArgs, /*(PhpObject)target.Value, */method.PhpRoutine, out restrictions, out invokeMethodExpr);


            //Expression:
            // if (target.insideCaller)
            //      throw new UndefinedMethodException();
            //
            // args = new PhpArray(paramsCount, 0);
            //
            // args.Add(arg0);
            // .
            // .
            // args.Add(paramsCount);
            //
            // target.insideCaller = true;
            // try
            // {
            //     ret_val = target.__call( scriptContext, methodName, args);
            // }
            // finally
            // {
            //     target.insideCaller = false;
            // }
            // return ret_val;
            //
            invokeMethodExpr = Expression.Block(
                vars,//local variables
                Expression.IfThen(Expression.Property(
                                        Expression.Convert(target.Expression, Types.DObject[0]),
                                        Properties.DObject_InsideCaller),
                                  Expression.Call(Methods.PhpException.UndefinedMethodCalled, Expression.Constant(obj.TypeName), Expression.Constant(ActualMethodName))),

                Expression.Assign(
                                argsArrayVariable,
                                Expression.New(Constructors.PhpArray.Int32_Int32,
                                            Expression.Constant(_paramsCount),
                                            Expression.Constant(0))),

                                ((initArgsArray.Length == 0) ? (Expression)Expression.Empty() : Expression.Block(initArgsArray)),

                                Expression.Assign(insideCaller,
                                                Expression.Constant(true)),
                                Expression.TryFinally(
                //__call(caller,args)
                                    Expression.Assign(retValVariable, invokeMethodExpr),
                //Finally part:
                                    Expression.Assign(insideCaller,
                                                        Expression.Constant(false))
                                    ),
                                 HandleResult(retValVariable, method.PhpRoutine.ArgFullInfo.ReturnType, false));
        }
        private void InvokeArgLess(DynamicMetaObject target, DynamicMetaObject scriptContext, DRoutineDesc method, DynamicMetaObject[] args, out BindingRestrictions restrictions, out Expression invokeMethodExpr)
        {
            int argsWithoutScriptContext = RealMethodArgumentCount - 1;

            System.Reflection.MethodInfo miAddFrame = Methods.PhpStack.AddFrame.Overload(argsWithoutScriptContext);

            Expression[] argsExpr = null;
            if (miAddFrame == Methods.PhpStack.AddFrame.N)
            {
                //Create array of arguments
                argsExpr = new Expression[1];
                argsExpr[0] = Expression.NewArrayInit(Types.Object[0], BinderHelper.PackToExpressions(args, 0, argsWithoutScriptContext));
            }
            else
            {
                //call overload with < N arguments
                //argsExpr = new Expression[argsWithoutScriptContext];
                argsExpr = BinderHelper.PackToExpressions(args, 0, argsWithoutScriptContext);
            }

            var stack = Expression.Field(scriptContext.Expression,
                                            Fields.ScriptContext_Stack);

            // scriptContext.PhpStack
            // PhpStack.Add( args )
            // call argless stub
            invokeMethodExpr = Expression.Block(_returnType,
                                    Expression.Call(
                                        stack,
                                        miAddFrame, argsExpr),
                                    Expression.Assign(
                                        Expression.Field(stack, Fields.PhpStack_AllowProtectedCall),
                                        Expression.Constant(true, Types.Bool[0])),
                                    HandleResult(
                                        Expression.Call(method.ArglessStubMethod,
                                            target.Expression,
                                            stack),
                                        method.ArglessStubMethod.ReturnType));

            restrictions = target.Restrictions;
        }
        private void InvokeClrMethod(DynamicMetaObject target, DynamicMetaObject/*!*/[] args, DRoutineDesc method, out BindingRestrictions restrictions, out Expression invokeMethodExpr)
        {
            DynamicMetaObject scriptContext = args[0];

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


#if DLR_OVERLOAD_RESOLUTION

            // Convert arguments
            DynamicMetaObject[] realArgsConverted = Array.ConvertAll<DynamicMetaObject, DynamicMetaObject>(realArgs, (x) =>
            {
                return x.ToPhpDynamicMetaObject();

            });

            //DLR overload resolution
            DynamicMetaObject res = PhpBinder.Instance.CallClrMethod(method.ClrMethod, target, realArgsConverted);
            restriction = res.Restriction;
            invokeMethodExpr = res.Rule;

#else
            // Old overload resolution
            // TODO: in case of zero-parameters, we can call via ArgFull
            InvokeArgLess(target, scriptContext, method, realArgs, out restrictions, out invokeMethodExpr);
#endif
        }
        public virtual object __construct(ScriptContext context, object @class, object methodname)
        {
            string methodnameStr = PhpVariable.AsString(methodname);

            if (@class == null || string.IsNullOrEmpty(methodnameStr))
                return false;

            this.dtype = null;
            this.method = null;

            DObject dobj;
            string str;

            if ((dobj = (@class as DObject)) != null)
            {
                this.dtype = dobj.TypeDesc;
            }
            else if ((str = PhpVariable.AsString(@class)) != null)
            {
                this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload);
            }

            if (this.dtype == null)
                return false;

            if (this.dtype.GetMethod(new Name(methodnameStr), dtype, out this.method) == GetMemberResult.NotFound)
                return false;

            return null;
        }
        public virtual object __construct(ScriptContext context, object arg)
        {
            string name = PhpVariable.AsString(arg);
            if (!string.IsNullOrEmpty(name))
            {
                routine = context.ResolveFunction(name, null, false);
            }
            else
            {
                PhpException.InvalidArgument("arg");
            }

            return null;
        }