public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = target; return Defer(deferArgs); } // Make sure target actually contains a Type. if (!typeof(Type).IsAssignableFrom(target.LimitType)) { return errorSuggestion ?? RuntimeHelpers.CreateBindingThrow( target, args, BindingRestrictions.Empty, typeof(InvalidOperationException), "Type object must be used when creating instance -- " + args); } var type = target.Value as Type; Debug.Assert(type != null); ConstructorInfo[] constructors = type.GetConstructors(); // Get constructors with right arg counts. IEnumerable<ConstructorInfo> ctors = constructors. Where(c => c.GetParameters().Length == args.Length); var res = new List<ConstructorInfo>(); foreach (ConstructorInfo c in ctors) { if (RuntimeHelpers.ParametersMatchArguments(c.GetParameters(), args)) { res.Add(c); } } // We generate an instance restriction on the target since it is a // Type and the constructor is associate with the actual Type instance. BindingRestrictions restrictions = RuntimeHelpers.GetTargetArgsRestrictions( target, args, true); if (res.Count == 0) { return errorSuggestion ?? RuntimeHelpers.CreateBindingThrow( target, args, restrictions, typeof(MissingMemberException), "Can't bind create instance -- " + args); } Expression[] ctorArgs = RuntimeHelpers.ConvertArguments( args, res[0].GetParameters()); return new DynamicMetaObject( // Creating an object, so don't need EnsureObjectResult. Expression.New(res[0], ctorArgs), restrictions); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(binder, "binder"); if (args.Any(arg => ComBinderHelpers.IsStrongBoxArg(arg))) { return ComBinderHelpers.RewriteStrongBoxAsRef(binder, this, args, false); } ComMethodDesc method; if (_self.TryGetGetItem(out method)){ return BindComInvoke(args, method, binder.Arguments); } return base.BindInvoke(binder, args); }
public override DynamicMetaObject FallbackInvoke( DynamicMetaObject targetMO, DynamicMetaObject[] argMOs, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindInvoke(this, targetMO, argMOs, out result)) { return result; } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue || argMOs.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[argMOs.Length + 1]; for (int i = 0; i < argMOs.Length; i++) { deferArgs[i + 1] = argMOs[i]; } deferArgs[0] = targetMO; return Defer(deferArgs); } //Find our own binding. if (targetMO.LimitType.IsSubclassOf(typeof(Delegate))) { var parms = targetMO.LimitType.GetMethod("Invoke").GetParameters(); if (parms.Length == argMOs.Length) { // Don't need to check if argument types match parameters. // If they don't, users get an argument conversion error. var callArgs = RuntimeHelpers.ConvertArguments(argMOs, parms); var expression = Expression.Invoke( Expression.Convert(targetMO.Expression, targetMO.LimitType), callArgs); return new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType)); } } return errorSuggestion ?? RuntimeHelpers.CreateThrow( targetMO, argMOs, BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType), typeof(InvalidOperationException), "Wrong number of arguments for function -- " + targetMO.LimitType.ToString() + " got " + argMOs.ToString()); }
private DynamicMetaObject BindGetOrInvoke(CallSiteBinder binder, DynamicMetaObject[] args, IList<ArgumentInfo> argInfos) { if (args.Any(arg => ComBinderHelpers.IsStrongBoxArg(arg))) { return ComBinderHelpers.RewriteStrongBoxAsRef(binder, this, args, false); } ComMethodDesc method; var target = _callable.DispatchComObject; var name = _callable.MemberName; if (target.TryGetMemberMethod(name, out method) || target.TryGetMemberMethodExplicit(name, out method)) { return BindComInvoke(method, args, argInfos); } return null; }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { if (indexes.Any(arg => ComBinderHelpers.IsStrongBoxArg(arg))) { return ComBinderHelpers.RewriteStrongBoxAsRef(binder, this, indexes.AddLast(value), true); } ComMethodDesc method; var target = _callable.DispatchComObject; var name = _callable.MemberName; if (target.TryGetPropertySetter(name, out method, value.LimitType) || target.TryGetPropertySetterExplicit(name, out method, value.LimitType)) { return BindComInvoke(method, indexes.AddLast(value), binder.Arguments); } return base.BindSetIndex(binder, indexes, value); }
public override DynamicMetaObject FallbackGetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindGetIndex(this, target, indexes, out result)) { return result; } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || indexes.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[indexes.Length + 1]; for (int i = 0; i < indexes.Length; i++) { deferArgs[i + 1] = indexes[i]; } deferArgs[0] = target; return Defer(deferArgs); } // Give good error for Cons. //if (target.LimitType == typeof(Cons)) //{ // if (indexes.Length != 1) // return errorSuggestion ?? // RuntimeHelpers.CreateThrow( // target, indexes, BindingRestrictions.Empty, // typeof(InvalidOperationException), // "Indexing list takes single index. " + "Got " + // indexes.Length.ToString()); //} // Find our own binding. // // Conversions created in GetIndexExpression must be consistent with // restrictions made in GetTargetArgsRestrictions. var indexingExpr = RuntimeHelpers.EnsureObjectResult( RuntimeHelpers.GetIndexingExpression(target, indexes)); var restrictions = RuntimeHelpers.GetTargetArgsRestrictions( target, indexes, false); return new DynamicMetaObject(indexingExpr, restrictions); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (!target.HasValue || args.Any(a => !a.HasValue)) return Defer(target, args); var restrictions = RuntimeHelpers.MergeTypeRestrictions(target); if (target.Value == null) throw LuaRuntimeException.Create(context, "Attempt to invoke a nil object (" + context.CurrentVariableIdentifier + ")"); if (!target.LimitType.IsSubclassOf(typeof(Delegate)) && target.LimitType != typeof(Varargs)) return new DynamicMetaObject( MetamethodFallbacks.WrapStackTrace(MetamethodFallbacks.Call(context, target, args), context, new FunctionStack(context.CurrentVariableIdentifier + "." + Constant.CALL_METAMETHOD)), restrictions); restrictions = restrictions.Merge( RuntimeHelpers.MergeTypeRestrictions(args).Merge( RuntimeHelpers.MergeInstanceRestrictions(target))); Delegate function = null; DynamicMetaObject actualTarget = null; if (target.LimitType.IsSubclassOf(typeof(Delegate))) { function = (Delegate)target.Value; actualTarget = target; } else if (target.LimitType == typeof(Varargs)) { function = ((Varargs)target.Value).First() as Delegate; actualTarget = new DynamicMetaObject(Expression.Constant(((Varargs)target.Value).First()), BindingRestrictions.Empty, ((Varargs)target.Value).First()); } if (function == null) return new DynamicMetaObject(MetamethodFallbacks.Call(context, actualTarget, args), restrictions); var methodInfo = function.Method; bool toss = false; return GetInvoker(actualTarget, args, methodInfo, out toss, ref restrictions); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (!target.HasValue || args.Any(a => !a.HasValue)) return Defer(target, args); var restrictions = RuntimeHelpers.MergeTypeRestrictions(target); if (!target.LimitType.IsSubclassOf(typeof(Delegate))) return new DynamicMetaObject(MetamethodFallbacks.Call(context, target, args), restrictions); restrictions = restrictions.Merge( RuntimeHelpers.MergeTypeRestrictions(args).Merge( RuntimeHelpers.MergeInstanceRestrictions(target))); List<Expr> sideEffects; Expr failExpr; var function = (Delegate)target.Value; var methodInfo = function.Method; var mappedArgs = MapArguments(args, methodInfo, ref restrictions, out sideEffects, out failExpr); if (failExpr != null) return new DynamicMetaObject(Expr.Block(failExpr, Expr.Default(typeof(object))), restrictions); var invokeExpr = InvokeExpression(target, mappedArgs, methodInfo); // Execute overflowing arguments for side effects Expr expr; if (sideEffects.Count == 0) { expr = invokeExpr; } else { var tempVar = Expr.Variable(typeof(object)); var assign = Expr.Assign(tempVar, invokeExpr); sideEffects.Insert(0, assign); sideEffects.Add(tempVar); expr = Expr.Block(new[] {tempVar}, sideEffects); } return new DynamicMetaObject(expr, restrictions); }
public override DynamicMetaObject FallbackSetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindSetIndex(this, target, indexes, value, out result)) { return result; } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || indexes.Any((a) => !a.HasValue) || !value.HasValue) { var deferArgs = new DynamicMetaObject[indexes.Length + 2]; for (int i = 0; i < indexes.Length; i++) { deferArgs[i + 1] = indexes[i]; } deferArgs[0] = target; deferArgs[indexes.Length + 1] = value; return Defer(deferArgs); } // Find our own binding. Expression valueExpr = value.Expression; ////we convert a value of TypeModel to Type. //if (value.LimitType == typeof(TypeModel)) //{ // valueExpr = RuntimeHelpers.GetRuntimeTypeMoFromModel(value).Expression; //} //Debug.Assert(target.HasValue && target.LimitType != typeof(Array)); Expression setIndexExpr; //if (target.LimitType == typeof(Cons)) //{ // if (indexes.Length != 1) // { // return errorSuggestion ?? // RuntimeHelpers.CreateThrow( // target, indexes, BindingRestrictions.Empty, // typeof(InvalidOperationException), // "Indexing list takes single index. " + "Got " + indexes); // } // // Call RuntimeHelper.SetConsElt // List<Expression> args = new List<Expression>(); // // The first argument is the list // args.Add( // Expression.Convert( // target.Expression, // target.LimitType) // ); // // The second argument is the index. // args.Add(Expression.Convert(indexes[0].Expression, // indexes[0].LimitType)); // // The last argument is the value // args.Add(Expression.Convert(valueExpr, typeof(object))); // // BinderFactory helper returns value stored. // setIndexExpr = Expression.Call( // typeof(RuntimeHelpers), // "SetConsElt", // null, // args.ToArray()); //} //else { Expression indexingExpr = RuntimeHelpers.GetIndexingExpression( target, indexes); // Assign returns the stored value, so we're good for BinderFactory. setIndexExpr = Expression.Assign(indexingExpr, valueExpr); } BindingRestrictions restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, indexes, false); return new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(setIndexExpr), restrictions); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject targetMO, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = targetMO; return Defer(deferArgs); } // Find our own binding. // Could consider allowing invoking static members from an instance. BindingFlags flags = BindingFlags.Instance | BindingFlags.Public; MemberInfo[] members = targetMO.LimitType.GetMember(Name, flags); if ((members.Length == 1) && (members[0] is PropertyInfo || members[0] is FieldInfo)) { // NEED TO TEST, should check for delegate value too MemberInfo mem = members[0]; throw new NotImplementedException(); //return new DynamicMetaObject( // Expression.Dynamic( // new SymplInvokeBinder(new CallInfo(args.Length)), // typeof(object), // args.Select(a => a.Expression).AddFirst( // Expression.MakeMemberAccess(this.Expression, mem))); // Don't test for eventinfos since we do nothing with them now. } else { // Get MethodInfos with right arg counts. IEnumerable<MethodInfo> mi_mems = members. Select(m => m as MethodInfo). Where(m => m.GetParameters().Length == args.Length); // Get MethodInfos with param types that work for args. This works // except for value args that need to pass to reftype params. // We could detect that to be smarter and then explicitly StrongBox // the args. var res = mi_mems.Where(mem => RuntimeHelpers.ParametersMatchArguments(mem.GetParameters(), args)).ToList(); // False below means generate a type restriction on the MO. // We are looking at the members targetMO's Type. BindingRestrictions restrictions = RuntimeHelpers.GetTargetArgsRestrictions(targetMO, args, false); if (res.Count == 0) { return errorSuggestion ?? RuntimeHelpers.CreateBindingThrow(targetMO, args, restrictions, typeof(MissingMemberException), "Can't bind member invoke -- " + args); } // restrictions and conversion must be done consistently. Expression[] callArgs = RuntimeHelpers.ConvertArguments(args, res[0].GetParameters()); return new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.Call( Expression.Convert(targetMO.Expression, targetMO.LimitType), res[0], callArgs)), restrictions); // Could hve tried just letting Expr.Call factory do the work, // but if there is more than one applicable method using just // assignablefrom, Expr.Call throws. It does not pick a "most // applicable" method or any method. } }
internal static bool NeedsDeferal(DynamicMetaObject[] args) { return args.Any(MetaObjectExtensions.NeedsDeferral); }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindInvokeMember(this, target, args, out result)) return result; // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = target; return Defer(deferArgs); } Func<DynamicMetaObject> getMethodNotFoundDMO = () => errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, RuntimeHelpers.GetTargetArgsRestrictions(target, args, false), typeof(MissingMethodException), String.Format(RuntimeMessages.PublicMethodDoesNotExist_Method_Type, this.Name, target.Value.GetType())); if (target.Value is HappyTypeTracker) { HappyTypeTracker typeTracker = (HappyTypeTracker) target.Value; IHappyTracker found; if (typeTracker.FindMemberTracker(this.Name, out found)) { HappyMethodTracker tracker = found as HappyMethodTracker; if(tracker == null) { return errorSuggestion ?? RuntimeHelpers.CreateThrow( target, args, RuntimeHelpers.GetTargetArgsRestrictions(target, args, false), typeof(MissingMemberException), String.Format(RuntimeMessages.MemberIsNotInvokable_MemberNameTypeName, found.Name, typeTracker.Name), args.ToString()); } return ResolveOverload(null, args, tracker.Methods, BindingRestrictions.GetInstanceRestriction(target.Expression, typeTracker)); } return getMethodNotFoundDMO(); } MethodInfo[] methods = target.Value.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(m => m.Name == Name).ToArray(); if(methods.Length != 0) return this.ResolveOverload(target, args, methods); return getMethodNotFoundDMO(); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { ContractUtils.RequiresNotNull(binder, "binder"); if (indexes.Any(arg => ComBinderHelpers.IsStrongBoxArg(arg))) { return ComBinderHelpers.RewriteStrongBoxAsRef(binder, this, indexes.AddLast(value), true); } ComMethodDesc setItem; if (_self.TryGetSetItem(out setItem)) { return BindComInvoke(indexes.AddLast(value), setItem, binder.Arguments); } return base.BindSetIndex(binder, indexes, value); }