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)); }
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)); }
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); } }
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); }