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.DynamicCache.GetInvokeBinder(new CallInfo(args.Length)), typeof(object), combinedArgs); return(new DynamicMetaObject(expression, restrictions)); }
/// <summary> /// Defers the binding of the operation until later time when the runtime values of all dynamic operation arguments have been computed. /// </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 <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public DynamicMetaObject Defer(DynamicMetaObject target, params DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); if (args == null) { return(MakeDeferred(target.Restrictions, target)); } else { return(MakeDeferred( target.Restrictions.Merge(BindingRestrictions.Combine(args)), args.AddFirst(target) )); } }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (ComBinder.TryBindInvoke(this, target, args, out DynamicMetaObject res)) { return(res); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New( typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }), Expression.Constant(Strings.CannotCall) ) ), target.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
// TODO: revisit private DynamicMetaObject MakeInvalidParametersRule(DefaultOverloadResolver binder, BindingRestrictions restrictions, BindingTarget bt) { var args = binder.Arguments; BindingRestrictions restriction = MakeSplatTests(binder.CallType, binder.Signature, true, args); // restrict to the exact type of all parameters for errors for (int i = 0; i < args.Count; i++) { args[i] = args[i].Restrict(args[i].GetLimitType()); } return(MakeError( binder.MakeInvalidParametersError(bt), restrictions.Merge(BindingRestrictions.Combine(args).Merge(restriction)), typeof(object) )); }
private DynamicMetaObject MakeMetaMethodCall(CallSignature signature, OverloadResolverFactory resolverFactory, TargetInfo targetInfo) { BindingRestrictions restrictions = BindingRestrictions.Combine(targetInfo.Arguments).Merge(targetInfo.Restrictions); if (targetInfo.Instance != null) { restrictions = targetInfo.Instance.Restrictions.Merge(restrictions); } DynamicMetaObject[] args; CallTypes callType; if (targetInfo.Instance != null) { args = ArrayUtils.Insert(targetInfo.Instance, targetInfo.Arguments); callType = CallTypes.ImplicitInstance; } else { args = targetInfo.Arguments; callType = CallTypes.None; } return CallMethod(resolverFactory.CreateOverloadResolver(args, signature, callType), targetInfo.Targets, restrictions); }
} // func GetRuntime internal static BindingRestrictions GetMethodSignatureRestriction(DynamicMetaObject target, DynamicMetaObject[] args) { BindingRestrictions restrictions = BindingRestrictions.Combine(args); if (target != null) { restrictions = restrictions .Merge(target.Restrictions) .Merge(GetSimpleRestriction(target)); } for (int i = 0; i < args.Length; i++) { restrictions = restrictions.Merge(GetSimpleRestriction(args[i])); } return(restrictions); } // func GetMethodSignatureRestriction
public static BindingRestrictions MergeTypeRestrictions(params DynamicMetaObject[] dmos) { var restrictions = BindingRestrictions.Combine(dmos); foreach (var dmo in dmos) { if (dmo.HasValue && dmo.Value == null) { restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(dmo.Expression, dmo.Value)); } else { restrictions = restrictions.Merge(BindingRestrictions.GetTypeRestriction(dmo.Expression, dmo.LimitType)); } } return(restrictions); }
public override DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { if (indexes[0].LimitType == typeof(string)) { return(new DynamicMetaObject( Expression.Dynamic(new TjsDeleteMemberBinder(_context, (string)indexes[0].Value, false), ReturnType, target.Expression), BindingRestrictions.Combine(ArrayUtils.Insert(target, indexes)).Merge( BindingRestrictions.GetInstanceRestriction(indexes[0].Expression, indexes[0].Value) ).Merge( BindingRestrictions.GetTypeRestriction(indexes[0].Expression, indexes[0].LimitType) ) )); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw(Expression.Constant(new MissingMemberException(indexes[0].Value.ToString())), typeof(object)), BindingRestrictions.Combine(ArrayUtils.Insert(target, indexes)).Merge(BindingRestrictions.GetTypeRestriction(indexes[0].Expression, indexes[0].LimitType)) )); }
// GetTargetArgsRestrictions generates the restrictions needed for the // MO resulting from binding an operation. This combines all existing // restrictions and adds some for arg conversions. targetInst indicates // whether to restrict the target to an instance (for operations on type // objects) or to a type (for operations on an instance of that type). // // NOTE, this function should only be used when the caller is converting // arguments to the same types as these restrictions. // public static BindingRestrictions GetTargetArgsRestrictions( DynamicMetaObject target, DynamicMetaObject[] args, bool instanceRestrictionOnTarget) { // Important to add existing restriction first because the // DynamicMetaObjects (and possibly values) we're looking at depend // on the pre-existing restrictions holding true. var restrictions = target.Restrictions.Merge(BindingRestrictions .Combine(args)); //LC Use instance restriction is value is null if (instanceRestrictionOnTarget || target.Value == null) { restrictions = restrictions.Merge( BindingRestrictions.GetInstanceRestriction( target.Expression, target.Value )); } else { restrictions = restrictions.Merge( BindingRestrictions.GetTypeRestriction( target.Expression, target.LimitType )); } for (int i = 0; i < args.Length; i++) { BindingRestrictions r; if (args[i].HasValue && args[i].Value == null) { r = BindingRestrictions.GetInstanceRestriction( args[i].Expression, null); } else { r = BindingRestrictions.GetTypeRestriction( args[i].Expression, args[i].LimitType); } restrictions = restrictions.Merge(r); } return(restrictions); }
/// <summary> /// Gets the resulting meta object for the full body. FinishCondition /// must have been called. /// </summary> public DynamicMetaObject GetMetaObject(params DynamicMetaObject[] types) { if (_body == null) { throw new InvalidOperationException("FinishCondition should have been called"); } if (_isError) { return(new ErrorMetaObject( _body, BindingRestrictions.Combine(types).Merge(Restrictions) )); } return(new DynamicMetaObject( _body, BindingRestrictions.Combine(types).Merge(Restrictions) )); }
public override DynamicMetaObject FallbackInvoke( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { var argexprs = new Expression[args.Length + 1]; for (var i = 0; i < args.Length; i++) { argexprs[i + 1] = args[i].Expression; } argexprs[0] = target.Expression; return(new DynamicMetaObject( Runtime.CompileDynamicExpression( Runtime.GetInvokeBinder(args.Length), typeof(object), argexprs), target.Restrictions.Merge( BindingRestrictions.Combine(args)))); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion) { var argExpressions = new Expression[args.Length + 1]; for (var i = 0; i < args.Length; i++) { argExpressions[i + 1] = args[i].Expression; } argExpressions[0] = target.Expression; // Just "defer" since we have code in SymplInvokeBinder that knows what to do, and // typically this fallback is from a language like Python that passes a DynamicMetaObject // with HasValue == false. return(new DynamicMetaObject(Expression.Dynamic( // This call site doesn't share any L2 caching since we don't call // GetInvokeBinder from Sympl. We aren't plumbed to get the runtime instance here. new SymplInvokeBinder(new CallInfo(args.Length)), typeof(Object), // ret type argExpressions), // No new restrictions since SymplInvokeBinder will handle it. target.Restrictions.Merge(BindingRestrictions.Combine(args)))); }
internal DynamicMetaObject Invoke() { _keywordArgNames = _callInfo.ArgumentNames.ToArray(); _totalExplicitArgs = _args.Length; Type[] marshalArgTypes = new Type[_args.Length]; // We already tested the instance, so no need to test it again for (int i = 0; i < _args.Length; i++) { DynamicMetaObject curMo = _args[i]; marshalArgTypes[i] = MarshalType(curMo, _isByRef[i]); } _varEnumSelector = new VarEnumSelector(marshalArgTypes); return(new DynamicMetaObject( CreateScope(MakeIDispatchInvokeTarget()), BindingRestrictions.Combine(_args).Merge(_restrictions) )); }
internal static DynamicMetaObject CreateThrow( DynamicMetaObject target, DynamicMetaObject[] args, BindingRestrictions restrictions, Type exception, object[] exceptionArgs) { if (exception is null) { throw new ArgumentNullException($"Argument {nameof(exception)} is null!"); } Expression[] argExpressions = null; var argTypes = Type.EmptyTypes; if (exceptionArgs != null) { var argsLength = exceptionArgs.Length; argExpressions = new Expression[argsLength]; argTypes = new Type[argsLength]; for (int i = 0; i < exceptionArgs.Length; i++) { var expression = Expression.Constant(exceptionArgs[i]); argExpressions[i] = expression; argTypes[i] = expression.Type; } } var constructor = exception.GetConstructor(argTypes); if (constructor is null) { throw new ArgumentException($"Type {exception.ToString()} coming from argument {nameof(exception)} doesn't contain a constructor with the given signature."); } return(new DynamicMetaObject(Expression.Throw( Expression.New(constructor, argExpressions), typeof(object)), target.Restrictions.Merge(BindingRestrictions.Combine(args).Merge(restrictions)))); }
// CreateThrow is a convenience function for when binders cannot bind. // They need to return a DynamicMetaObject with appropriate restrictions // that throws. Binders never just throw due to the protocol since // a binder or MO down the line may provide an implementation. // // It returns a DynamicMetaObject whose expr throws the exception, and // ensures the expr's type is object to satisfy the CallSite return type // constraint. // // A couple of calls to CreateThrow already have the args and target // restrictions merged in, but BindingRestrictions.Merge doesn't add // duplicates. // public static DynamicMetaObject CreateThrow (DynamicMetaObject target, DynamicMetaObject[] args, BindingRestrictions moreTests, Type exception, params object[] exceptionArgs) { Expression[] argExprs = null; Type[] argTypes = Type.EmptyTypes; int i; if (exceptionArgs != null) { i = exceptionArgs.Length; argExprs = new Expression[i]; argTypes = new Type[i]; i = 0; foreach (object o in exceptionArgs) { Expression e = Expression.Constant(o); argExprs[i] = e; argTypes[i] = e.Type; i += 1; } } ConstructorInfo constructor = exception.GetConstructor(argTypes); if (constructor == null) { throw new ArgumentException( "Type doesn't have constructor with a given signature"); } return(new DynamicMetaObject( Expression.Throw( Expression.New(constructor, argExprs), // Force expression to be type object so that DLR CallSite // code things only type object flows out of the CallSite. typeof(object)), target.Restrictions.Merge(BindingRestrictions.Combine(args)) .Merge(moreTests))); }
// TODO: support for IgnoreCase in underlying ScriptScope APIs public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder action, DynamicMetaObject[] args) { var fallback = action.FallbackInvokeMember(this, args); var result = Expression.Variable(typeof(object), "result"); var fallbackInvoke = action.FallbackInvoke(new DynamicMetaObject(result, BindingRestrictions.Empty), args, null); return(new DynamicMetaObject( Expression.Block( new ParameterExpression[] { result }, Expression.Condition( Expression.Call( Expression.Convert(Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("TryGetVariable", new[] { typeof(string), typeof(object).MakeByRefType() }), Expression.Constant(action.Name), result ), Expression.Convert(fallbackInvoke.Expression, typeof(object)), Expression.Convert(fallback.Expression, typeof(object)) ) ), BindingRestrictions.Combine(args).Merge(BindingRestrictions.GetTypeRestriction(Expression, typeof(ScriptScope))).Merge(fallback.Restrictions) )); }
private DynamicMetaObject /*!*/ MakeDynamicMemberAccess(DynamicMetaObjectBinder /*!*/ member, string /*!*/ name, MemberAccess access, DynamicMetaObject /*!*/[] /*!*/ args) { DynamicMetaObject self = Restrict(typeof(OldInstance)); Expression target; ParameterExpression tmp = Ast.Variable(typeof(object), "result"); switch (access) { case MemberAccess.Invoke: target = Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Expression.Not( Expression.TypeIs( Expression.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(name) ) ), typeof(OperationFailed) ) ), ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(tmp, BindingRestrictions.Empty), args, null).Expression, AstUtils.Convert( ((InvokeMemberBinder)member).FallbackInvokeMember(this, args).Expression, typeof(object) ) ) ); break; case MemberAccess.Get: target = Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Expression.Not( Expression.TypeIs( Expression.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(name) ) ), typeof(OperationFailed) ) ), tmp, AstUtils.Convert( FallbackGet(member, args), typeof(object) ) ) ); break; case MemberAccess.Set: target = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceSetCustomMember)), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(name), AstUtils.Convert(args[1].Expression, typeof(object)) ); break; case MemberAccess.Delete: target = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDeleteCustomMember)), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(name) ); break; default: throw new InvalidOperationException(); } return(new DynamicMetaObject( target, self.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
private DynamicMetaObject /*!*/ MakeMemberAccess(DynamicMetaObjectBinder /*!*/ member, string name, MemberAccess access, params DynamicMetaObject /*!*/[] /*!*/ args) { DynamicMetaObject self = Restrict(typeof(OldInstance)); CustomInstanceDictionaryStorage dict; int key = GetCustomStorageSlot(name, out dict); if (key == -1) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " NoOptimized"); return(MakeDynamicMemberAccess(member, name, access, args)); } ParameterExpression tmp = Ast.Variable(typeof(object), "dict"); Expression target; ValidationInfo test = new ValidationInfo( Ast.NotEqual( Ast.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceGetOptimizedDictionary)), self.Expression, AstUtils.Constant(dict.KeyVersion) ) ), AstUtils.Constant(null) ) ); PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " Optimized"); switch (access) { case MemberAccess.Invoke: ParameterExpression value = Ast.Variable(typeof(object), "value"); target = Ast.Block( new[] { value }, Ast.Condition( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.TryOldInstanceDictionaryGetValueHelper)), tmp, Ast.Constant(key), AstUtils.Convert(Expression, typeof(object)), value ), AstUtils.Convert( ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(value, BindingRestrictions.Empty), args, null).Expression, typeof(object) ), AstUtils.Convert( ((InvokeMemberBinder)member).FallbackInvokeMember(self, args).Expression, typeof(object) ) ) ); break; case MemberAccess.Get: // BUG: There's a missing Fallback path here that's always been present even // in the version that used rules. target = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDictionaryGetValueHelper)), tmp, AstUtils.Constant(key), AstUtils.Convert(Expression, typeof(object)) ); break; case MemberAccess.Set: target = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDictionarySetExtraValue)), tmp, AstUtils.Constant(key), AstUtils.Convert(args[1].Expression, typeof(object)) ); break; case MemberAccess.Delete: target = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDeleteCustomMember)), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), AstUtils.Convert(Expression, typeof(OldInstance)), AstUtils.Constant(name) ); break; default: throw new InvalidOperationException(); } return(BindingHelpers.AddDynamicTestAndDefer( member, new DynamicMetaObject( target, BindingRestrictions.Combine(args).Merge(self.Restrictions) ), args, test, tmp )); }
private DynamicMetaObject /*!*/ InvokeWorker(DynamicMetaObjectBinder /*!*/ invoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke"); DynamicMetaObject self = Restrict(typeof(OldInstance)); Expression[] exprArgs = new Expression[args.Length + 1]; for (int i = 0; i < args.Length; i++) { exprArgs[i + 1] = args[i].Expression; } ParameterExpression tmp = Ast.Variable(typeof(object), "callFunc"); exprArgs[0] = tmp; return(new DynamicMetaObject( // we could get better throughput w/ a more specific rule against our current custom old class but // this favors less code generation. Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Expression.Not( Expression.TypeIs( Expression.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)), codeContext, self.Expression, AstUtils.Constant("__call__") ) ), typeof(OperationFailed) ) ), Ast.Block( Utils.Try( Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrameCodeContext)), codeContext), Ast.Assign( tmp, DynamicExpression.Dynamic( PythonContext.GetPythonContext(invoke).Invoke( BindingHelpers.GetCallSignature(invoke) ), typeof(object), ArrayUtils.Insert(codeContext, exprArgs) ) ) ).Finally( Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame))) ), tmp ), Utils.Convert( BindingHelpers.InvokeFallback(invoke, codeContext, this, args).Expression, typeof(object) ) ) ), self.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { DynamicMetaObject dynamicMetaObject = errorSuggestion; DynamicMetaObject dynamicMetaObject1 = dynamicMetaObject; if (dynamicMetaObject == null) { PSInvokeBinder pSInvokeBinder = new PSInvokeBinder(base.CallInfo); Type type = typeof(object); IEnumerable <DynamicMetaObject> dynamicMetaObjects = args.Prepend <DynamicMetaObject>(target); dynamicMetaObject1 = new DynamicMetaObject(Expression.Dynamic(pSInvokeBinder, type, dynamicMetaObjects.Select <DynamicMetaObject, Expression>((DynamicMetaObject dmo) => dmo.Expression)), target.Restrictions.Merge(BindingRestrictions.Combine(args))); } return(dynamicMetaObject1); }
private BindingRestrictions ComTypeLibInfoRestrictions(params DynamicMetaObject[] args) { return(BindingRestrictions.Combine(args).Merge(BindingRestrictions.GetTypeRestriction(Expression, typeof(ComTypeLibInfo)))); }
private static DynamicMetaObject TryPrimitiveCompare(OperatorInfo info, DynamicMetaObject[] args) { if (args[0].GetLimitType().GetNonNullableType() == args[1].GetLimitType().GetNonNullableType() && args[0].GetLimitType().IsNumeric()) { Expression arg0 = args[0].Expression; Expression arg1 = args[1].Expression; // TODO: Nullable<PrimitveType> Support Expression expr; switch (info.Operator) { case ExpressionType.Equal: expr = Expression.Equal(arg0, arg1); break; case ExpressionType.NotEqual: expr = Expression.NotEqual(arg0, arg1); break; case ExpressionType.GreaterThan: expr = Expression.GreaterThan(arg0, arg1); break; case ExpressionType.LessThan: expr = Expression.LessThan(arg0, arg1); break; case ExpressionType.GreaterThanOrEqual: expr = Expression.GreaterThanOrEqual(arg0, arg1); break; case ExpressionType.LessThanOrEqual: expr = Expression.LessThanOrEqual(arg0, arg1); break; default: throw new InvalidOperationException(); } return(new DynamicMetaObject( expr, BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg0, args[0].GetLimitType()).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg1, args[0].GetLimitType())).Merge(BindingRestrictions.Combine(args)) )); } return(null); }
public BindingRestrictions GetAllRestrictions() { return(BindingRestrictions.Combine(_objects)); }
private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args) { if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All)) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (oper == IndexType.Get) { return(new DynamicMetaObject( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), restrictions )); } return(new DynamicMetaObject( Expression.Assign( Expression.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType()) ), restrictions.Merge(args[1].Restrictions) )); } return(null); }
private static DynamicMetaObject TryMakeDefaultUnaryRule(OperatorInfo info, DynamicMetaObject[] args) { if (args.Length == 1) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); switch (info.Operator) { case ExpressionType.IsTrue: if (args[0].GetLimitType() == typeof(bool)) { return(args[0]); } break; case ExpressionType.Negate: if (args[0].GetLimitType().IsArithmetic()) { return(new DynamicMetaObject( Expression.Negate(args[0].Expression), restrictions )); } break; case ExpressionType.Not: if (args[0].GetLimitType().IsIntegerOrBool()) { return(new DynamicMetaObject( Expression.Not(args[0].Expression), restrictions )); } break; } } return(null); }
public void CombineRestrictionsFromNull() { Assert.Same(BindingRestrictions.Empty, BindingRestrictions.Combine(null)); }
internal static DynamicMetaObject TranslateArguments(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject function, DynamicMetaObject /*!*/[] args, bool hasSelf, string name) { if (hasSelf) { args = ArrayUtils.RemoveFirst(args); } CallSignature sig = BindingHelpers.GetCallSignature(call); if (sig.HasDictionaryArgument()) { int index = sig.IndexOf(ArgumentType.Dictionary); DynamicMetaObject dict = args[index]; if (!(dict.Value is IDictionary) && dict.Value != null) { // The DefaultBinder only handles types that implement IDictionary. Here we have an // arbitrary user-defined mapping type. We'll convert it into a PythonDictionary // and then have an embedded dynamic site pass that dictionary through to the default // binder. DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args); dynamicArgs[index + 1] = new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonDictionary)), codeContext, args[index].Expression, AstUtils.Constant(name) ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()), PythonOps.UserMappingToPythonDictionary(PythonContext.GetPythonContext(call).SharedContext, dict.Value, name) ); if (call is IPythonSite) { dynamicArgs = ArrayUtils.Insert( new DynamicMetaObject(codeContext, BindingRestrictions.Empty), dynamicArgs ); } return(new DynamicMetaObject( DynamicExpression.Dynamic( call, typeof(object), DynamicUtils.GetExpressions(dynamicArgs) ), BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType())) )); } } if (sig.HasListArgument()) { int index = sig.IndexOf(ArgumentType.List); DynamicMetaObject str = args[index]; // TODO: ANything w/ __iter__ that's not an IList<object> if (!(str.Value is IList <object>) && str.Value is IEnumerable) { // The DefaultBinder only handles types that implement IList<object>. Here we have a // string. We'll convert it into a tuple // and then have an embedded dynamic site pass that tuple through to the default // binder. DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args); dynamicArgs[index + 1] = new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeTupleFromSequence)), Expression.Convert(args[index].Expression, typeof(object)) ), BindingRestrictions.Empty ); if (call is IPythonSite) { dynamicArgs = ArrayUtils.Insert( new DynamicMetaObject(codeContext, BindingRestrictions.Empty), dynamicArgs ); } return(new DynamicMetaObject( DynamicExpression.Dynamic( call, typeof(object), DynamicUtils.GetExpressions(dynamicArgs) ), function.Restrictions.Merge( BindingRestrictions.Combine(args).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(str.Expression, str.GetLimitType())) ) )); } } return(null); }
internal static DynamicMetaObject Call(DynamicMetaObjectBinder /*!*/ call, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args) { Assert.NotNull(call, args); Assert.NotNullItems(args); if (target.NeedsDeferral()) { return(call.Defer(ArrayUtils.Insert(target, args))); } foreach (DynamicMetaObject mo in args) { if (mo.NeedsDeferral()) { RestrictTypes(args); return(call.Defer( ArrayUtils.Insert(target, args) )); } } DynamicMetaObject self = target.Restrict(target.GetLimitType()); ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target); PythonType pt = DynamicHelpers.GetPythonType(target.Value); PythonContext pyContext = PythonContext.GetPythonContext(call); // look for __call__, if it's present dispatch to it. Otherwise fall back to the // default binder PythonTypeSlot callSlot; if (!typeof(Delegate).IsAssignableFrom(target.GetLimitType()) && pt.TryResolveSlot(pyContext.SharedContext, "__call__", out callSlot)) { ConditionalBuilder cb = new ConditionalBuilder(call); callSlot.MakeGetExpression( pyContext.Binder, PythonContext.GetCodeContext(call), self, GetPythonType(self), cb ); if (!cb.IsFinal) { cb.FinishCondition(GetCallError(call, self)); } Expression[] callArgs = ArrayUtils.Insert( PythonContext.GetCodeContext(call), cb.GetMetaObject().Expression, DynamicUtils.GetExpressions(args) ); Expression body = DynamicExpression.Dynamic( PythonContext.GetPythonContext(call).Invoke( BindingHelpers.GetCallSignature(call) ), typeof(object), callArgs ); body = Ast.TryFinally( Ast.Block( Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrame)), Ast.Constant(pyContext)), body ), Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame))) ); return(BindingHelpers.AddDynamicTestAndDefer( call, new DynamicMetaObject(body, self.Restrictions.Merge(BindingRestrictions.Combine(args))), args, valInfo )); } return(null); }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (target.HasValue && target.Value == null) { return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("Cannot call {0} method named {1} on nil", _isStatic ? "static" : "instance", this.Name))), typeof(object)), BindingRestrictions.GetInstanceRestriction(target.Expression, null))); } Type typeToUse = _isStatic && target.Value is Type ? (Type)target.Value : target.LimitType; IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(args.Length + (_isStatic ? 0 : 1)); if (!_isStatic) { argsPlus.Add(target); } foreach (DynamicMetaObject arg in args) { argsPlus.Add(arg); } OverloadResolverFactory factory = _context.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(args.Length), _isStatic ? CallTypes.None : CallTypes.ImplicitInstance); BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | (_isStatic ? BindingFlags.Static : BindingFlags.Instance); IList <MethodBase> methods = new List <MethodBase>(typeToUse.GetMethods(flags).Where <MethodBase>(x => x.Name == Name && x.GetParameters().Length == args.Length)); if (methods.Count > 0) { BindingTarget bt; DynamicMetaObject dmo = _context.Binder.CallMethod( res, methods, target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))), Name, NarrowingLevel.None, NarrowingLevel.All, out bt); dmo = DynUtils.MaybeBoxReturnValue(dmo); //; Console.WriteLine(dmo.Expression.DebugView); return(dmo); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New(typeof(MissingMethodException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(String.Format("No matching member {0} taking {1} args for {2}", this.Name, args.Length, typeToUse.Name))), typeof(object)), target.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target).Merge(BindingRestrictions.Combine(args))))); }
/// <summary> /// Produces a rule for comparing a value to null - supports comparing object references and nullable types. /// </summary> private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args) { Type otherType = args[1].GetLimitType(); BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (args[0].GetLimitType() == typeof(DynamicNull)) { if (!otherType.IsValueType) { return(new DynamicMetaObject( Expression.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } else if (otherType == typeof(DynamicNull)) { if (!args[0].GetLimitType().IsValueType) { return(new DynamicMetaObject( Expression.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } return(null); }