BindToBool() private static method

private static BindToBool ( Expression expr ) : Expression
expr System.Linq.Expressions.Expression
return System.Linq.Expressions.Expression
Esempio n. 1
0
        public static Expression BindField(PhpTypeInfo type, Type classCtx, Expression target, string field, Expression ctx, AccessMask access, Expression rvalue)
        {
            if (access.Write() != (rvalue != null))
            {
                throw new ArgumentException();
            }

            // lookup a declared field
            for (var t = type; t != null; t = t.BaseType)
            {
                foreach (var p in t.DeclaredFields.GetPhpProperties(field))
                {
                    if (p.IsStatic == (target == null) && p.IsVisible(classCtx))
                    {
                        return(BindAccess(p.Bind(ctx, target), ctx, access, rvalue));
                    }
                }
            }

            //
            // runtime fields
            //

            if (type.RuntimeFieldsHolder != null)                                         // we don't handle magic methods without the runtime fields
            {
                var runtimeflds = Expression.Field(target, type.RuntimeFieldsHolder);     // Template: target->__runtime_fields
                var fieldkey    = Expression.Constant(new IntStringKey(field));           // Template: IntStringKey(field)
                var resultvar   = Expression.Variable(Cache.Types.PhpValue[0], "result"); // Template: PhpValue result;

                // Template: runtimeflds != null && runtimeflds.TryGetValue(field, out result)
                var trygetfield   = Expression.AndAlso(Expression.ReferenceNotEqual(runtimeflds, Expression.Constant(null)), Expression.Call(runtimeflds, Cache.Operators.PhpArray_TryGetValue, fieldkey, resultvar));
                var containsfield = Expression.AndAlso(Expression.ReferenceNotEqual(runtimeflds, Expression.Constant(null)), Expression.Call(runtimeflds, Cache.Operators.PhpArray_ContainsKey, fieldkey));

                Expression result;

                //
                if (access.EnsureObject())
                {
                    // (object)target->field->

                    // Template: runtimeflds.EnsureObject(key)
                    result = Expression.Call(EnsureNotNullPhpArray(runtimeflds), Cache.Operators.PhpArray_EnsureItemObject, fieldkey);

                    var __get = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__get, field, null);
                    if (__get != null)
                    {
                        // Template: runtimeflds.Contains(key) ? runtimeflds.EnsureObject(key) : ( __get(key) ?? runtimeflds.EnsureObject(key))
                        return(Expression.Condition(containsfield,
                                                    Expression.Call(runtimeflds, Cache.Operators.PhpArray_EnsureItemObject, fieldkey),
                                                    InvokeHandler(ctx, target, field, __get, access, result, typeof(object))));
                    }
                    else
                    {
                        return(result);
                    }
                }
                else if (access.EnsureArray())
                {
                    // (IPhpArray)target->field[] =
                    result = Expression.Call(EnsureNotNullPhpArray(runtimeflds), Cache.Operators.PhpArray_EnsureItemArray, fieldkey);

                    var __get = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__get, field, null);
                    if (__get != null)
                    {
                        // Template: runtimeflds.Contains(key) ? runtimeflds.EnsureArray(key) : ( __get(key) ?? runtimeflds.EnsureArray(key))
                        return(Expression.Condition(containsfield,
                                                    Expression.Call(runtimeflds, Cache.Operators.PhpArray_EnsureItemArray, fieldkey),
                                                    InvokeHandler(ctx, target, field, __get, access, result, typeof(IPhpArray))));
                    }
                    else
                    {
                        // runtimeflds.EnsureItemArray(key)
                        return(result);
                    }
                }
                else if (access.EnsureAlias())
                {
                    // (PhpAlias)&target->field

                    result = Expression.Call(EnsureNotNullPhpArray(runtimeflds), Cache.Operators.PhpArray_EnsureItemAlias, fieldkey);

                    var __get = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__get, field, null);
                    if (__get != null)
                    {
                        // Template: runtimeflds.Contains(key) ? runtimeflds.EnsureItemAlias(key) : ( __get(key) ?? runtimeflds.EnsureItemAlias(key))
                        return(Expression.Condition(containsfield,
                                                    Expression.Call(runtimeflds, Cache.Operators.PhpArray_EnsureItemAlias, fieldkey),
                                                    InvokeHandler(ctx, target, field, __get, access, result, typeof(PhpAlias))));
                    }
                    else
                    {
                        // runtimeflds.EnsureItemAlias(key)
                        return(result);
                    }
                }
                else if (access.Unset())
                {
                    // unset(target->field)
                    // Template: if (!runtimeflds.RemoveKey(key)) __unset(key)

                    var removekey = Expression.Call(runtimeflds, Cache.Operators.PhpArray_RemoveKey, fieldkey);
                    var __unset   = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__unset, field, null);
                    if (__unset != null)
                    {
                        return(Expression.IfThen(
                                   Expression.OrElse(Expression.ReferenceEqual(runtimeflds, Expression.Constant(null)), Expression.IsFalse(removekey)),
                                   InvokeHandler(ctx, target, field, __unset, access, Expression.Block(), typeof(void))));
                    }
                    else
                    {
                        // if (runtimeflds != null) runtimeflds.RemoveKey(key)
                        return(Expression.IfThen(
                                   Expression.ReferenceNotEqual(runtimeflds, Expression.Constant(null)),
                                   removekey));
                    }
                }
                else if (access.Write())
                {
                    var __set = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__set, field, rvalue);

                    if (access.WriteAlias())
                    {
                        // target->field = (PhpAlias)&rvalue
                        Debug.Assert(rvalue.Type == typeof(PhpAlias));
                        rvalue = ConvertExpression.Bind(rvalue, typeof(PhpAlias), ctx);

                        // EnsureNotNull(runtimeflds).SetItemAlias(key, rvalue)
                        result = Expression.Call(EnsureNotNullPhpArray(runtimeflds), Cache.Operators.PhpArray_SetItemAlias, fieldkey, rvalue);

                        if (__set != null)
                        {
                            // if (ContainsKey(key)) ? runtimeflds.SetItemAlias(rvalue) : (__set(key, rvalue) ?? runtimeflds.SetItemAlias(key, rvalue)
                            return(Expression.Condition(containsfield,
                                                        Expression.Call(runtimeflds, Cache.Operators.PhpArray_SetItemAlias, fieldkey, rvalue),
                                                        InvokeHandler(ctx, target, field, __set, access, result, typeof(void))));
                        }
                        else
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        // target->field = rvalue
                        rvalue = ConvertExpression.Bind(rvalue, typeof(PhpValue), ctx);

                        /* Template:
                         * return runtimeflds != null && runtimeflds.ContainsKey(field)
                         *   ? runtimeflds.SetItemValue(key, rvalue)
                         *   : (__set(field, value) ?? runtimeflds.SetItemValue(key, value))
                         */

                        result = Expression.Call(EnsureNotNullPhpArray(runtimeflds), Cache.Operators.PhpArray_SetItemValue, fieldkey, rvalue);

                        if (__set != null)
                        {
                            return(Expression.Condition(containsfield,
                                                        Expression.Call(runtimeflds, Cache.Operators.PhpArray_SetItemValue, fieldkey, rvalue),
                                                        InvokeHandler(ctx, target, field, __set, access, result, typeof(void))));
                        }
                        else
                        {
                            return(result);
                        }
                    }
                }
                else if (access.Isset())
                {
                    // isset(target->field)

                    var __isset = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__isset, field, null);

                    // Template: (TryGetField(result) || (bool)__isset(key)) ? true : void
                    result = Expression.Condition(Expression.OrElse(
                                                      trygetfield,
                                                      ConvertExpression.BindToBool(InvokeHandler(ctx, target, field, __isset, access))),
                                                  Expression.Property(null, Cache.Properties.PhpValue_True),
                                                  Expression.Field(null, Cache.Properties.PhpValue_Void));
                }
                else
                {
                    // = target->field

                    /* Template:
                     * return runtimeflds.TryGetValue(field, out result) ? result : (__get(field) ?? ERR);
                     */
                    var __get = BindMagicMethod(type, classCtx, target, ctx, TypeMethods.MagicMethods.__get, field, null);
                    result = Expression.Condition(trygetfield,
                                                  resultvar,
                                                  InvokeHandler(ctx, target, field, __get, access)); // TODO: @default = { ThrowError; return null; }
                }

                //
                return(Expression.Block(result.Type, new[] { resultvar }, result));
            }

            // TODO: IDynamicMetaObject

            //
            return(null);
        }