Beispiel #1
0
 private static void AddDependentType(PhpTypeDesc /*!*/ selfType, List <KeyValuePair <string, DTypeDesc> > /*!*/ dependentTypes, DTypeDesc dependentType)
 {
     if (dependentType != null && dependentType is PhpTypeDesc && !IsSameCompilationUnit(selfType, dependentType))
     {
         dependentTypes.Add(new KeyValuePair <string, DTypeDesc>(dependentType.MakeFullName(), dependentType));
     }
 }
Beispiel #2
0
        public static string GetCalledClass(DTypeDesc caller)
        {
            if (caller == null || caller.IsUnknown)
            {
                return(null);
            }

            return(caller.MakeFullName());
        }
Beispiel #3
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();
        }
Beispiel #4
0
        public static string GetParentClass(DTypeDesc caller, object classNameOrObject)
        {
            ScriptContext context = ScriptContext.CurrentContext;

            DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true);

            if (type == null || type.IsInterface)
            {
                return(null);
            }

            DTypeDesc parent_type = type.Base;

            return(parent_type == null ? null : parent_type.MakeFullName());
        }
Beispiel #5
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();
        }
Beispiel #6
0
        public static PhpArray GetClassParents(DTypeDesc caller, object classNameOrObject, bool useAutoload)
        {
            ScriptContext context = ScriptContext.CurrentContext;

            DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, useAutoload);

            if (type == null || type.IsInterface)
            {
                return(null);
            }

            PhpArray result = new PhpArray();

            while ((type = type.Base) != null)
            {
                string class_name = type.MakeFullName();
                result.Add(class_name, class_name);
            }

            return(result);
        }
Beispiel #7
0
        public static void UnsetStaticProperty(DTypeDesc type, object propertyName, DTypeDesc caller, ScriptContext context)
        {
            // convert propertyName to string
            string name = (propertyName == null ? String.Empty : Convert.ObjectToString(propertyName));

            // throw the error
            PhpException.StaticPropertyUnset(type.MakeFullName(), name);
        }
Beispiel #8
0
        /// <summary>
        /// Gets the <see cref="DPropertyDesc"/> of a static property of a class.
        /// </summary>
        /// <param name="type">The class to get the property of.</param>
        /// <param name="propertyName">The property name.</param>
        /// <param name="caller"><see cref="DTypeDesc"/> of the object that request the retrieval.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <param name="quiet">If <B>true</B>, the &quot;property not found&quot; exception should not be thrown.</param>
        /// <returns>The <see cref="DPropertyDesc"/> representing the static property or <B>null</B> if an error occurs.</returns>
        /// <exception cref="PhpException">The property denoted by <paramref name="propertyName"/> was not found. (Error)</exception>
        /// <exception cref="PhpException">The property is inaccessible due to its protected or private visibility level (Error).
        /// </exception>
        internal static DPropertyDesc GetStaticPropertyDesc(DTypeDesc type, object propertyName, DTypeDesc caller,
            ScriptContext context, bool quiet)
        {
            if (type == null) return null;

            // convert propertyName to string
            string name = (propertyName == null ? String.Empty : Convert.ObjectToString(propertyName));

            // find the property
            DPropertyDesc property;
            switch (type.GetProperty(new VariableName(name), caller, out property))
            {
                case GetMemberResult.NotFound:
                    {
                        if (!quiet) PhpException.UndeclaredStaticProperty(type.MakeFullName(), name);
                        return null;
                    }

                case GetMemberResult.BadVisibility:
                    {
                        if (!quiet)
                        {
                            PhpException.PropertyNotAccessible(
                                property.DeclaringType.MakeFullName(),
                                name,
                                (caller == null ? String.Empty : caller.MakeFullName()),
                                property.IsProtected);
                        }
                        return null;
                    }

                case GetMemberResult.OK:
                    {
                        if (!property.IsStatic) goto case GetMemberResult.NotFound;
                        break;
                    }
            }

            // make sure that the property has been initialized for this request
            property.EnsureInitialized(context);

            return property;
        }
