public override DynamicMetaObject FallbackInvoke( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var deferArgs = Runtime.CheckDeferArgs(target, args); if (deferArgs != null) { return(Defer(deferArgs)); } if (target.Value == null) { return(Runtime.CheckTargetNullReference(target, "Not invokable: " + Runtime.CollectParameterInfo(target, args))); } if (Runtime.Prototypep(target.Value)) { var indexingExpr = Runtime.GetIndexingExpression(target, args); var restrictions = Runtime.GetTargetArgsRestrictions(target, args, false); if (indexingExpr == null) { return(errorSuggestion ?? Runtime.CreateThrow( target, args, restrictions, typeof(InvalidOperationException), "Not invokable: " + Runtime.CollectParameterInfo(target, args))); } return(new DynamicMetaObject(Runtime.EnsureObjectResult(indexingExpr), restrictions)); } if (target.LimitType.IsSubclassOf(typeof(Delegate))) { var parms = target.LimitType.GetMethod("Invoke").GetParameters(); if (parms.Length == args.Length) { // Don't need to check if argument types match parameters. // If they don't, users get an argument conversion error. var callArgs = Runtime.ConvertArguments(args, parms); var expression = Expression.Invoke( Expression.Convert(target.Expression, target.LimitType), callArgs); return(new DynamicMetaObject( Runtime.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } } return(errorSuggestion ?? Runtime.CreateThrow( target, args, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), "Not invokable: " + Runtime.CollectParameterInfo(target, args))); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { bool createdParamArray; var ctors = new List <CandidateMethod <ConstructorInfo> >(); foreach (ConstructorInfo m in runtimeModel.Members) { if (m.IsStatic) { continue; } if (Runtime.ParametersMatchArguments(m.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(ctors, m, createdParamArray); } } if (ctors.Count == 0) { throw new MissingMemberException("No (suitable) constructor found: new " + runtimeModel.FullName + Runtime.CollectParameterInfo(args)); } var ctor = ctors[0].Method; var restrictions = Runtime.GetTargetArgsRestrictions(this, args, true); var callArgs = Runtime.ConvertArguments(args, ctor.GetParameters()); return(new DynamicMetaObject(Runtime.EnsureObjectResult(Expression.New(ctor, callArgs)), restrictions)); }
public override DynamicMetaObject FallbackSetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { var deferArgs = Runtime.CheckDeferArgs(target, indexes); if (deferArgs != null) { return(Defer(deferArgs)); } if (target.Value == null) { return(Runtime.CheckTargetNullReference(target, "Cannot set index on null reference: " + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes))); } Expression valueExpr = value.Expression; Debug.Assert(target.HasValue && target.LimitType != typeof(Array)); Type valueType; var indexingExpr = Runtime.GetIndexingExpression(target, indexes, out valueType); if (indexingExpr == null) { return(errorSuggestion ?? Runtime.CreateThrow( target, indexes, BindingRestrictions.Empty, typeof(InvalidOperationException), "No set indexer found: " + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes))); } var setIndexExpr = Expression.Assign(indexingExpr, Expression.Convert(valueExpr, valueType)); BindingRestrictions restrictions = Runtime.GetTargetArgsRestrictions(target, indexes, false); return(new DynamicMetaObject(Runtime.EnsureObjectResult(setIndexExpr), restrictions)); }
public override DynamicMetaObject FallbackGetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { var deferArgs = Runtime.CheckDeferArgs(target, indexes); if (deferArgs != null) { return(Defer(deferArgs)); } if (target.Value == null) { var expr = Expression.Constant(null); var restrictions2 = BindingRestrictions.GetInstanceRestriction(target.Expression, null); return(new DynamicMetaObject(expr, restrictions2)); } // Find our own binding. // // Conversions created in GetIndexExpression must be consistent with // restrictions made in GetTargetArgsRestrictions. var indexingExpr = Runtime.GetIndexingExpression(target, indexes); if (indexingExpr == null) { return(errorSuggestion ?? Runtime.CreateThrow( target, indexes, BindingRestrictions.Empty, typeof(InvalidOperationException), "No get indexer found: " + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes))); } var restrictions = Runtime.GetTargetArgsRestrictions(target, indexes, false); return(new DynamicMetaObject(Runtime.EnsureObjectResult(indexingExpr), restrictions)); }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var deferArgs = Runtime.CheckDeferArgs(target, args); if (deferArgs != null) { return(Defer(deferArgs)); } var limitType = target.LimitType; var name = Name.LispToPascalCaseName(); if (target.Value == null) { return(Runtime.CheckTargetNullReference(target, "Cannot invoke a method on a null reference:" + limitType.FullName + "." + name + Runtime.CollectParameterInfo(target, args))); } var builtin = Runtime.FindImportedFunction(limitType, Name); if (builtin != null) { DynamicMetaObject result; if (builtin.TryBindInvokeBestInstanceMethod(false, target, target, args, out result)) { return(result); } } var flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy; var methods = new List <CandidateMethod <MethodInfo> >(); bool createdParamArray; foreach (var m in limitType.GetMember(name, flags)) { MethodInfo mi; if (m is PropertyInfo) { mi = ((PropertyInfo)m).GetGetMethod(); } else { mi = m as MethodInfo; } if (mi != null && Runtime.ParametersMatchArguments(mi.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(methods, mi, createdParamArray); } } if (methods.Count == 0 && (Name.StartsWith("set-") || Name.StartsWith("get-"))) { // Fallback to special handling to change .set-bla to .set_bla if the former has failed. name = Name.Left(3) + "_" + Name.Substring(4).LispToPascalCaseName(); foreach (var m in limitType.GetMember(name, flags)) { MethodInfo mi; if (m is PropertyInfo) { mi = ((PropertyInfo)m).GetGetMethod(); } else { mi = m as MethodInfo; } if (mi != null && Runtime.ParametersMatchArguments(mi.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(methods, mi, createdParamArray); } } } var restrictions = Runtime.GetTargetArgsRestrictions(target, args, false); if (methods.Count == 0) { return(errorSuggestion ?? Runtime.CreateThrow(target, args, restrictions, typeof(MissingMemberException), "No (suitable) method found: " + limitType.FullName + "." + name + Runtime.CollectParameterInfo(target, args))); } else { var method = methods[0].Method; var callArgs2 = Runtime.ConvertArguments(args, method.GetParameters()); Expression expr; if (method.IsStatic) { // NOT REACHED // static // extension with target as extra parameter expr = Expression.Call(method, callArgs2); } else { expr = Expression.Call(Expression.Convert(target.Expression, limitType), method, callArgs2); } return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions)); } }
public bool TryBindInvokeBestMethod(bool instanceMethodsOnly, bool restrictionOnTargetInstance, DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject argsFirst, DynamicMetaObject[] argsRest, out DynamicMetaObject result) { bool createdParamArray; var candidates = new List <CandidateMethod <MethodInfo> >(); args = args ?? Runtime.GetCombinedTargetArgs(argsFirst, argsRest); foreach (MethodInfo m in BuiltinExtensionMembers) { if (instanceMethodsOnly && !IsProperOrExtensionInstanceMethod(m)) { continue; } if (m.IsStatic) { if (Runtime.ParametersMatchArguments(m.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } else { if (argsRest == null) { Runtime.SplitCombinedTargetArgs(args, out argsFirst, out argsRest); } if (argsRest != null && Runtime.ParametersMatchArguments(m.GetParameters(), argsRest, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } } if (candidates.Count == 0) { foreach (MethodInfo m in Members) { if (instanceMethodsOnly && !IsProperOrExtensionInstanceMethod(m)) { continue; } if (m.IsStatic) { if (Runtime.ParametersMatchArguments(m.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } else { if (argsRest == null) { Runtime.SplitCombinedTargetArgs(args, out argsFirst, out argsRest); } if (argsRest != null && Runtime.ParametersMatchArguments(m.GetParameters(), argsRest, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } } } if (candidates.Count == 0) { foreach (MethodInfo m in ExternalExtensionMembers) { if (instanceMethodsOnly && !IsProperOrExtensionInstanceMethod(m)) { continue; } if (m.IsStatic) { if (Runtime.ParametersMatchArguments(m.GetParameters(), args, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } else { if (argsRest == null) { Runtime.SplitCombinedTargetArgs(args, out argsFirst, out argsRest); } if (argsRest != null && Runtime.ParametersMatchArguments(m.GetParameters(), argsRest, out createdParamArray)) { Runtime.InsertInMostSpecificOrder(candidates, m, createdParamArray); } } } } if (candidates.Count == 0) { result = null; return(false); } var method = candidates[0].Method; if (method.IsStatic) { var restrictions = Runtime.GetTargetArgsRestrictions(target, args, true); var callArgs = Runtime.ConvertArguments(args, method.GetParameters()); result = new DynamicMetaObject(Runtime.EnsureObjectResult(Expression.Call(method, callArgs)), restrictions); } else { if (argsRest == null) { Runtime.SplitCombinedTargetArgs(args, out argsFirst, out argsRest); } // When called from FallbackInvokeMember we want to restrict on the type. var restrictions = Runtime.GetTargetArgsRestrictions(target, argsRest, restrictionOnTargetInstance); var targetInst = Expression.Convert(argsFirst.Expression, method.DeclaringType); var callArgs = Runtime.ConvertArguments(argsRest, method.GetParameters()); result = new DynamicMetaObject(Runtime.EnsureObjectResult(Expression.Call(targetInst, method, callArgs)), restrictions); } return(true); }