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 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 BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { MethodInfo method = typeof(Prototype).GetMethod("SetValue"); var index = Expression.Constant(binder.Name); var expr = Expression.Call(Expression.Convert(this.Expression, typeof(Prototype)), method, index, value.Expression); var restrictions = BindingRestrictions.GetTypeRestriction(this.Expression, typeof(Prototype)); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions)); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { var restrictions = BindingRestrictions.Empty; var callArgs = LambdaHelpers.FillDataFrame(lambda.Definition.Signature, args, ref restrictions); var method = typeof(LambdaClosure).GetMethod("ApplyLambdaFast", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var expr = Expression.Call(Expression.Convert(Expression, typeof(LambdaClosure)), method, callArgs); restrictions = BindingRestrictions.GetInstanceRestriction(Expression, Value).Merge(restrictions); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions)); }
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { // Handles (.member obj) MethodInfo method = typeof(Prototype).GetMethod("GetMultipleValue"); var index = Expression.Constant(binder.Name); var expr = Expression.Call(Expression.Convert(this.Expression, typeof(Prototype)), method, index); var restrictions = BindingRestrictions.GetTypeRestriction(this.Expression, typeof(Prototype)); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions)); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { MethodInfo method = typeof(IApply).GetMethod("Apply"); var list = new List <Expression>(); foreach (var arg in args) { list.Add(Runtime.ConvertArgument(arg, typeof(object))); } var callArg = Expression.NewArrayInit(typeof(object), list); var expr = Expression.Call(Expression.Convert(Expression, typeof(T)), method, callArg); var restrictions = BindingRestrictions.GetTypeRestriction(Expression, typeof(T)); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions)); }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { // Used by (attr obj name) if (!target.HasValue) { return(Defer(target)); } var flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy; var name = Name.LispToPascalCaseName(); var members = target.LimitType.GetMember(name, flags); if (target.Value == null) { var id = target.LimitType.Name + "." + name; return(Runtime.CheckTargetNullReference(target, "Cannot get property on null reference:" + id + "(null)")); } if (members.Length == 1 && (members[0] is PropertyInfo || members[0] is FieldInfo)) { var expr = Expression.MakeMemberAccess(Expression.Convert(target.Expression, members[0].DeclaringType), members[0]); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), // Don't need restriction test for name since this // rule is only used where binder is used, which is // only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else { return(errorSuggestion ?? Runtime.CreateThrow( target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), "Property or field not found: " + target.LimitType.Name + "." + name + Runtime.CollectParameterInfo(target))); } }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { var methods = Match(args); if (methods == null) { throw new LispException("No matching multi-method found"); } var lambda = (LambdaClosure)methods.Car; if (lambda.GenericRestrictions == null) { lambda.GenericRestrictions = LambdaHelpers.GetGenericRestrictions(lambda, args); } var restrictions = lambda.GenericRestrictions; var callArgs = LambdaHelpers.FillDataFrame(lambda.Definition.Signature, args, ref restrictions); MethodInfo method = Runtime.RuntimeMethod("CallNextMethod"); var expr = Expression.Call(method, Expression.Constant(methods), callArgs); restrictions = BindingRestrictions.GetInstanceRestriction(Expression, Value).Merge(restrictions); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), 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 FallbackSetMember( DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { // Used by (set-attr obj name value) if (!target.HasValue) { return(Defer(target)); } var name = Name.LispToPascalCaseName(); if (target.Value == null) { var id = target.LimitType.Name + "." + name; return(Runtime.CheckTargetNullReference(target, "Cannot set property on null reference:" + id + "(null)")); } var flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy; var members = target.LimitType.GetMember(name, flags); if (members.Length == 1 && members[0] is PropertyInfo) { var prop = (PropertyInfo)members[0]; var val = Expression.Convert(value.Expression, prop.PropertyType); var expr = Expression.Assign(Expression.MakeMemberAccess(Expression.Convert(target.Expression, prop.DeclaringType), prop), val); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else if (members.Length == 1 && members[0] is FieldInfo) { var field = (FieldInfo)members[0]; var val = Expression.Convert(value.Expression, field.FieldType); var expr = Expression.Assign(Expression.MakeMemberAccess(Expression.Convert(target.Expression, field.DeclaringType), field), val); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else if (members.Length == 1 && members[0] is EventInfo) { //public static void AddEventHandler( System.Reflection.EventInfo eventinfo, object target, object func ) var evt = (EventInfo)members[0]; var expr = Expression.Call(Runtime.AddEventHandlerMethod, Expression.Constant(evt, typeof(EventInfo)), Expression.Convert(target.Expression, evt.DeclaringType), Expression.Convert(value.Expression, typeof(IApply))); return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else { return(errorSuggestion ?? Runtime.CreateThrow( target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), "Property or field not found: " + target.LimitType.Name + "." + name + Runtime.CollectParameterInfo(target))); } }
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); }