Beispiel #9
0
        public static object GetClassConstant(DTypeDesc type, string constantName, DTypeDesc caller, ScriptContext context)
        {
            if (type == null) return null;

            // lookup the constant desc
            DConstantDesc constant;
            switch (type.GetConstant(new VariableName(constantName), caller, out constant))
            {
                case GetMemberResult.NotFound:
                    {
                        PhpException.Throw(PhpError.Error, CoreResources.GetString("undefined_class_constant",
                            type.MakeFullName(), constantName));
                        return null;
                    }

                case GetMemberResult.BadVisibility:
                    {
                        PhpException.ConstantNotAccessible(
                            constant.DeclaringType.MakeFullName(),
                            constantName,
                            (caller == null ? String.Empty : caller.MakeFullName()),
                            constant.IsProtected);
                        return null;
                    }
            }

            // make sure that the constant has been initialized for this request
            return PhpVariable.Dereference(constant.GetValue(context));
        }
Beispiel #10
0
		public static string GetCalledClass(DTypeDesc caller)
		{
            if (caller == null || caller.IsUnknown)
                return null;

            return caller.MakeFullName();
		}
Beispiel #11
0
        /// <summary>
        /// Specifies dynamic behavior for set operation for a constant
        /// </summary>
        public override bool TrySetMember(
            SetMemberBinder binder,
            Object value
            )
        {
            if (type != null)
            {
                PhpException.Throw(PhpError.Error, String.Format(PHP.Core.Localizations.Strings.constant_redefined, type.MakeFullName() + Name.ClassMemberSeparator + binder.Name));
                return(true);
            }

            Context.DefineConstant(GetFullName(binder.Name), value);
            return(true);
        }
Beispiel #12
0
        private static void ReportErrorMakingInstantiation(DTypeDesc.MakeGenericArgumentsResult/*!*/ error,
            DTypeDesc/*!*/ genericType, DTypeDesc argument, GenericParameterDesc/*!*/ parameter)
        {
            switch (error)
            {
                case DTypeDesc.MakeGenericArgumentsResult.IncompatibleConstraint:
                    PhpException.Throw(PhpError.Error, CoreResources.GetString("incompatible_type_parameter_constraints_type",
                        argument.MakeFullName(), parameter.RealType.GenericParameterPosition, parameter.RealType.Name));
                    break;

                case DTypeDesc.MakeGenericArgumentsResult.MissingArgument:
                    PhpException.Throw(PhpError.Error, CoreResources.GetString("missing_type_argument_in_type_use",
                        genericType.MakeFullName(), parameter.RealType.GenericParameterPosition, parameter.RealType.Name));
                    break;

                case DTypeDesc.MakeGenericArgumentsResult.TooManyArguments:
                    PhpException.Throw(PhpError.Warning, CoreResources.GetString("too_many_type_arguments_in_type_use",
                        genericType.MakeFullName(), genericType.GenericParameters.Length));
                    break;
            }
        }
Beispiel #13
0
        public static string GetGenericArg(int index)
        {
            DTypeDesc type_desc = ScriptContext.CurrentContext.Stack.GetTypeArgument(index);

            return((type_desc != null) ? type_desc.MakeFullName() : null);
        }
