Example #1
0
        public PhpAlias GetAlias(ref PhpValue value, Context ctx, Type classContext)
        {
            PhpValue tmp;

            if (value.AsObject() is ArrayAccess arrayaccess)
            {
                // special case for ArrayAccess avoids conversion to IntStringKey

                tmp = arrayaccess.offsetGet(Key);

                switch (Next.Operation)
                {
                case RuntimeChainOperation.ArrayItem:
                    tmp = PhpValue.EnsureAlias(ref tmp);
                    break;

                case RuntimeChainOperation.Property:
                    tmp = PhpValue.FromClass(PhpValue.EnsureObject(ref tmp));
                    break;

                case RuntimeChainOperation.End:
                    return(PhpValue.EnsureAlias(ref tmp));

                default:
                    throw new InvalidOperationException();
                }
            }
            else
            {
                var arr = PhpValue.EnsureArray(ref value);

                switch (Next.Operation)
                {
                case RuntimeChainOperation.ArrayItem:
                    tmp = PhpValue.Create(arr.EnsureItemArray(Key));
                    break;

                case RuntimeChainOperation.Property:
                    tmp = PhpValue.FromClass(arr.EnsureItemObject(Key));
                    break;

                case RuntimeChainOperation.End:
                    return(arr.EnsureItemAlias(Key));

                default:
                    throw new InvalidOperationException();
                }
            }

            //
            return(Next.GetAlias(ref tmp, ctx, classContext));
        }
Example #2
0
        ref PhpValue Ensure(ref PhpValue value)
        {
            Debug.Assert(Next.Operation != RuntimeChainOperation.End);

            switch (Next.Operation)
            {
            case RuntimeChainOperation.Value:
                break;

            case RuntimeChainOperation.Property:
                value = PhpValue.FromClass(PhpValue.EnsureObject(ref value));
                break;

            case RuntimeChainOperation.ArrayItem:
                value = PhpValue.Create(PhpValue.EnsureArray(ref value));
                break;

            default:
                throw new InvalidOperationException();
            }

            //
            return(ref value);
        }
Example #3
0
        public virtual object EnsureObject(Context ctx, object instance)
        {
            var value = GetValue(ctx, instance);

            return(PhpValue.EnsureObject(ref value));
        }
Example #4
0
        public PhpAlias GetAlias(ref PhpValue value, Context ctx, Type classContext)
        {
            var receiver = PhpValue.EnsureObject(ref value);
            var t        = receiver.GetPhpTypeInfo();

            PhpValue tmp;

            if (BinderHelpers.TryResolveDeclaredProperty(t, classContext, false, Name, out var prop))
            {
                switch (Next.Operation)
                {
                case RuntimeChainOperation.Property:
                    tmp = PhpValue.FromClass(prop.EnsureObject(ctx, receiver));
                    break;

                case RuntimeChainOperation.ArrayItem:
                    tmp = PhpValue.Create(prop.EnsureArray(ctx, receiver));
                    break;

                case RuntimeChainOperation.End:
                    return(prop.EnsureAlias(ctx, receiver));

                default:
                    throw new InvalidOperationException();
                }
            }
            else
            {
                // Template: runtimeflds.Contains(key) ? runtimeflds.EnsureObject(key) : ( __get(key) ?? runtimeflds.EnsureObject(key))

                var runtimeFields = t.GetRuntimeFields(receiver);
                if (runtimeFields == null || !runtimeFields.Contains(Name))
                {
                    //
                    var __get = t.RuntimeMethods[TypeMethods.MagicMethods.__get];
                    if (__get != null)
                    {
                        // NOTE: magic methods must have public visibility, therefore the visibility check is unnecessary

                        // int subkey1 = access.Write() ? 1 : access.Unset() ? 2 : access.Isset() ? 3 : 4;
                        int subkey = Name.GetHashCode() ^ (1 << 4 /*subkey1*/);

                        using (var token = new Context.RecursionCheckToken(ctx, receiver, subkey))
                        {
                            if (!token.IsInRecursion)
                            {
                                tmp = __get.Invoke(ctx, receiver, Name);
                                return(Next.GetAlias(ref tmp, ctx, classContext));
                            }
                        }
                    }
                }

                if (runtimeFields == null)
                {
                    runtimeFields = t.EnsureRuntimeFields(receiver);
                }

                //

                switch (Next.Operation)
                {
                case RuntimeChainOperation.Property:
                    tmp = PhpValue.FromClass(runtimeFields.EnsureItemObject(Name));
                    break;

                case RuntimeChainOperation.ArrayItem:
                    tmp = PhpValue.Create(runtimeFields.EnsureItemArray(Name));
                    break;

                case RuntimeChainOperation.End:
                    return(runtimeFields.EnsureItemAlias(Name));

                default:
                    throw new InvalidOperationException();
                }
            }

            // chain:
            return(Next.GetAlias(ref tmp, ctx, classContext));
        }