public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { Type[] argTypes = args.Select(a => a.RuntimeType).ToArray(); MethodInfo method = type.GetMethod(binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public, null, argTypes, null); if (method == null) return base.BindInvokeMember(binder, args); var parameters = new Expression[] { Expression.Constant(null), Expression.NewArrayInit(typeof(object), args.Select(a => Expression.Convert(a.Expression, typeof(object)))) }; return new DynamicMetaObject( Expression.Call( Expression.Constant(method), typeof(MethodInfo).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) }), parameters), BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { return new DynamicMetaObject( Expression.Call( Expression.Constant(Function), typeof(BonsaiFunction).GetMethod("Call"), Expression.NewArrayInit(typeof(object), args.Select(a => Expression.Convert(a.Expression, typeof(object))))), BindingRestrictions.GetInstanceRestriction(this.Expression, Function)); }
public static Expr Call(Expr context, DynamicMetaObject target, DynamicMetaObject[] args) { var expression = Expr.Invoke( Expr.Constant((Func<CodeContext, object, object[], object>)LuaOps.CallMetamethod), context, Expr.Convert(target.Expression, typeof(object)), Expr.NewArrayInit( typeof(object), args.Select(arg => Expr.Convert(arg.Expression, typeof(object))))); return expression; }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var combinedArgs = new Expr[args.Length + 1]; combinedArgs[0] = target.Expression; Array.Copy(args.Select(a => a.Expression).ToArray(), 0, combinedArgs, 1, args.Length); var restrictions = target.Restrictions.Merge(BindingRestrictions.Combine(args)); var expression = Expr.Dynamic( context.CreateInvokeBinder(new CallInfo(args.Length)), typeof(object), combinedArgs); return new DynamicMetaObject(expression, restrictions); }
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) { var limitedSelf = Expression; if (limitedSelf.Type != LimitType) { limitedSelf = Expression.Convert(limitedSelf, LimitType); } var indexer = LimitType.GetProperty("Item"); Expression expression = Expression.Call(limitedSelf, indexer.GetGetMethod(), indexes.Select(i => i.Expression)); if (binder.ReturnType != expression.Type) { expression = Expression.Convert(expression, binder.ReturnType); } return new DynamicMetaObject(expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var combinedArgs = new Expr[args.Length + 1]; combinedArgs[0] = target.Expression; Array.Copy(args.Select(a => a.Expression).ToArray(), 0, combinedArgs, 1, args.Length); var restrictions = target.Restrictions.Merge(BindingRestrictions.Combine(args)); Expr expression = Expr.Dynamic( context.CreateInvokeBinder(new CallInfo(args.Length)), typeof(object), combinedArgs); expression = MetamethodFallbacks.WrapStackTrace(expression, context, new FunctionStack(context,null, null, context.CurrentVariableIdentifier + "." + Name)); return new DynamicMetaObject(expression, restrictions); }
// Return the expression for getting target[indexes] // // Note, callers must ensure consistent restrictions are added for // the conversions on args and target. // public static Expression GetIndexingExpression( DynamicMetaObject target, DynamicMetaObject[] indexes) { Debug.Assert(target.HasValue && target.LimitType != typeof(Array)); var indexExpressions = indexes.Select( i => Expression.Convert(i.Expression, i.LimitType)) .ToArray(); //// CONS //if (target.LimitType == typeof(Cons)) //{ // // Call RuntimeHelper.GetConsElt // var args = new List<Expression>(); // // The first argument is the list // args.Add( // Expression.Convert( // target.Expression, // target.LimitType) // ); // args.AddRange(indexExpressions); // return Expression.Call( // typeof(RuntimeHelpers), // "GetConsElt", // null, // args.ToArray()); // // ARRAY //} //else if (target.LimitType.IsArray) { return Expression.ArrayAccess( Expression.Convert(target.Expression, target.LimitType), indexExpressions ); // INDEXER } else { var props = target.LimitType.GetProperties(); var indexers = props.Where(p => p.GetIndexParameters().Length > 0).ToArray(); indexers = indexers.Where(idx => idx.GetIndexParameters().Length == indexes.Length).ToArray(); var res = new List<PropertyInfo>(); foreach (var idxer in indexers) { if (RuntimeHelpers.ParametersMatchArguments( idxer.GetIndexParameters(), indexes)) { // all parameter types match res.Add(idxer); } } if (res.Count == 0) { return Expression.Throw( Expression.New( typeof(MissingMemberException) .GetConstructor(new Type[] { typeof(string) }), Expression.Constant( "Can't bind because there is no matching indexer.") ) ); } return Expression.MakeIndex( Expression.Convert(target.Expression, target.LimitType), res[0], indexExpressions); } }
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { var wrapper = this.Value as ExpressionContainer; var valueExpr = wrapper.Expression; var typeArgs = MockingUtil.TryGetTypeArgumentsFromBinder(binder); var candidateMethods = valueExpr.Type.GetAllMethods() .Where(m => MockingUtil.StringEqual(m.Name, binder.Name, binder.IgnoreCase) && m.IsStatic == wrapper.IsStatic) .Where(m => m.GetParameters().Length >= args.Length) .Select(m => { if (typeArgs == null) { return MockingUtil.TrySpecializeGenericMethod(m, args.Select(a => a.RuntimeType).ToArray()) ?? m; } else { return MockingUtil.TryApplyTypeArguments(m, typeArgs); } }) .Where(m => m != null) .Where(m => { var methodParams = m.GetParameters(); for (int i = 0; i < args.Length; ++i) { var matcher = UnwrapMatcher(args[i]); if (matcher != null) { var argType = matcher.ReturnType; if (!methodParams[i].ParameterType.IsAssignableFrom(argType)) return false; } } return true; }) .ToArray(); if (candidateMethods.Length == 0 && args.Length == 0) { return DoBindGetMember(binder.ReturnType, binder.Name, binder.IgnoreCase); } var methodArgs = args.Select(a => { var matcher = UnwrapMatcher(a); return matcher != null ? matcher.ReturnType.GetDefaultValue() : a.Value; }).ToArray(); object state; var method = (MethodInfo)MockingUtil.BindToMethod(MockingUtil.Default, candidateMethods, ref methodArgs, null, null, null, out state); var memberExpr = Expression.Call(!wrapper.IsStatic ? valueExpr : null, method, args.Select(FromArg).ToArray()); return CreateRecorder(memberExpr, binder.ReturnType); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { var wrapper = this.Value as ExpressionContainer; var valueExpr = wrapper.Expression; var property = PrivateAccessor.ResolveProperty(valueExpr.Type, "Item", false, indexes.Select(i => i.Value).ToArray(), !wrapper.IsStatic, value.Value, getter: false); if (property == null) ThrowMissingMemberException(valueExpr.Type, "Item"); var memberExpr = Expression.Assign( Expression.MakeIndex(!wrapper.IsStatic ? valueExpr : null, property, indexes.Select(FromArg)), FromArg(value)); return CreateRecorder(memberExpr, binder.ReturnType); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { return BindSetMember(binder.ReturnType, "Item", value.Expression, indexes.Select(i => i.Expression)); }
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) { var getProp = typeof(PrivateAccessor).GetMethod("GetProperty"); var call = Expression.Call(Expression.Convert(this.Expression, typeof(PrivateAccessor)), getProp, Expression.Constant("Item"), Expression.NewArrayInit(typeof(object), indexes.Select(a => Expression.Convert(a.Expression, typeof(object))))); return CreateMetaObject(call); }
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { var callResult = Expression.Variable(typeof(object)); var argsVar = Expression.Variable(typeof(object[])); MethodInfo invoke = typeof(PrivateAccessor).GetMethod("CallMethod", new[] { typeof(string), typeof(object[]) }); var invokeArgs = new List<Expression> { Expression.Constant(binder.Name), argsVar }; var typeArgs = MockingUtil.TryGetTypeArgumentsFromBinder(binder); if (typeArgs != null) { invoke = typeof(PrivateAccessor).GetMethod("CallMethodWithTypeArguments"); invokeArgs.Insert(1, Expression.Constant(typeArgs)); } var executionList = new List<Expression> { Expression.Assign(argsVar, Expression.NewArrayInit(typeof(object), args.Select(a => Expression.Convert(a.Expression, typeof(object))))), Expression.Assign(callResult, Expression.Call( Expression.Convert(this.Expression, typeof(PrivateAccessor)), invoke, invokeArgs.ToArray())), }; executionList.AddRange(args .Select((a, i) => new { expr = a.Expression, i }) .Where(p => p.expr is ParameterExpression) .Select(p => Expression.Assign(p.expr, Expression.Convert(Expression.ArrayIndex(argsVar, Expression.Constant(p.i)), p.expr.Type)))); executionList.Add(callResult); return CreateMetaObject(Expression.Block(new[] { argsVar, callResult }, executionList)); }
IEnumerable<Expr> MapArguments(DynamicMetaObject[] args, MethodInfo methodInfo, ref BindingRestrictions restrictions, out List<Expr> sideEffects, out Expr failExpr) { var parameters = methodInfo.GetParameters(); var isFromLua = methodInfo.Name.StartsWith(Constant.FUNCTION_PREFIX); var arguments = args.Select(arg => new Argument(arg.Expression, arg.LimitType)).ToList(); // Remove closure if (parameters.Length > 0 && parameters[0].ParameterType == typeof(Closure)) { var tempParameters = new ParameterInfo[parameters.Length - 1]; Array.Copy(parameters, 1, tempParameters, 0, tempParameters.Length); parameters = tempParameters; } ExpandLastArg(arguments, args, ref restrictions); DefaultParamValues(arguments, parameters); OverflowIntoParams(arguments, parameters); TrimArguments(arguments, parameters, out sideEffects); if (isFromLua) DefaultParamTypeValues(arguments, parameters); ConvertArgumentToParamType(arguments, parameters, out failExpr); if (failExpr == null && !isFromLua) CheckNumberOfArguments(arguments, parameters, out failExpr); return arguments.Select(arg => arg.Expression); }
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { MethodInfo method = _proxy._instanceType.GetMethod(binder.Name, args.Select(d => d.RuntimeType ?? d.LimitType.MakeByRefType()).ToArray()); if (method == null) return null; return new DynamicMetaObject(new DynamicMethod(method, _proxy._instance).GetMethodExpression(args.Select(arg => arg.Expression)), BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { var args2 = args.Select(x => x.Expression).ToArray(); var code = MakeExpression(false, Lambda.Members, args2); var restrictions = BindingRestrictions.GetInstanceRestriction(Expression, Value); return new DynamicMetaObject(code, restrictions); }
public override DynamicMetaObject BindInvokeMember( InvokeMemberBinder binder, DynamicMetaObject[] args) { FunctionMapping mapping; if (FunctionMapping.SupportedFunctions.TryGetValue(new ExpressionFunction.FunctionCall(binder.Name, args.Count()), out mapping)) { var expression = Expression.New(CtorWithExpressionAndExpressionFunction, new[] { Expression.Constant(this.Value), Expression.Constant(new ExpressionFunction(binder.Name, args.Select(x => x.Value))) }); return new DynamicMetaObject( expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); } else { return base.BindInvokeMember(binder, args); } }
public sealed override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) { var fallback = ((Func<Expression>)(() => { try { return base.BindCreateInstance(binder, args).Expression; } catch (Exception ex) { return Expression.Throw(Expression.Constant(ex)); } }))(); var dispatchResult = Expression.Parameter(typeof(DispatchResult), "dispatchResult"); var shim = Expression.Block(dispatchResult.MkArray(), // 1. var dispatchResult = DispatchCreateInstance(binder, `expression`, args); Expression.Assign(dispatchResult, Expression.Call( Expression.Constant(this), typeof(SimpleMetaObject).GetMethod("DispatchCreateInstance", BF.PrivateInstance), Expression.Constant(binder), Expression, Expression.NewArrayInit(typeof(Object), args.Select(arg => Expression.Convert(arg.Expression, typeof(Object)))))), // 2. return dispatchResult.Success ? dispatchResult.Result : `fallback`; Expression.Condition( Expression.Property(dispatchResult, "Success"), Expression.Convert(Expression.Property(dispatchResult, "Result"), binder.ReturnType), fallback, binder.ReturnType)); return new DynamicMetaObject(shim, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public sealed override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) { var fallback = ((Func<Expression>)(() => { try { return base.BindDeleteIndex(binder, indexes).Expression; } catch (Exception ex) { return Expression.Throw(Expression.Constant(ex)); } }))(); var dispatchResult = Expression.Parameter(typeof(DispatchResult), "dispatchResult"); var shim = Expression.Block(dispatchResult.MkArray(), // 1. var dispatchResult = DispatchDeleteIndex(binder, `expression`, indexes); Expression.Assign(dispatchResult, Expression.Call( Expression.Constant(this), typeof(SimpleMetaObject).GetMethod("DispatchDeleteIndex", BF.PrivateInstance), Expression.Constant(binder), Expression, Expression.NewArrayInit(typeof(Object), indexes.Select(index => Expression.Convert(index.Expression, typeof(Object)))))), // 2. if (!dispatchResult.Success) `fallback`; Expression.IfThen( Expression.Not(Expression.Property(dispatchResult, "Success")), fallback)); return new DynamicMetaObject(shim, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public override DynamicMetaObject BindInvokeMember( InvokeMemberBinder binder, DynamicMetaObject[] args) { if (FunctionMapping.ContainsFunction(binder.Name, args.Count())) { var expression = Expression.New(CtorWithExpressionAndExpressionFunction, new[] { Expression.Constant(this.Value), Expression.Constant(new ExpressionFunction(binder.Name, args.Select(x => x.Value))) }); return new DynamicMetaObject( expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); } else if (string.Equals(binder.Name, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) || string.Equals(binder.Name, ODataLiteral.All, StringComparison.OrdinalIgnoreCase)) { var expression = Expression.New(CtorWithExpressionAndExpressionFunction, new[] { Expression.Constant(this.Value), Expression.Constant(new ExpressionFunction(binder.Name, args.Select(x => x.Value))) }); return new DynamicMetaObject( expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); } else if (string.Equals(binder.Name, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) || string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase) || string.Equals(binder.Name, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase) || string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase)) { var functionName = string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase) ? ODataLiteral.IsOf : string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase) ? ODataLiteral.Cast : binder.Name; var expression = Expression.New(CtorWithExpressionAndExpressionFunction, new[] { Expression.Constant(this.Value), Expression.Constant(new ExpressionFunction( functionName, new [] { (this.Value as ODataExpression).IsNull ? null : this.Value, args.First().Value })) }); return new DynamicMetaObject( expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType)); } else { return base.BindInvokeMember(binder, args); } }
/// <summary> /// Performs the binding of the dynamic operation. /// </summary> /// <param name="target">The target of the dynamic operation.</param> /// <param name="args">An array of arguments of the dynamic operation.</param> /// <returns>The System.Dynamic.DynamicMetaObject representing the result of the binding.</returns> public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { // Look-up the method implementation for the given selector // and generate an expression (runtime code) for that method. // This also returns the restriction needed for the PIC. BindingRestrictions restrictions; SmalltalkClass receiverClass; Expression expression; MethodLookupHelper.GetMethodInformation(this.Runtime, this.Selector, this.GetSuperLookupScope(), target.Value, target, args, out receiverClass, out restrictions, out expression); // If no code was generated, method is missing, and we must do #doesNotUnderstand. See DoesNotUnderstandCallSiteBinder. if (expression == null) { DoesNotUnderstandCallSiteBinder binder = CallSiteBinderCache.GetCache(this.Runtime).CachedDoesNotUnderstandCallSiteBinder; if (binder == null) { binder = new DoesNotUnderstandCallSiteBinder(this.Runtime); CallSiteBinderCache.GetCache(this.Runtime).CachedDoesNotUnderstandCallSiteBinder = binder; } expression = Expression.Dynamic(binder, typeof(Object), target.Expression, Expression.Constant(this.Selector, typeof(object)), Expression.NewArrayInit(typeof(object), args.Select(d => Expression.Convert(d.Expression, typeof(object))).ToArray())); } // Return a DynamicMetaObject with the generated code. // Important here are the restrictions, which ensure that as long as <self> is // of the correct type, we can freely execute the code for the method we've just found. return new DynamicMetaObject(expression, target.Restrictions.Merge(restrictions)); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { return new DynamicMetaObject(Index.GetSetIndexedItemExpression(indexes.Select(i => i.Expression), value.Expression), BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }
public override DynamicMetaObject FallbackGetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { if (!target.HasValue) return Defer(target); if (target.Value == null) { return errorSuggestion ?? RuntimeHelper.CreateThrow( target, null, BindingRestrictions.GetExpressionRestriction( Expression.Equal( target.Expression, Expression.Constant(null, typeof (object)))), typeof (InvalidOperationException), "Attempted to get member from a null value."); } if (NumericHelper.IsNumeric(target.LimitType) || target.LimitType == typeof (string) || target.LimitType == typeof (UserData) || target.LimitType == typeof (Thread)) { var h = Expression.Parameter(typeof (object)); var args = new List<Expression> {h}; args.AddRange(indexes.Select(i => i.Expression)); var cond = Expression.Condition( RuntimeHelper.EmitGetBinHandler( _metaTables, target.Expression, Expression.Constant(null, typeof (object)), "__index", h), Expression.Condition( TypeHelper.EmitIsCallable(h), RValueList.EmitNarrow( Expression.Dynamic( InvokeBinder.New(_metaTables, new CallInfo(2)), typeof (object), h, target.Expression)), Expression.Dynamic( New(_metaTables, new CallInfo(1)), typeof (object), args.ToArray())), RuntimeHelper.EmitError()); var block = Expression.Block( typeof (object), new[] { h }, cond); return new DynamicMetaObject( block, BindingRestrictions.GetTypeRestriction( target.Expression, target.LimitType)); } // Find our own binding. const BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public; if (target.Value == null) { return errorSuggestion ?? RuntimeHelper.CreateThrow( target, null, BindingRestrictions.GetExpressionRestriction( Expression.Equal( target.Expression, Expression.Constant(null, typeof (object)))), typeof (InvalidOperationException), "Attempted to get member from a null value."); } var members = target.LimitType.GetMember("get_Item", flags); if (members.Length == 1) { // 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. return new DynamicMetaObject( Expression.MakeMemberAccess( Expression.Convert(target.Expression, members[0].DeclaringType), members[0]), RuntimeHelper.MatchTypeOrNull(target, target.LimitType)); } return errorSuggestion ?? RuntimeHelper.CreateThrow( target, null, RuntimeHelper.MatchTypeOrNull(target, target.LimitType), typeof (MissingMemberException), "cannot bind member, get_Item, on object" + target.Value); }
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { Expression self = Expression.Convert(Expression, LimitType); Expression[] parameters = new Expression[2]; parameters[0] = Expression.Constant(binder.Name); parameters[1] = Expression.NewArrayInit(typeof(object), args.Select(dmo => dmo.Expression).ToArray()); return new DynamicMetaObject( Expression.Call(self, typeof(AutofacRegistrationHelper).GetMethod("InvokeMember", BindingFlags.NonPublic | BindingFlags.Instance), parameters), BindingRestrictions.GetTypeRestriction(Expression, LimitType)); }