Beispiel #14
0
        private DynamicMetaObject /*!*/ FallbackInvokeMember(DynamicMetaObject target /*!*/, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            // determine run time values and additional restrictions:
            DTypeDesc           classContext = this._classContext;
            string              fieldName    = this._fieldName;
            BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); //target.Restrictions;

            int currentArg = 0;

            if (!ClassContextIsKnown)
            {
                Debug.Assert(args.Length > currentArg, "Not enough arguments!");
                Debug.Assert(args[currentArg].Value == null || Types.DTypeDesc[0].IsAssignableFrom(args[currentArg].LimitType), "Wrong class context type!");
                classContext = (DTypeDesc)args[currentArg].Value;
                Debug.Assert(classContext == null || !classContext.IsUnknown, "Class context should be known at run time!");

                restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(args[currentArg].Expression, classContext));

                currentArg++;
            }
            if (IsIndirect)
            {
                Debug.Assert(args.Length > currentArg, "Not enough arguments!");
                Debug.Assert(Types.String[0].IsAssignableFrom(args[currentArg].LimitType), "Wrong field name type!");
                fieldName = (string)args[currentArg].Value;

                restrictions = restrictions.Merge(
                    BindingRestrictions.GetExpressionRestriction(
                        Expression.Equal(
                            args[currentArg].Expression,
                            Expression.Constant(fieldName, Types.String[0]))));

                currentArg++;
            }

            //
            ////Debug.Assert(!(var is PhpReference) && name != null);
            Debug.Assert(target.HasValue && target.LimitType != Types.PhpReference[0], "Target should not be PhpReference!");

            ////if (ReferenceEquals(obj, ScriptContext.SetterChainSingletonObject))
            ////{
            ////    ScriptContext.CurrentContext.AbortSetterChain(false);
            ////    return new PhpReference();
            ////}
            if (WantReference && ReferenceEquals(target.Value, ScriptContext.SetterChainSingletonObject))
            {
                // GetObjectPropertyRef:
                Func <PhpReference> abortSetterChain = () =>
                {
                    ScriptContext.CurrentContext.AbortSetterChain(false);
                    return(new PhpReference());
                };

                return(new DynamicMetaObject(
                           Expression.Call(abortSetterChain.Method),
                           BindingRestrictions.GetInstanceRestriction(target.Expression, ScriptContext.SetterChainSingletonObject)
                           ));
            }

            DObject obj;

            ////// a property of a DObject:
            if ((obj = target.Value as DObject) != null)
            {
                if (obj is ClrObject /*|| obj is IClrValue // IClrValue -> ClrValue<T> -> already in restriction */)
                {
                    // ((DObject)target).RealType == <obj>.RealType
                    restrictions = restrictions.Merge(
                        BindingRestrictions.GetInstanceRestriction(
                            Expression.Property(Expression.Convert(target.Expression, Types.DObject[0]), Properties.DObject_RealType),
                            obj.RealType));
                }

                ////    return GetObjectProperty(obj, name, caller, quiet);
                DPropertyDesc   property;
                GetMemberResult result = obj.TypeDesc.GetInstanceProperty(new VariableName(fieldName), classContext, out property);

                switch (result)
                {
                case GetMemberResult.OK:
                    ////object value = property.Get(this);
                    ////PhpReference reference = value as PhpReference;

                    if (property.Member is PhpField || property.Member is PhpVisibleProperty)
                    {
                        var          realType     = property.DeclaringType.RealType;
                        FieldInfo    realField    = (property.Member is PhpField) ? property.PhpField.RealField : null;
                        PropertyInfo realProperty = (property.Member is PhpVisibleProperty) ? ((PhpVisibleProperty)property.Member).RealProperty : null;

                        Debug.Assert(realField != null ^ realProperty != null);

                        MemberExpression getter = null;

                        if (realField != null)
                        {
                            getter = Expression.Field(Expression.Convert(target.Expression, realType), realField);
                        }
                        else if (realProperty != null)
                        {
                            getter = Expression.Property(Expression.Convert(target.Expression, realType), realProperty);
                        }


                        if (Types.PhpReference[0].IsAssignableFrom(getter.Type))
                        {
                            var reference  = Expression.Variable(Types.PhpReference[0]);
                            var assignment = Expression.Assign(reference, getter);

                            if (WantReference)
                            {
                                ////value = property.Get(this);
                                ////reference = value as PhpReference;

                                var returnLabel = Expression.Label(this._returnType);

                                ////if (reference != null && reference.IsSet)
                                ////{
                                ////    reference.IsAliased = true;
                                ////    return reference;
                                ////}

                                var isset = Expression.IfThen(
                                    Expression.Property(assignment, Properties.PhpReference_IsSet),
                                    Expression.Block(
                                        Expression.Assign(Expression.Property(reference, Properties.PhpReference_IsAliased), Expression.Constant(true)),
                                        Expression.Return(returnLabel, reference)));

                                ////// the CT property has been unset -> try to invoke __get
                                ////PhpReference get_ref = InvokeGetterRef(name, caller, out getter_exists);
                                ////if (getter_exists) return (get_ref == null ? new PhpReference() : get_ref);

                                ////if (reference == null)
                                ////{
                                ////    reference = new PhpReference(value);
                                ////    property.Set(this, reference);
                                ////}
                                ////else
                                ////{
                                ////    reference.IsAliased = true;
                                ////    reference.IsSet = true;
                                ////}
                                Func <DObject, string, DTypeDesc, PhpReference, PhpReference> notsetOperation = (self, name, caller, refrnc) =>
                                {
                                    bool getter_exists;
                                    // the CT property has been unset -> try to invoke __get
                                    PhpReference get_ref = self.InvokeGetterRef(name, caller, out getter_exists);
                                    if (getter_exists)
                                    {
                                        return(get_ref ?? new PhpReference());
                                    }

                                    Debug.Assert(refrnc != null);

                                    refrnc.IsAliased = true;
                                    refrnc.IsSet     = true;

                                    return(refrnc);
                                };

                                ////return reference;

                                return(new DynamicMetaObject(
                                           Expression.Block(this._returnType,
                                                            new[] { reference },
                                                            new Expression[] {
                                    isset,
                                    Expression.Label(returnLabel,
                                                     Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]), reference))
                                }),
                                           restrictions));
                            }
                            else
                            {
                                ////if (reference != null && !reference.IsSet)
                                ////{
                                ////    // the property is CT but has been unset
                                ////    if (issetSemantics)
                                ////    {
                                ////        bool handled;
                                ////        return PropertyIssetHandler(name, caller, out handled);
                                ////    }
                                ////    else return GetRuntimeField(name, caller);
                                ////}
                                ////else return value;


                                Func <DObject, string, DTypeDesc, object> notsetOperation;
                                if (_issetSemantics)
                                {
                                    notsetOperation = (self, name, caller) =>
                                    {
                                        return(PhpVariable.Dereference(self.GetRuntimeField(name, caller)));
                                    }
                                }
                                ;
                                else
                                {
                                    notsetOperation = (self, name, caller) =>
                                    {
                                        bool handled;
                                        return(PhpVariable.Dereference(self.PropertyIssetHandler(name, caller, out handled)));
                                    }
                                };
                                var value =
                                    Expression.Block(this._returnType,
                                                     new[] { reference },
                                                     Expression.Condition(
                                                         Expression.Property(assignment, Properties.PhpReference_IsSet),
                                                         Expression.Field(reference, Fields.PhpReference_Value),
                                                         Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]))
                                                         ));

                                return(new DynamicMetaObject(value, restrictions));
                            }
                        }
                        else
                        {
                            if (WantReference)
                            {
                                return(new DynamicMetaObject(
                                           Expression.New(Constructors.PhpReference_Object, Expression.Convert(getter, Types.Object[0])),
                                           restrictions));
                            }
                            else
                            {
                                return(new DynamicMetaObject(
                                           Expression.Call(Methods.PhpVariable.Dereference, Expression.Convert(getter, Types.Object[0])),
                                           restrictions));
                            }
                        }
                    }
                    else if (property.Member is ClrProperty)
                    {
                        var realType     = property.DeclaringType.RealType;
                        var realProperty = property.ClrProperty.RealProperty;

                        // (target.{RealObject|realValue}).<realProperty>
                        Expression value = Expression.Convert(
                            BinderHelper.ClrObjectWrapDynamic(
                                Expression.Property(
                                    BinderHelper.ClrRealObject(target, realType),
                                    realProperty)),
                            Types.Object[0]);

                        if (WantReference)
                        {
                            value = BinderHelper.MakePhpReference(value);
                        }

                        return(new DynamicMetaObject(value, restrictions));
                    }
                    else if (property.Member is ClrField)
                    {
                        var realType  = property.DeclaringType.RealType;
                        var realField = property.ClrField.FieldInfo;

                        // (target.{RealObject|realValue}).<realField>
                        Expression value = Expression.Convert(
                            BinderHelper.ClrObjectWrapDynamic(
                                Expression.Field(
                                    BinderHelper.ClrRealObject(target, realType),
                                    realField)),
                            Types.Object[0]);

                        if (WantReference)
                        {
                            value = BinderHelper.MakePhpReference(value);
                        }

                        return(new DynamicMetaObject(value, restrictions));
                    }
                    else if (property.Member is ClrEvent)
                    {
                        var clrEvent = (ClrEvent)property.Member;
                        var realType = property.DeclaringType.RealType;

                        // emit stub that Wraps event as [ ClrEventObject<handlerType>.Wrap(<SC>, <event name>, <addMethod>, <removeMethod>) ]
                        var stub = new System.Reflection.Emit.DynamicMethod(
                            string.Format("event<{0}>", fieldName),
                            Types.DObject[0], new[] { realType }, realType);
                        var il = new ILEmitter(stub);
                        clrEvent.EmitGetEventObject(
                            il,
                            new Place(null, Properties.ScriptContext_CurrentContext),
                            new IndexedPlace(PlaceHolder.Argument, 0),
                            false);
                        il.Emit(System.Reflection.Emit.OpCodes.Ret);

                        Expression value = Expression.Call(stub, BinderHelper.ClrRealObject(target, realType));
                        if (WantReference)
                        {
                            value = BinderHelper.MakePhpReference(value);
                        }
                        return(new DynamicMetaObject(value, restrictions));
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                case GetMemberResult.NotFound:
                    if (WantReference)
                    {
                        Func <DObject, string, DTypeDesc, PhpReference> op = (self, name, caller) =>
                        {
                            PhpReference reference;
                            bool         getter_exists;

                            // search in RT fields
                            if (self.RuntimeFields != null && self.RuntimeFields.ContainsKey(name))
                            {
                                var namekey = new IntStringKey(name);
                                return(self.RuntimeFields.table._ensure_item_ref(ref namekey, self.RuntimeFields));
                            }

                            // property is not present -> try to invoke __get
                            reference = self.InvokeGetterRef(name, caller, out getter_exists);
                            if (getter_exists)
                            {
                                return((reference == null) ? new PhpReference() : reference);
                            }

                            // (no notice/warning/error thrown by PHP)

                            // add the field
                            reference = new PhpReference();
                            if (self.RuntimeFields == null)
                            {
                                self.RuntimeFields = new PhpArray();
                            }
                            self.RuntimeFields[name] = reference;

                            return(reference);
                        };

                        return(new DynamicMetaObject(
                                   Expression.Call(null, op.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0])),
                                   restrictions));
                    }
                    else
                    {
                        ////if (issetSemantics)
                        ////{
                        ////    OrderedHashtable<string>.Element element;
                        ////    if (RuntimeFields != null && (element = RuntimeFields.GetElement(name)) != null)
                        ////    {
                        ////        return element.Value;
                        ////    }
                        ////    else
                        ////    {
                        ////        bool handled;
                        ////        return PropertyIssetHandler(name, caller, out handled);
                        ////    }
                        ////}
                        ////else return GetRuntimeField(name, caller);

                        if (_issetSemantics)
                        {
                            Func <DObject, string, DTypeDesc, object> notsetOperation = (self, name, caller) =>
                            {
                                if (self.RuntimeFields != null)
                                {
                                    object value;
                                    if (self.RuntimeFields.TryGetValue(name, out value))
                                    {
                                        return(value);
                                    }
                                }

                                bool handled;
                                return(self.PropertyIssetHandler(name, caller, out handled));
                            };

                            return(new DynamicMetaObject(
                                       Expression.Call(Methods.PhpVariable.Dereference,
                                                       Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]))),
                                       restrictions));
                        }
                        else
                        {
                            return(new DynamicMetaObject(
                                       Expression.Call(
                                           Methods.PhpVariable.Dereference,
                                           Expression.Call(
                                               Expression.Convert(target.Expression, Types.DObject[0]),
                                               Methods.DObject_GetRuntimeField, Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]))),
                                       restrictions));
                        };
                    }

                case GetMemberResult.BadVisibility:
                {
                    ////PhpException.PropertyNotAccessible(
                    ////    property.DeclaringType.MakeFullName(),
                    ////    name.ToString(),
                    ////    (caller == null ? String.Empty : caller.MakeFullName()),
                    ////    property.IsProtected);

                    string stringResourceKey = property.IsProtected ? "protected_property_accessed" : "private_property_accessed";

                    return(new DynamicMetaObject(
                               Expression.Block(this._returnType,
                                                Expression.Call(null, Methods.PhpException.Throw,
                                                                Expression.Constant(PhpError.Error, Types.PhpError_String[0]),
                                                                Expression.Constant(CoreResources.GetString(stringResourceKey, property.DeclaringType.MakeFullName(), fieldName, (classContext == null ? String.Empty : classContext.MakeFullName())))),
                                                WantReference ? (Expression)Expression.New(Constructors.PhpReference_Void) : Expression.Constant(null)
                                                ),
                               restrictions));
                }
                }
            }

            ////// warnings:
            ////if (!quiet) // not in isset() operator only
            ////{
            if (!_issetSemantics)
            {
                ////    if (PhpVariable.IsEmpty(var))
                ////        // empty:
                ////        PhpException.Throw(PhpError.Notice, CoreResources.GetString("empty_used_as_object"));
                ////    else
                ////        // PhpArray, string, scalar type:
                ////        PhpException.VariableMisusedAsObject(var, false);

                Action <object> error = (var) =>
                {
                    if (PhpVariable.IsEmpty(var))
                    {
                        // empty:
                        PhpException.Throw(PhpError.Notice, CoreResources.GetString("empty_used_as_object"));
                    }
                    else
                    {
                        // PhpArray, string, scalar type:
                        PhpException.VariableMisusedAsObject(var, false);
                    }
                };

                return(new DynamicMetaObject(
                           Expression.Block(this._returnType,
                                            Expression.Call(error.Method, target.Expression),
                                            WantReference ? (Expression)Expression.New(Constructors.PhpReference_Void) : Expression.Constant(null)),
                           (target.HasValue && target.Value == null) ?
                           BindingRestrictions.GetInstanceRestriction(target.Expression, null) :
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            ////}

            ////// property does not exist
            ////return null;
            return(new DynamicMetaObject(
                       Expression.Constant(null),
                       (target.HasValue && target.Value == null) ?
                       BindingRestrictions.GetInstanceRestriction(target.Expression, null) :
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        /// <summary>
        /// Attemps to find a method desc according to a given class name and method name. Used when
        /// a non-virtual dispatch is about to be performed and when a <c>array(class, method)</c>
        /// callback is being bound.
        /// </summary>
        /// <param name="requestedType">The type whose method should be returned.</param>
        /// <param name="methodName">The method name.</param>
        /// <param name="self">Current <c>$this</c>. Will be set to an instance, on which the resulting
        /// CLR method should be invoked (<B>null</B> if the CLR method is static).</param>
        /// <param name="caller"><see cref="Type"/> of the object that request the lookup.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <param name="quiet">If <B>true</B>, no exceptions will be thrown if an error occurs.</param>
        /// <param name="removeFrame">If <B>true</B>, <see cref="PhpStack.RemoveFrame"/> will be called
        /// before throwing an exception.</param>
        /// <param name="isCallerMethod">Will be set to true, if required method was not found but __callStatic was.</param>
        /// <returns>The <see cref="DRoutineDesc"/> or <B>null</B> on error.</returns>
        internal static DRoutineDesc GetStaticMethodDesc(DTypeDesc requestedType, string methodName, ref DObject self,
            DTypeDesc caller, ScriptContext context, bool quiet, bool removeFrame, out bool isCallerMethod)
        {
            Debug.Assert(requestedType != null);

            isCallerMethod = false;

            DRoutineDesc method;
            GetMemberResult result = requestedType.GetMethod(new Name(methodName), caller, out method);

            if (result == GetMemberResult.NotFound)
            {
                // if not found, perform __callStatic or __call 'magic' method lookup
                Name callMethod = (self != null && requestedType.IsAssignableFrom(self.TypeDesc)) ?
                    Name.SpecialMethodNames.Call : Name.SpecialMethodNames.CallStatic;

                if ((result = requestedType.GetMethod(callMethod, caller, out method)) != GetMemberResult.NotFound)
                {
                    isCallerMethod = true;
                }
                else
                {
                    // there is no such method in the class
                    if (removeFrame) context.Stack.RemoveFrame();
                    if (!quiet) PhpException.UndefinedMethodCalled(requestedType.MakeFullName(), methodName);

                    return null;
                }
            }

            if (result == GetMemberResult.BadVisibility)
            {
                if (removeFrame) context.Stack.RemoveFrame();
                if (!quiet)
                {
                    PhpException.MethodNotAccessible(
                        method.DeclaringType.MakeFullName(),
                        method.MakeFullName(),
                        (caller == null ? String.Empty : caller.MakeFullName()),
                        method.IsProtected);
                }
                return null;
            }

            // check whether the method is abstract
            if (method.IsAbstract)
            {
                if (removeFrame) context.Stack.RemoveFrame();
                if (!quiet) PhpException.AbstractMethodCalled(method.DeclaringType.MakeFullName(), method.MakeFullName());

                return null;
            }

            if (method.IsStatic)
            {
                self = null;
            }
            else
            {
                // check whether self is of acceptable type
                if (self != null && !method.DeclaringType.RealType.IsInstanceOfType(self.RealObject)) self = null;


                /*
                // PHP allows for static invocations of instance method
				if (self == null &&
					(requestedType.IsAbstract || !(requestedType is PhpTypeDesc)) &&
					(method.DeclaringType.IsAbstract || !(method.DeclaringType is PhpTypeDesc)))
				{
					// calling instance methods declared in abstract classes statically through abstract classes
					// is unsupported -  passing null as 'this' to such instance method could result in
					// NullReferenceException even if the method does not touch $this
					if (removeFrame) context.Stack.RemoveFrame();
					if (!quiet)
					{
						PhpException.Throw(PhpError.Error, CoreResources.GetString("nonstatic_method_called_statically",
							method.DeclaringType.MakeFullName(), method.MakeFullName()));
					}
					return null;
				}

				if (self == null)
				{
                    if (!quiet && !context.Config.Variables.ZendEngineV1Compatible)
                    {
                        PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically",
                            method.DeclaringType.MakeFullName(), method.MakeFullName()));
                    }

					// create a dummy instance to be passed as 'this' to the instance method
					DTypeDesc dummy_type =
						(!requestedType.IsAbstract && requestedType is PhpTypeDesc) ? requestedType : method.DeclaringType;

					self = PhpFunctionUtils.InvokeConstructor(
                        dummy_type,
                        //Emit.Types.ScriptContext_Bool,
                        context, false);
				}*/


                //
                // The code above was commented and replaced with following.
                //
                // We can call instance method, and pass null as 'this', and expect
                // it can fail with NullReferenceException (even if the method does not touch $this).
                // 
                // Note this solution has no side effect as above - invoking constructor of dummy instance.
                //

                // !! self can be null !!

                if (self == null)
                {
                    if (!quiet /*&& !context.Config.Variables.ZendEngineV1Compatible*/)
                    {
                        PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically",
                            method.DeclaringType.MakeFullName(), method.MakeFullName()));
                    }
                }

            }

            return method;
        }
Beispiel #17
0
        public static object New(DTypeDesc type, DTypeDesc caller, ScriptContext context, NamingContext nameContext)
        {
            // error has been thrown by Convert.ObjectToTypeDesc or MakeGenericTypeInstantiation
            if (type == null)
            {
                context.Stack.RemoveFrame();
                return null;
            }

            // interfaces and abstract classes cannot be instantiated
            if (type.IsAbstract)
            {
                context.Stack.RemoveFrame();
                PhpException.CannotInstantiateType(type.MakeFullName(), type.IsInterface);
                return null;
            }

            return type.New(context.Stack, caller, nameContext);
        }
Beispiel #18
0
 private static void AddDependentType(PhpTypeDesc/*!*/selfType, List<KeyValuePair<string, DTypeDesc>>/*!*/dependentTypes, DTypeDesc dependentType)
 {
     if (dependentType != null && dependentType is PhpTypeDesc && dependentType.RealType.Module != selfType.RealType.Module)// base type if from different module (external dependency)
         dependentTypes.Add(new KeyValuePair<string, DTypeDesc>(dependentType.MakeFullName(), dependentType));
 }
Beispiel #19
0
        public static string GetFullyQualifiedName(DTypeDesc type)
        {
            if (type == null)
                return string.Empty;

            return type.MakeFullName();
        }
Beispiel #20
0
 private static void AddDependentType(PhpTypeDesc/*!*/selfType, List<KeyValuePair<string, DTypeDesc>>/*!*/dependentTypes, DTypeDesc dependentType)
 {
     if (dependentType != null && dependentType is PhpTypeDesc && !IsSameCompilationUnit(selfType, dependentType))
         dependentTypes.Add(new KeyValuePair<string, DTypeDesc>(dependentType.MakeFullName(), dependentType));
 }