示例#1
0
        public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            var bound = CreateContext().ProcessArgs(target, args, HasTarget);

            Expression invocation;

            //
            var methods = ResolveMethods(bound);

            if (methods != null && methods.Length != 0)
            {
                if (bound.HasArgumentUnpacking)
                {
                    var args_var = Expression.Variable(typeof(PhpValue[]), "args_array");

                    /*
                     * args_var = ArgumentsToArray()
                     * call(...args_var...)
                     */

                    invocation = Expression.Block(new[] { args_var },
                                                  Expression.Assign(args_var, BinderHelpers.UnpackArgumentsToArray(methods, bound.Arguments, bound.Context, bound.ClassContext)),
                                                  OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, methods, bound.Context, args_var, bound.IsStaticSyntax, lateStaticType: bound.TargetType)
                                                  );
                }
                else
                {
                    invocation = OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, methods, bound.Context, bound.Arguments, bound.IsStaticSyntax, lateStaticType: bound.TargetType, classContext: bound.ClassContext);
                }
            }
            else
            {
                invocation = BindMissingMethod(bound);
            }

            // TODO: by alias or by value
            return(new DynamicMetaObject(invocation, bound.Restrictions));
        }
示例#2
0
        protected override Expression BindMissingMethod(DynamicMetaObject ctx, DynamicMetaObject target, IList <DynamicMetaObject> args, ref BindingRestrictions restrictions)
        {
            var tinfo = target.RuntimeType.GetPhpTypeInfo();
            var call  = (PhpMethodInfo)tinfo.DeclaredMethods[TypeMethods.MagicMethods.__call];

            if (call != null)
            {
                if (_name == null)
                {
                    throw new NotImplementedException();
                }

                // target.__call(name, array)
                var call_args = new Expression[]
                {
                    Expression.Constant(_name),
                    BinderHelpers.NewPhpArray(ctx.Expression, args.Select(a => a.Expression)),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, target.Expression, call.Methods, ctx.Expression, call_args));
            }

            return(base.BindMissingMethod(ctx, target, args, ref restrictions));
        }
示例#3
0
        public static TObjectCreator BindToCreator(Type type, ConstructorInfo[] ctors)
        {
            Debug.Assert(ctors.All(ctor => ctor is ConstructorInfo));
            Debug.Assert(ctors.All(ctor => ctor.DeclaringType == type));

            // (Context ctx, PhpValue[] arguments)
            var ps = new ParameterExpression[] { Expression.Parameter(typeof(Context), "ctx"), Expression.Parameter(typeof(PhpValue[]), "argv") };

            if (ctors.Length != 0)
            {
                // invoke targets
                var invocation = OverloadBinder.BindOverloadCall(type, null, ctors, ps[0], ps[1]);
                Debug.Assert(invocation.Type == type);

                // compile & create delegate
                var lambda = Expression.Lambda <TObjectCreator>(invocation, ctors[0].Name + "#" + ctors.Length, true, ps);
                return(lambda.Compile());
            }
            else
            {
                // TODO: lambda {error; NULL;}
                throw new ArgumentException("No constructor accessible for " + type.FullName);
            }
        }
示例#4
0
        public static Expression BindField(PhpTypeInfo type, Type classCtx, Expression target, string field, Expression ctx, AccessFlags access, Expression rvalue)
        {
            if (access.Write() != (rvalue != null))
            {
                throw new ArgumentException();
            }

            // lookup a declared field
            for (var t = type; t != null; t = t.BaseType)
            {
                var expr = t.DeclaredFields.Bind(field, classCtx, target, ctx, (target != null) ? TypeFields.FieldKind.InstanceField : TypeFields.FieldKind.StaticField);
                if (expr != null)
                {
                    return(BindAccess(expr, ctx, access, rvalue));
                }
            }

            // lookup __get, __set, ...
            TypeMethods.MagicMethods magic;
            if (access.Write())
            {
                magic = TypeMethods.MagicMethods.__set;
            }
            else if (access.Unset())
            {
                magic = TypeMethods.MagicMethods.__unset;
            }
            else if (access.Isset())
            {
                magic = TypeMethods.MagicMethods.__isset;
            }
            else
            {
                magic = TypeMethods.MagicMethods.__get;
            }

            for (var t = type; t != null; t = t.BaseType)
            {
                var m = (PhpMethodInfo)t.DeclaredMethods[magic];
                if (m != null)
                {
                    if (m.Methods.Length == 1 && m.Methods[0].IsVisible(classCtx))
                    {
                        switch (magic)
                        {
                        case TypeMethods.MagicMethods.__set:
                            // __set(name, value)
                            return(OverloadBinder.BindOverloadCall(rvalue.Type, target, m.Methods, ctx, new Expression[] { Expression.Constant(field), rvalue }));

                        default:
                            // __get(name), __unset(name), __isset(name)
                            return(OverloadBinder.BindOverloadCall(m.Methods[0].ReturnType, target, m.Methods, ctx, new Expression[] { Expression.Constant(field) }));
                        }
                    }

                    break;
                }
            }

            // runtime fields
            var __runtimeflds = type.RuntimeFieldsHolder;

            if (__runtimeflds != null)
            {
                var __runtimeflds_field = Expression.Field(target, __runtimeflds);
                var key = Expression.Constant(new IntStringKey(field));

                return(BindArrayAccess(__runtimeflds_field, key, ctx, access, rvalue));
            }

            // TODO: dynamic

            //
            return(null);
        }