public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) { if (self.NeedsDeferral()) { return Defer(self); } return Binder.Binder.DeleteMember(Name, self, AstUtils.Constant(Binder.Context)); }
protected override DynamicMetaObject SetBoundValue(OverloadResolverFactory factory, ActionBinder binder, Type type, DynamicMetaObject value, DynamicMetaObject instance, DynamicMetaObject errorSuggestion) { return new DynamicMetaObject( Expression.Condition( Ast.Call( typeof(PythonOps).GetMethod("SlotTrySetValue"), ((PythonOverloadResolverFactory)factory)._codeContext, AstUtils.Constant(GetSlot(), typeof(PythonTypeSlot)), AstUtils.Convert( instance.Expression, typeof(object) ), AstUtils.Constant(DynamicHelpers.GetPythonTypeFromType(type)), value.Expression ), AstUtils.Convert(value.Expression, typeof(object)), errorSuggestion != null ? errorSuggestion.Expression : Expression.Throw( Expression.Call( typeof(PythonOps).GetMethod("AttributeErrorForMissingAttribute", new Type[] { typeof(object), typeof(string) }), instance.Expression, Expression.Constant(Name) ), typeof(object) ) ), BindingRestrictions.Empty ); }
public override DynamicMetaObject FallbackBinaryOperation( DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { DynamicMetaObject left = target; DynamicMetaObject right = arg; if (Operation != ExpressionType.LessThan) throw new NotImplementedException(); if (left.LimitType != right.LimitType) { throw new Exception(String.Format( "attempt to compare {0} with {1}", left.LimitType.Name, right.LimitType.Name)); } if (left.LimitType != typeof(string) && left.LimitType != typeof(double)) { throw new Exception(String.Format( "attempt to compare two {0} values", left.LimitType.Name)); } return _binder.DoOperation(Operation, left, right); }
public override DynamicMetaObject/*!*/ BindInvokeMember(InvokeMemberBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) { DynamicMetaObject errorSuggestion = null; if (_baseMetaObject != null) { errorSuggestion = _baseMetaObject.BindInvokeMember(action, args); } CodeContext context = BinderState.GetBinderState(action).Context; IPythonObject sdo = Value; PythonTypeSlot foundSlot; if (TryGetGetAttribute(context, sdo.PythonType, out foundSlot)) { // we'll always fetch the value, go ahead and invoke afterwards. return BindingHelpers.GenericCall(action, this, args); } bool isOldStyle; bool systemTypeResolution; foundSlot = FindSlot(context, action.Name, sdo, out isOldStyle, out systemTypeResolution); if (foundSlot != null && !systemTypeResolution) { // we found the member in the type dictionary, not a .NET type, go ahead and // do the get & invoke. return BindingHelpers.GenericCall(action, this, args); } // it's a normal .NET member, let the calling language handle it how it usually does return action.FallbackInvokeMember(this, args, errorSuggestion); }
public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation) { ContractUtils.RequiresNotNull(binder, "binder"); ContractUtils.RequiresNotNull(instance, "instance"); if (TryGetMetaObject(ref instance)) { // // Demand Full Trust to proceed with the binding. // new PermissionSet(PermissionState.Unrestricted).Demand(); var comGetMember = new ComGetMemberBinder(binder, delayInvocation); result = instance.BindGetMember(comGetMember); if (result.Expression.Type.IsValueType) { result = new DynamicMetaObject( Expression.Convert(result.Expression, typeof(object)), result.Restrictions ); } return true; } else { result = null; return false; } }
public static DynamicMetaObject BindCatchAllPrimitive(DynamicMetaObject target, DynamicMetaObject[] args, Type returnType) { var method = typeof(BonsaiPrimitives).GetMethodsWith<CatchAllPrimitiveAttribute>( (mi, capi) => capi.Type == null || ( target.LimitType.IsAssignableFrom(capi.Type) || ( capi.Type.IsGenericTypeDefinition && target.LimitType.IsGenericType && capi.Type.GetGenericArguments().Length == target.LimitType.GetGenericArguments().Length && capi.Type.MakeGenericType(target.LimitType.GetGenericArguments()).IsAssignableFrom(target.LimitType)))) .FirstOrDefault(); // assume that if the method is generic than the matched type is also generic and it gets the same parameters if (method != null && method.IsGenericMethodDefinition) method = method.MakeGenericMethod(target.LimitType.GetGenericArguments()); if (method != null) { return new DynamicMetaObject( Expression.Convert( Expression.Call( null, method, new Expression[] { Expression.Convert(target.Expression, method.GetParameters()[0].ParameterType), args[0].Expression, Expression.NewArrayInit( typeof(object), args.Subarray(1).Select(a => Expression.Convert(a.Expression, typeof(object)))) }), returnType), BindingRestrictions.GetTypeRestriction(target.Expression, target.Value.GetType())); } else { throw new Exception("Binding failed"); } }
public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) { if (self.NeedsDeferral()) { return Defer(self); } return Context.Binder.DeleteMember(Name, self, new PythonOverloadResolverFactory(_context.Binder, AstUtils.Constant(Context.SharedContext))); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { // // Demand Full Trust to proceed with the binding. // new PermissionSet(PermissionState.Unrestricted).Demand(); ComMethodDesc method; var target = _callable.DispatchComObject; var name = _callable.MemberName; bool holdsNull = value.Value == null && value.HasValue; if (target.TryGetPropertySetter(name, out method, value.LimitType, holdsNull) || target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull)) { bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes); isByRef = isByRef.AddLast(false); var result = BindComInvoke(method, indexes.AddLast(value), binder.CallInfo, isByRef); // Make sure to return the value; some languages need it. return new DynamicMetaObject( Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))), result.Restrictions ); } return base.BindSetIndex(binder, indexes, value); }
/// <summary> /// Creating a standard .NET type is easy - we just call it's constructor with the provided /// arguments. /// </summary> private DynamicMetaObject/*!*/ MakeStandardDotNetTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) { CallSignature signature = BindingHelpers.GetCallSignature(call); BinderState state = BinderState.GetBinderState(call); MethodBase[] ctors = CompilerHelpers.GetConstructors(Value.UnderlyingSystemType, state.Binder.PrivateBinding); if (ctors.Length > 0) { return state.Binder.CallMethod( new ParameterBinderWithCodeContext(state.Binder, codeContext), ctors, args, signature, Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value)) ); } else { return new DynamicMetaObject( Ast.Throw( Ast.New( typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }), Ast.Constant("Cannot create instances of " + Value.Name) ) ), Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value)) ); } }
internal ComInvokeBinder( CallInfo callInfo, DynamicMetaObject[] args, bool[] isByRef, BindingRestrictions restrictions, Expression method, Expression dispatch, ComMethodDesc methodDesc ) { Debug.Assert(callInfo != null, "arguments"); Debug.Assert(args != null, "args"); Debug.Assert(isByRef != null, "isByRef"); Debug.Assert(method != null, "method"); Debug.Assert(dispatch != null, "dispatch"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch"); _method = method; _dispatch = dispatch; _methodDesc = methodDesc; _callInfo = callInfo; _args = args; _isByRef = isByRef; _restrictions = restrictions; // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with _instance = dispatch; }
public static DynamicMetaObject TryBind(RubyContext/*!*/ context, GetMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target) { Assert.NotNull(context, target); var metaBuilder = new MetaObjectBuilder(); var contextExpression = AstUtils.Constant(context); RubyClass targetClass = context.GetImmediateClassOf(target.Value); MethodResolutionResult method; RubyMemberInfo methodMissing = null; using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(target.Value, targetClass, target.Expression, context, contextExpression); method = targetClass.ResolveMethodForSiteNoLock(binder.Name, RubyClass.IgnoreVisibility); if (method.Found) { methodMissing = targetClass.ResolveMethodForSiteNoLock(Symbols.MethodMissing, RubyClass.IgnoreVisibility).Info; } } if (method.Found) { // we need to create a bound member: metaBuilder.Result = AstUtils.Constant(new RubyMethod(target.Value, method.Info, binder.Name)); } else { // TODO: // We need to throw an exception if we don't find method_missing so that our version update optimization works: // This limits interop with other languages. // // class B CLR type with method 'foo' // class C < B Ruby class // x = C.new // // 1. x.GET("foo") from Ruby // No method found or CLR method found -> fallback to Python // Python might see its method foo or might just fallback to .NET, // in any case it will add rule [1] with restriction on type of C w/o Ruby version check. // 2. B.define_method("foo") // This doesn't update C due to the optimization (there is no overridden method foo in C). // 3. x.GET("foo") from Ruby // This will not invoke the binder since the rule [1] is still valid. // object symbol = SymbolTable.StringToId(binder.Name); RubyCallAction.BindToMethodMissing(metaBuilder, new CallArguments( new DynamicMetaObject(contextExpression, BindingRestrictions.Empty, context), new[] { target, new DynamicMetaObject(AstUtils.Constant(symbol), BindingRestrictions.Empty, symbol) }, RubyCallSignature.Simple(1) ), binder.Name, methodMissing, method.IncompatibleVisibility, false ); } // TODO: we should return null if we fail, we need to throw exception for now: return metaBuilder.CreateMetaObject(binder, DynamicMetaObject.EmptyMetaObjects); }
public DynamicMetaObject/*!*/ Invoke(PythonInvokeBinder/*!*/ pythonInvoke, Expression/*!*/ codeContext, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) { DynamicMetaObject translated = BuiltinFunction.TranslateArguments(pythonInvoke, codeContext, target, args, false, Value.Name); if (translated != null) { return translated; } return InvokeWorker(pythonInvoke, args, codeContext); }
public override DynamicMetaObject/*!*/ FallbackInvokeMember(DynamicMetaObject/*!*/ self, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject/*!*/ onBindingError) { var result = TryBind(_context, this, self, args); if (result != null) { return result; } // TODO: return ((DefaultBinder)_context.Binder).GetMember(Name, self, Ast.Null(typeof(CodeContext)), true); throw new NotImplementedException(); }
public override DynamicMetaObject/*!*/ FallbackGetMember(DynamicMetaObject/*!*/ self, DynamicMetaObject/*!*/ onBindingError) { var result = TryBind(_context, this, self); if (result != null) { return result; } // TODO: remove CodeContext return ((DefaultBinder)_context.Binder).GetMember(Name, self, AstUtils.Constant(null, typeof(CodeContext)), true); }
public override DynamicMetaObject/*!*/ FallbackCreateInstance(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject errorSuggestion) { var result = TryBind(_context, this, target, args); if (result != null) { return result; } throw new NotImplementedException(); // TODO: //return ((DefaultBinder)_context.Binder).Create(.GetMember(Name, self, Ast.Null(typeof(CodeContext)), true); }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinFunc Operation " + action.Operation); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinFunc Operation"); switch (action.Operation) { case PythonOperationKind.CallSignatures: return PythonProtocol.MakeCallSignatureOperation(this, Value.Targets); } return null; }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { return new DynamicMetaObject( Expression.Call( typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), Expression.Constant("FallbackInvoke"), target.Expression ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) ); }
/// <summary> /// Performs the binding of the dynamic set member operation. /// </summary> /// <param name="target">The target of the dynamic set member operation.</param> /// <param name="args">An array of arguments of the dynamic set member operation.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.RequiresNotNull(args, "args"); ContractUtils.Requires(args.Length == 1, "args"); var arg0 = args[0]; ContractUtils.RequiresNotNull(arg0, "args"); return target.BindSetMember(this, arg0); }
public override DynamicMetaObject/*!*/ BindOperation(OperationBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) { switch (action.Operation) { case StandardOperators.CallSignatures: return MakeCallSignatureRule(this); case StandardOperators.IsCallable: return MakeIsCallableRule(this); } return base.BindOperation(action, args); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { return errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New( typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }), Expression.Constant(Strings.CannotCall) ) ), target.Restrictions.Merge(BindingRestrictions.Combine(args)) ); }
/// <summary> /// Python's Invoke is a non-standard action. Here we first try to bind through a Python /// internal interface (IPythonInvokable) which supports CallSigantures. If that fails /// and we have an IDO then we translate to the DLR protocol through a nested dynamic site - /// this includes unsplatting any keyword / position arguments. Finally if it's just a plain /// old .NET type we use the default binder which supports CallSignatures. /// </summary> public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) { Debug.Assert(args.Length > 0); DynamicMetaObject cc = target; DynamicMetaObject actualTarget = args[0]; args = ArrayUtils.RemoveFirst(args); Debug.Assert(cc.GetLimitType() == typeof(CodeContext)); return BindWorker(cc, actualTarget, args); }
public static DynamicMetaObject/*!*/ Operation(BinaryOperationBinder/*!*/ operation, DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback BinaryOperator " + target.LimitType.FullName + " " + operation.Operation + " " + arg.LimitType.FullName); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString()); DynamicMetaObject[] args = new[] { target, arg }; if (BindingHelpers.NeedsDeferral(args)) { return operation.Defer(target, arg); } ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args); PythonOperationKind? pyOperator = null; switch (operation.Operation) { case ExpressionType.Add: pyOperator = PythonOperationKind.Add; break; case ExpressionType.And: pyOperator = PythonOperationKind.BitwiseAnd; break; case ExpressionType.Divide: pyOperator = PythonOperationKind.Divide; break; case ExpressionType.ExclusiveOr: pyOperator = PythonOperationKind.ExclusiveOr; break; case ExpressionType.Modulo: pyOperator = PythonOperationKind.Mod; break; case ExpressionType.Multiply: pyOperator = PythonOperationKind.Multiply; break; case ExpressionType.Or: pyOperator = PythonOperationKind.BitwiseOr; break; case ExpressionType.Power: pyOperator = PythonOperationKind.Power; break; case ExpressionType.RightShift: pyOperator = PythonOperationKind.RightShift; break; case ExpressionType.LeftShift: pyOperator = PythonOperationKind.LeftShift; break; case ExpressionType.Subtract: pyOperator = PythonOperationKind.Subtract; break; case ExpressionType.AddAssign: pyOperator = PythonOperationKind.InPlaceAdd; break; case ExpressionType.AndAssign: pyOperator = PythonOperationKind.InPlaceBitwiseAnd; break; case ExpressionType.DivideAssign: pyOperator = PythonOperationKind.InPlaceDivide; break; case ExpressionType.ExclusiveOrAssign: pyOperator = PythonOperationKind.InPlaceExclusiveOr; break; case ExpressionType.ModuloAssign: pyOperator = PythonOperationKind.InPlaceMod; break; case ExpressionType.MultiplyAssign: pyOperator = PythonOperationKind.InPlaceMultiply; break; case ExpressionType.OrAssign: pyOperator = PythonOperationKind.InPlaceBitwiseOr; break; case ExpressionType.PowerAssign: pyOperator = PythonOperationKind.InPlacePower; break; case ExpressionType.RightShiftAssign: pyOperator = PythonOperationKind.InPlaceRightShift; break; case ExpressionType.LeftShiftAssign: pyOperator = PythonOperationKind.InPlaceLeftShift; break; case ExpressionType.SubtractAssign: pyOperator = PythonOperationKind.InPlaceSubtract; break; case ExpressionType.Equal: pyOperator = PythonOperationKind.Equal; break; case ExpressionType.GreaterThan: pyOperator = PythonOperationKind.GreaterThan; break; case ExpressionType.GreaterThanOrEqual: pyOperator = PythonOperationKind.GreaterThanOrEqual; break; case ExpressionType.LessThan: pyOperator = PythonOperationKind.LessThan; break; case ExpressionType.LessThanOrEqual: pyOperator = PythonOperationKind.LessThanOrEqual; break; case ExpressionType.NotEqual: pyOperator = PythonOperationKind.NotEqual; break; } DynamicMetaObject res = null; if (pyOperator != null) { res = MakeBinaryOperation(operation, args, pyOperator.Value, errorSuggestion); } else { res = operation.FallbackBinaryOperation(target, arg); } return BindingHelpers.AddDynamicTestAndDefer(operation, BindingHelpers.AddPythonBoxing(res), args, valInfo); }
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(binder, "binder"); ComMethodDesc method; if (_self.TryGetGetItem(out method)) { bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args); return BindComInvoke(args, method, binder.CallInfo, isByRef); } return base.BindInvoke(binder, args); }
// Ruby binders: internal CallArguments(RubyContext context, DynamicMetaObject/*!*/ scopeOrContextOrTargetOrArgArray, DynamicMetaObject/*!*/[]/*!*/ args, RubyCallSignature signature) { Assert.NotNull(scopeOrContextOrTargetOrArgArray); Assert.NotNullItems(args); ArgumentArray argArray = scopeOrContextOrTargetOrArgArray.Value as ArgumentArray; if (argArray != null) { Debug.Assert(args.Length == 0 && argArray.Count >= 1); // build meta-objects for arguments wrapped in the array: args = new DynamicMetaObject[argArray.Count - 1]; for (int i = 0; i < args.Length; i++) { args[i] = argArray.GetMetaObject(scopeOrContextOrTargetOrArgArray.Expression, 1 + i); } scopeOrContextOrTargetOrArgArray = argArray.GetMetaObject(scopeOrContextOrTargetOrArgArray.Expression, 0); } Debug.Assert(signature.HasScope == scopeOrContextOrTargetOrArgArray.Value is RubyScope); Debug.Assert((context == null && !signature.HasScope) == scopeOrContextOrTargetOrArgArray.Value is RubyContext); if (context != null) { // bound site: _context = new DynamicMetaObject(AstUtils.Constant(context), BindingRestrictions.Empty, context); if (signature.HasScope) { _scope = scopeOrContextOrTargetOrArgArray; _hasScopeOrContextArg = true; } else { _target = scopeOrContextOrTargetOrArgArray; } } else if (signature.HasScope) { // unbound site with scope: _context = new DynamicMetaObject( Methods.GetContextFromScope.OpCall(scopeOrContextOrTargetOrArgArray.Expression), BindingRestrictions.Empty, ((RubyScope)scopeOrContextOrTargetOrArgArray.Value).RubyContext ); _scope = scopeOrContextOrTargetOrArgArray; _hasScopeOrContextArg = true; _target = null; } else { // unbound site with context: _context = scopeOrContextOrTargetOrArgArray; _hasScopeOrContextArg = true; _target = null; } Debug.Assert(_target != null || args.Length > 0); _args = args; _copyArgsOnWrite = true; _signature = signature; Debug.Assert(!signature.HasSplattedArgument || GetSplattedArgument() != null); }
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject onBindingError) { if (self.NeedsDeferral()) { return Defer(self, value); } #if !SILVERLIGHT DynamicMetaObject com; if (System.Dynamic.ComBinder.TryBindSetMember(this, self, value, out com)) { return com; } #endif return Binder.Binder.SetMember(Name, self, value, Ast.Constant(Binder.Context)); }
public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, DynamicMetaObject/*!*/[]/*!*/ args) { var callArgs = new CallArguments(context, args, Signature); // TODO: COM interop if (IsForeignMetaObject(callArgs.MetaTarget)) { return InteropBind(callArgs); } var metaBuilder = new MetaObjectBuilder(); Build(metaBuilder, callArgs); return metaBuilder.CreateMetaObject(this); }
/// <summary> /// Performs the binding of the dynamic set index operation. /// </summary> /// <param name="target">The target of the dynamic set index operation.</param> /// <param name="args">An array of arguments of the dynamic set index operation.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { ContractUtils.RequiresNotNull(target, "target"); ContractUtils.RequiresNotNull(args, "args"); ContractUtils.Requires(args.Length >= 2, "args"); DynamicMetaObject value = args[args.Length - 1]; DynamicMetaObject[] indexes = args.RemoveLast(); ContractUtils.RequiresNotNull(value, "args"); ContractUtils.RequiresNotNullItems(indexes, "args"); return target.BindSetIndex(this, indexes, value); }
internal override void MakeGetExpression(PythonBinder/*!*/ binder, Expression/*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject/*!*/ owner, ConditionalBuilder/*!*/ builder) { if (instance != null) { builder.FinishCondition( Ast.Call( typeof(PythonOps).GetMethod("MakeBoundBuiltinFunction"), AstUtils.Constant(_template), instance.Expression ) ); } else { builder.FinishCondition(AstUtils.Constant(this)); } }
public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { if (!target.HasValue && !arg.HasValue) return Defer(target, arg); else if (!target.HasValue) return Defer(target); else if (!arg.HasValue) return Defer(arg); if (Operation == ExpressionType.GreaterThan) { return new DynamicMetaObject( AstUtils.LightDynamic( _context.BinaryOperation(ExpressionType.LessThan), arg.Expression, target.Expression ), BindingRestrictions.Empty ); } if (target.Value == null) { var tNull = TotemNull.Get(_context); target = new DynamicMetaObject( Expression.Constant(tNull, typeof(TotemNull)), BindingRestrictions.GetExpressionRestriction( Expression.ReferenceEqual(target.Expression, AstUtils.Constant(null)) ), tNull ); } var targetType = target.LimitType; if (target.GetType() != typeof(TotemType.MetaObject)) { var type = _context.GetTypeHandler(targetType); if (type != null) { return type.GetMetaObject(target.Expression, target.Restrictions, target.Value).BindBinaryOperation(this, arg); } } // we get the error message w/ {0}, {1} so that TypeError formats it correctly return errorSuggestion ?? TotemProtocol.TypeError( this, MakeBinaryOpErrorMessage(Operation, "{0}", "{1}"), target, arg ); }
// this helper prepares arguments for COM binding by transforming ByVal StongBox arguments // into ByRef expressions that represent the argument's Value fields. internal static bool[] ProcessArgumentsForCom(ref DynamicMetaObject[] args) { Debug.Assert(args != null); DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length]; bool[] isByRefArg = new bool[args.Length]; for (int i = 0; i < args.Length; i++) { DynamicMetaObject curArgument = args[i]; // set new arg infos to their original values or set default ones // we will do this fixup early so that we can assume we always have // arginfos in COM binder. if (IsByRef(curArgument)) { newArgs[i] = curArgument; isByRefArg[i] = true; } else { if (IsStrongBoxArg(curArgument)) { var restrictions = curArgument.Restrictions.Merge( GetTypeRestrictionForDynamicMetaObject(curArgument) ); // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast. Expression boxedValueAccessor = Expression.Field( Helpers.Convert( curArgument.Expression, curArgument.LimitType ), curArgument.LimitType.GetField("Value") ); IStrongBox value = curArgument.Value as IStrongBox; object boxedValue = value != null ? value.Value : null; newArgs[i] = new DynamicMetaObject( boxedValueAccessor, restrictions, boxedValue ); isByRefArg[i] = true; } else { newArgs[i] = curArgument; isByRefArg[i] = false; } } } args = newArgs; return isByRefArg; }
public DynamicMetaObject GetMetaObject(Expression parameter, int index) { return(DynamicMetaObject.Create(this.GetArgument(index), Expression.Call(_GetArgMethod, Utils.Convert(parameter, typeof(ArgumentArray)), Utils.Constant(index)))); }
internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder) { builder.FinishCondition(Ast.Constant(this)); }
/// <summary> /// Helper for generating the call to a builtin function. This is used for calls from built-in method /// descriptors and built-in functions w/ and w/o a bound instance. /// /// This provides all sorts of common checks on top of the call while the caller provides a delegate /// to do the actual call. The common checks include: /// check for generic-only methods /// reversed operator support /// transforming arguments so the default binder can understand them (currently user defined mapping types to PythonDictionary) /// returning NotImplemented from binary operators /// Warning when calling certain built-in functions /// /// </summary> /// <param name="call">The call binder we're doing the call for</param> /// <param name="codeContext">An expression which points to the code context</param> /// <param name="function">the meta object for the built in function</param> /// <param name="hasSelf">true if we're calling with an instance</param> /// <param name="args">The arguments being passed to the function</param> /// <param name="functionRestriction">A restriction for the built-in function, method desc, etc...</param> /// <param name="bind">A delegate to perform the actual call to the method.</param> internal DynamicMetaObject /*!*/ MakeBuiltinFunctionCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ function, DynamicMetaObject /*!*/[] args, bool hasSelf, BindingRestrictions /*!*/ functionRestriction, Func <DynamicMetaObject /*!*/[] /*!*/, BindingResult /*!*/> bind) { DynamicMetaObject res = null; // if we have a user defined operator for **args then transform it into a PythonDictionary DynamicMetaObject translated = TranslateArguments(call, codeContext, new DynamicMetaObject(function.Expression, functionRestriction, function.Value), args, hasSelf, Name); if (translated != null) { return(translated); } // swap the arguments if we have a reversed operator if (IsReversedOperator) { ArrayUtils.SwapLastTwo(args); } // do the appropriate calling logic BindingResult result = bind(args); // validate the result BindingTarget target = result.Target; res = result.MetaObject; if (target.Overload != null && target.Overload.IsProtected) { // report an error when calling a protected member res = new DynamicMetaObject( BindingHelpers.TypeErrorForProtectedMember( target.Overload.DeclaringType, target.Overload.Name ), res.Restrictions ); } else if (IsBinaryOperator && args.Length == 2 && IsThrowException(res.Expression)) { // Binary Operators return NotImplemented on failure. res = new DynamicMetaObject( Ast.Property(null, typeof(PythonOps), nameof(PythonOps.NotImplemented)), res.Restrictions ); } else if (target.Overload != null) { // Add profiling information for this builtin function, if applicable if (call is IPythonSite pythonSite) { var pc = pythonSite.Context; if (pc.Options is PythonOptions po && po.EnableProfiler) { Profiler profiler = Profiler.GetProfiler(pc); res = new DynamicMetaObject( profiler.AddProfiling(res.Expression, target.Overload.ReflectionInfo), res.Restrictions ); } } } // add any warnings that are applicable for calling this function WarningInfo info; if (target.Overload != null && BindingWarnings.ShouldWarn(PythonContext.GetPythonContext(call), target.Overload, out info)) { res = info.AddWarning(codeContext, res); } // finally add the restrictions for the built-in function and return the result. res = new DynamicMetaObject( res.Expression, functionRestriction.Merge(res.Restrictions) ); // The function can return something typed to boolean or int. // If that happens, we need to apply Python's boxing rules. if (res.Expression.Type.IsValueType) { res = BindingHelpers.AddPythonBoxing(res); } else if (res.Expression.Type == typeof(void)) { res = new DynamicMetaObject( Expression.Block( res.Expression, Expression.Constant(null) ), res.Restrictions ); } return(res); }
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { Requires.NotNull(binder); return(binder.Defer(WrapSelf(), value)); }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) => null;
public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) { return(IsOverridden("TryBinaryOperation") ? CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e)) : base.BindBinaryOperation(binder, arg)); }
public DynamicMetaObject /*!*/ Invoke(PythonInvokeBinder /*!*/ pythonInvoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args) { return(InvokeWorker(pythonInvoke, args)); }
/// <summary> /// Updates the <see cref="Expression"/> tree for the operands of the specified operation. /// </summary> /// <param name="operation">The operation to evalutes.</param> /// <param name="thisOperand">The first operand.</param> /// <param name="otherOperand">The second operand.</param> /// <param name="thisExpression">The <see cref="Expression"/> for the first operand.</param> /// <param name="otherExpression">The <see cref="Expression"/> for the second operand.</param> private static void GetBinaryOperandExpressions(ExpressionType operation, DynamicMetaObject thisOperand, DynamicMetaObject otherOperand, ref Expression thisExpression, ref Expression otherExpression) { JsonValue thisValue = thisOperand.Value as JsonValue; JsonValue otherValue = otherOperand.Value as JsonValue; Type thisType = thisValue.Read().GetType(); Type otherType = otherValue != null?otherValue.Read().GetType() : otherOperand.Value.GetType(); Type coercedType; if (JsonValueDynamicMetaObject.TryCoerceType(operation, thisType, otherType, out coercedType)) { thisType = otherType = coercedType; } else if (JsonValueDynamicMetaObject.TryCoerceSpecialTypes(thisOperand, otherOperand, out coercedType)) { thisType = otherType = coercedType; } thisExpression = Expression.Convert(thisExpression, thisOperand.LimitType); thisExpression = Expression.Convert(Expression.Call(thisExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(thisType) }), thisType); otherExpression = Expression.Convert(otherExpression, otherOperand.LimitType); if (otherValue != null) { otherExpression = Expression.Convert(Expression.Call(otherExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(otherType) }), otherType); } else if (otherOperand.LimitType != otherType) { otherExpression = Expression.Convert(otherExpression, otherType); } }
private DynamicMetaObject InvokeWorker(DynamicMetaObjectBinder /*!*/ callAction, DynamicMetaObject /*!*/[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Method Invoke " + args.Length); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Method"); CallSignature signature = BindingHelpers.GetCallSignature(callAction); DynamicMetaObject self = Restrict(typeof(Method)); BindingRestrictions restrictions = self.Restrictions; DynamicMetaObject func = GetMetaFunction(self); DynamicMetaObject call; if (Value.im_self == null) { // restrict to null self (Method is immutable so this is an invariant test) restrictions = restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.Equal( GetSelfExpression(self), AstUtils.Constant(null) ) ) ); if (args.Length == 0) { // this is an error, we pass null which will throw the normal error call = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("MethodCheckSelf"), PythonContext.GetCodeContext(callAction), self.Expression, AstUtils.Constant(null) ), restrictions ); } else { // this may or may not be an error call = new DynamicMetaObject( Ast.Block( MakeCheckSelf(callAction, signature, args), DynamicExpression.Dynamic( PythonContext.GetPythonContext(callAction).Invoke( BindingHelpers.GetCallSignature(callAction) ).GetLightExceptionBinder(callAction.SupportsLightThrow()), typeof(object), ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(ArrayUtils.Insert(func, args))) ) ), BindingRestrictions.Empty ); /*call = func.Invoke(callAction, ArrayUtils.Insert(func, args)); * call = new MetaObject( * Ast.Comma( * Ast.Call( * typeof(PythonOps).GetMethod("MethodCheckSelf"), * self.Expression, * args[0].Expression * ), * call.Expression * ), * call.Restrictions * );*/ } } else { // restrict to non-null self (Method is immutable so this is an invariant test) restrictions = restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.NotEqual( GetSelfExpression(self), AstUtils.Constant(null) ) ) ); DynamicMetaObject im_self = GetMetaSelf(self); DynamicMetaObject[] newArgs = ArrayUtils.Insert(func, im_self, args); CallSignature newSig = new CallSignature(ArrayUtils.Insert(new Argument(ArgumentType.Simple), signature.GetArgumentInfos())); call = new DynamicMetaObject( DynamicExpression.Dynamic( PythonContext.GetPythonContext(callAction).Invoke( newSig ).GetLightExceptionBinder(callAction.SupportsLightThrow()), typeof(object), ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(newArgs)) ), BindingRestrictions.Empty ); /* * call = func.Invoke( * new CallBinder( * PythonContext.GetBinderState(callAction), * newSig * ), * newArgs * );*/ } if (call.HasValue) { return(new DynamicMetaObject( call.Expression, restrictions.Merge(call.Restrictions), call.Value )); } else { return(new DynamicMetaObject( call.Expression, restrictions.Merge(call.Restrictions) )); } }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { throw new NotImplementedException(); }
public override DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { throw new NotImplementedException(); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { return(IsOverridden("TrySetIndex") ? CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e)) : base.BindSetIndex(binder, indexes, value)); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { return(_context.Binder.Invoke( Signature, errorSuggestion, new TjsOverloadResolverFactory(_context.Binder), target, args )); }
public DynamicMetaObject /*!*/ Invoke(PythonInvokeBinder /*!*/ pythonInvoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args) { return(MakeCallRule(pythonInvoke, codeContext, args)); }
public override DynamicMetaObject /*!*/ BindSetMember(SetMemberBinder /*!*/ member, DynamicMetaObject /*!*/ value) { return(MakeSetMember(member.Name, value)); }
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { return(PythonProtocol.Index(this, PythonIndexType.SetSlice, ArrayUtils.Insert(target, args))); }
/// <summary> /// Implements getter for dynamic indexer by index (JsonArray). /// </summary> /// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param> /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the set index operation.</param> /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param> /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { if (binder == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder")); } if (indexes == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("indexes")); } if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); } Expression indexExpression; if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression)) { return(new DynamicMetaObject(indexExpression, this.DefaultRestrictions)); } MethodInfo methodInfo = indexExpression.Type == typeof(string) ? SetValueByKeyMethodInfo : SetValueByIndexMethodInfo; Expression[] args = new Expression[] { indexExpression, Expression.Convert(value.Expression, typeof(object)) }; return(this.GetMethodMetaObject(methodInfo, args)); }
/// <summary> /// Performs the binding of the dynamic binary operation. /// </summary> /// <param name="binder">An instance of the <see cref="BinaryOperationBinder"/> that represents the details of the dynamic operation.</param> /// <param name="arg">An instance of the <see cref="DynamicMetaObject"/> representing the right hand side of the binary operation.</param> /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) { if (binder == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder")); } if (arg == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("arg")); } Expression thisExpression = this.Expression; Expression otherExpression = arg.Expression; Expression operExpression = null; JsonValue otherValue = arg.Value as JsonValue; JsonValue thisValue = this.Value as JsonValue; OperationSupport supportValue = JsonValueDynamicMetaObject.GetBinaryOperationSupport(binder.Operation, thisValue, arg.Value); if (supportValue == OperationSupport.Supported) { if (otherValue != null) { if (thisValue is JsonPrimitive && otherValue is JsonPrimitive) { //// operation on primitive types. JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression); } else { //// operation on JsonValue types. thisExpression = Expression.Convert(thisExpression, typeof(JsonValue)); otherExpression = Expression.Convert(otherExpression, typeof(JsonValue)); } } else { if (arg.Value != null) { //// operation on JSON primitive and CLR primitive JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression); } else { //// operation on JsonValue and null. thisExpression = Expression.Convert(thisExpression, typeof(JsonValue)); if (thisValue.JsonType == JsonType.Default) { thisExpression = Expression.Constant(null); } } } operExpression = JsonValueDynamicMetaObject.GetBinaryOperationExpression(binder.Operation, thisExpression, otherExpression); } if (operExpression == null) { operExpression = JsonValueDynamicMetaObject.GetOperationErrorExpression(supportValue, binder.Operation, thisValue, arg.Value); } operExpression = Expression.Convert(operExpression, typeof(object)); return(new DynamicMetaObject(operExpression, this.DefaultRestrictions)); }
public DynamicMetaObject GetMember(PythonGetMemberBinder member, DynamicMetaObject codeContext) { // no codeContext filtering but avoid an extra site by handling this action directly return(MakeGetMember(member, codeContext)); }
internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder) { if (instance != null) { builder.FinishCondition( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeBoundBuiltinFunction)), AstUtils.Constant(_template), instance.Expression ) ); } else { builder.FinishCondition(AstUtils.Constant(this)); } }
private DynamicMetaObject /*!*/ MakeGetMember(DynamicMetaObjectBinder /*!*/ member, DynamicMetaObject codeContext) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass GetMember"); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "OldClass GetMember"); DynamicMetaObject self = Restrict(typeof(OldClass)); Expression target; string memberName = GetGetMemberName(member); switch (memberName) { case "__dict__": target = Ast.Block( Ast.Call( typeof(PythonOps).GetMethod("OldClassDictionaryIsPublic"), self.Expression ), Ast.Call( typeof(PythonOps).GetMethod("OldClassGetDictionary"), self.Expression ) ); break; case "__bases__": target = Ast.Call( typeof(PythonOps).GetMethod("OldClassGetBaseClasses"), self.Expression ); break; case "__name__": target = Ast.Call( typeof(PythonOps).GetMethod("OldClassGetName"), self.Expression ); break; default: ParameterExpression tmp = Ast.Variable(typeof(object), "lookupVal"); return(new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Expression.Not( Expression.TypeIs( Expression.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldClassTryLookupValue"), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(memberName) ) ), typeof(OperationFailed) ) ), tmp, AstUtils.Convert( GetMemberFallback(this, member, codeContext).Expression, typeof(object) ) ) ), self.Restrictions )); } return(new DynamicMetaObject( target, self.Restrictions )); }
///////////////////////////////////////////////////////////////////////////////// private static Type GetTypeForErrorMetaObject(DynamicMetaObjectBinder action, DynamicMetaObject arg0) { // This is similar to ConvertResult but has fewer things to worry about. var invokeConstructor = action as CSharpInvokeConstructorBinder; if (invokeConstructor != null) { if (arg0 == null || !(arg0.Value is Type)) { Debug.Assert(false); return(typeof(object)); } Type result = arg0.Value as Type; return(result); } return(action.ReturnType); }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { Requires.NotNull(binder); return(binder.Defer(WrapSelf(), indexes.AddLast(value))); }
internal static DynamicMetaObject Bind( DynamicMetaObjectBinder action, RuntimeBinder binder, DynamicMetaObject[] args, IEnumerable <CSharpArgumentInfo> arginfos, DynamicMetaObject onBindingError) { Expression[] parameters = new Expression[args.Length]; BindingRestrictions restrictions = BindingRestrictions.Empty; ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder; ParameterExpression tempForIncrement = null; IEnumerator <CSharpArgumentInfo> arginfosEnum = (arginfos ?? Array.Empty <CSharpArgumentInfo>()).GetEnumerator(); for (int index = 0; index < args.Length; ++index) { DynamicMetaObject o = args[index]; // Our contract with the DLR is such that we will not enter a bind unless we have // values for the meta-objects involved. if (!o.HasValue) { Debug.Assert(false, "The runtime binder is being asked to bind a metaobject without a value"); throw Error.InternalCompilerError(); } CSharpArgumentInfo info = arginfosEnum.MoveNext() ? arginfosEnum.Current : null; if (index == 0 && IsIncrementOrDecrementActionOnLocal(action)) { // We have an inc or a dec operation. Insert the temp local instead. // // We need to do this because for value types, the object will come // in boxed, and we'd need to unbox it to get the original type in order // to increment. The only way to do that is to create a new temporary. object value = o.Value; tempForIncrement = Expression.Variable(value != null ? value.GetType() : typeof(object), "t0"); parameters[0] = tempForIncrement; } else { parameters[index] = o.Expression; } BindingRestrictions r = DeduceArgumentRestriction(index, callPayload, o, info); restrictions = restrictions.Merge(r); // Here we check the argument info. If the argument info shows that the current argument // is a literal constant, then we also add an instance restriction on the value of // the constant. if (info != null && info.LiteralConstant) { if (o.Value is double && double.IsNaN((double)o.Value)) { MethodInfo isNaN = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN")); Expression e = Expression.Call(null, isNaN, o.Expression); restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e)); } else if (o.Value is float && float.IsNaN((float)o.Value)) { MethodInfo isNaN = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN")); Expression e = Expression.Call(null, isNaN, o.Expression); restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e)); } else { Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type)); r = BindingRestrictions.GetExpressionRestriction(e); restrictions = restrictions.Merge(r); } } } // Get the bound expression. try { DynamicMetaObject deferredBinding; Expression expression = binder.Bind(action, parameters, args, out deferredBinding); if (deferredBinding != null) { expression = ConvertResult(deferredBinding.Expression, action); restrictions = deferredBinding.Restrictions.Merge(restrictions); return(new DynamicMetaObject(expression, restrictions)); } if (tempForIncrement != null) { // If we have a ++ or -- payload, we need to do some temp rewriting. // We rewrite to the following: // // temp = (type)o; // temp++; // o = temp; // return o; DynamicMetaObject arg0 = args[0]; expression = Expression.Block( new[] { tempForIncrement }, Expression.Assign(tempForIncrement, Expression.Convert(arg0.Expression, arg0.Value.GetType())), expression, Expression.Assign(arg0.Expression, Expression.Convert(tempForIncrement, arg0.Expression.Type))); } expression = ConvertResult(expression, action); return(new DynamicMetaObject(expression, restrictions)); } catch (RuntimeBinderException e) { if (onBindingError != null) { return(onBindingError); } return(new DynamicMetaObject( Expression.Throw( Expression.New( typeof(RuntimeBinderException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(e.Message) ), GetTypeForErrorMetaObject(action, args.Length == 0 ? null : args[0]) ), restrictions )); } }
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 list = args[index]; if (!(list.Value is IList <object>) && list.Value != null) { // The DefaultBinder only handles types that implement IList<object>. Here we have a // arbitrary user-defined sequence type. 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.UserMappingToPythonTuple)), codeContext, args[index].Expression, AstUtils.Constant(name) ), 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(list.Expression, list.GetLimitType())) ) )); } } return(null); }
private static bool IsByRef(DynamicMetaObject mo) { return(mo.Expression is ParameterExpression pe && pe.IsByRef); }
public BindingResult(BindingTarget target, DynamicMetaObject meta) { Target = target; MetaObject = meta; }
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { ComMethodDesc setItem; if (_self.TryGetSetItem(out setItem)) { List <ParameterExpression> temps = new List <ParameterExpression>(); List <Expression> initTemps = new List <Expression>(); bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(setItem, ref indexes, temps, initTemps); isByRef = isByRef.AddLast(false); // Convert the value to the target type DynamicMetaObject updatedValue = new DynamicMetaObject(value.CastOrConvertMethodArgument( value.LimitType, setItem.Name, "SetIndex", temps, initTemps), value.Restrictions); var result = BindComInvoke(indexes.AddLast(updatedValue), setItem, binder.CallInfo, isByRef, temps, initTemps); // Make sure to return the value; some languages need it. return(new DynamicMetaObject( Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))), result.Restrictions )); } return(base.BindSetIndex(binder, indexes, value)); }
private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke) { // // Build a new expression like: // { // object result; // TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult // } // ParameterExpression result = Expression.Parameter(typeof(object), null); IList <Expression> callArgs = new List <Expression>(); callArgs.Add(Expression.Convert(Expression, typeof(T))); callArgs.Add(Constant(binder)); callArgs.AddRange(args); callArgs.Add(result); DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty); // Need to add a conversion if calling TryConvert if (binder.ReturnType != typeof(object)) { UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType); // will always be a cast or unbox resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions); } if (fallbackInvoke != null) { resultMetaObject = fallbackInvoke(resultMetaObject); } DynamicMetaObject callDynamic = new DynamicMetaObject( Expression.Block( new[] { result }, Expression.Condition( Expression.Call( Expression.Constant(_proxy), typeof(DynamicProxy <T>).GetMethod(methodName), callArgs ), resultMetaObject.Expression, fallbackResult.Expression, binder.ReturnType ) ), GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions) ); return(callDynamic); }
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { var result = Context.Binder.SetMember(Name, target, value, errorSuggestion, new TjsOverloadResolverFactory(Context.Binder)); if (result.Expression.Type.IsValueType) { result = new DynamicMetaObject(AstUtils.Convert(result.Expression, typeof(object)), result.Restrictions); } return(result); }