DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { switch (action.Operation) { case PythonOperationKind.CallSignatures: return(PythonProtocol.MakeCallSignatureOperation(this, Value.Template.Targets)); } return(null); }
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; }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass PythonOperation " + action.Operation); if (action.Operation == PythonOperationKind.IsCallable) { return(MakeIsCallable(action)); } return(null); }
public override bool Equals(object obj) { PythonOperationBinder ob = obj as PythonOperationBinder; if (ob == null) { return(false); } return(ob._context.Binder == _context.Binder && base.Equals(obj)); }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { if (action.Operation == PythonOperationKind.IsCallable) { return(new DynamicMetaObject( AstUtils.Constant(true), Restrictions.Merge(BindingRestrictions.GetTypeRestriction(Expression, typeof(OldClass))) )); } return(null); }
private DynamicMetaObject /*!*/ MakeIsCallable(PythonOperationBinder /*!*/ operation) { DynamicMetaObject self = Restrict(typeof(OldInstance)); return(new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceIsCallable)), AstUtils.Constant(PythonContext.GetPythonContext(operation).SharedContext), self.Expression ), self.Restrictions )); }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { if (action.Operation == PythonOperationKind.IsCallable) { DynamicMetaObject self = Restrict(Value.GetType()); return(new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("UserObjectIsCallable"), AstUtils.Constant(PythonContext.GetPythonContext(action).SharedContext), self.Expression ), self.Restrictions )); } return(null); }
/// <summary> /// Creates a rule for the contains operator. This is exposed via "x in y" in /// IronPython. It is implemented by calling the __contains__ method on x and /// passing in y. /// /// If a type doesn't define __contains__ but does define __getitem__ then __getitem__ is /// called repeatedly in order to see if the object is there. /// /// For normal .NET enumerables we'll walk the iterator and see if it's present. /// </summary> private static DynamicMetaObject/*!*/ MakeContainsOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/[]/*!*/ types) { DynamicMetaObject res; // the paramteres come in backwards from how we look up __contains__, flip them. Debug.Assert(types.Length == 2); ArrayUtils.SwapLastTwo(types); PythonContext state = PythonContext.GetPythonContext(operation); SlotOrFunction sf = SlotOrFunction.GetSlotOrFunction(state, "__contains__", types); if (sf.Success) { // just a call to __contains__ res = sf.Target; } else { RestrictTypes(types); sf = SlotOrFunction.GetSlotOrFunction(state, "__iter__", types[0]); if (sf.Success) { // iterate using __iter__ res = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("ContainsFromEnumerable"), AstUtils.Constant(state.SharedContext), sf.Target.Expression, AstUtils.Convert(types[1].Expression, typeof(object)) ), BindingRestrictions.Combine(types) ); } else { ParameterExpression curIndex = Ast.Variable(typeof(int), "count"); sf = SlotOrFunction.GetSlotOrFunction(state, "__getitem__", types[0], new DynamicMetaObject(curIndex, BindingRestrictions.Empty)); if (sf.Success) { // defines __getitem__, need to loop over the indexes and see if we match ParameterExpression getItemRes = Ast.Variable(sf.ReturnType, "getItemRes"); ParameterExpression containsRes = Ast.Variable(typeof(bool), "containsRes"); LabelTarget target = Ast.Label(); res = new DynamicMetaObject( Ast.Block( new ParameterExpression[] { curIndex, getItemRes, containsRes }, Utils.Loop( null, // test Ast.Assign(curIndex, Ast.Add(curIndex, AstUtils.Constant(1))), // increment Ast.Block( // body // getItemRes = param0.__getitem__(curIndex) Utils.Try( Ast.Block( Ast.Assign( getItemRes, sf.Target.Expression ), Ast.Empty() ) ).Catch( // end of indexes, return false typeof(IndexOutOfRangeException), Ast.Break(target) ), // if(getItemRes == param1) return true Utils.If( DynamicExpression.Dynamic( state.BinaryOperationRetType( state.BinaryOperation(ExpressionType.Equal), state.Convert(typeof(bool), ConversionResultKind.ExplicitCast) ), typeof(bool), types[1].Expression, getItemRes ), Ast.Assign(containsRes, AstUtils.Constant(true)), Ast.Break(target) ), AstUtils.Empty() ), null, // loop else target, // break label target null ), containsRes ), BindingRestrictions.Combine(types) ); } else { // non-iterable object res = new DynamicMetaObject( operation.Throw( Ast.Call( typeof(PythonOps).GetMethod("TypeErrorForNonIterableObject"), AstUtils.Convert( types[1].Expression, typeof(object) ) ), typeof(bool) ), BindingRestrictions.Combine(types) ); } } } if (res.GetLimitType() != typeof(bool) && res.GetLimitType() != typeof(void)) { res = new DynamicMetaObject( DynamicExpression.Dynamic( state.Convert( typeof(bool), ConversionResultKind.ExplicitCast ), typeof(bool), res.Expression ), res.Restrictions ); } return res; }
private static DynamicMetaObject/*!*/ MakeOperationRule(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/[]/*!*/ args) { ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args); DynamicMetaObject res; Type deferType = typeof(object); switch (NormalizeOperator(operation.Operation)) { case PythonOperationKind.Documentation: res = BindingHelpers.AddPythonBoxing(MakeDocumentationOperation(operation, args)); break; case PythonOperationKind.CallSignatures: res = BindingHelpers.AddPythonBoxing(MakeCallSignatureOperation(args[0], CompilerHelpers.GetMethodTargets(args[0].Value))); break; case PythonOperationKind.IsCallable: res = MakeIscallableOperation(operation, args); break; case PythonOperationKind.Hash: res = MakeHashOperation(operation, args[0]); break; case PythonOperationKind.Contains: res = MakeContainsOperation(operation, args); break; case PythonOperationKind.AbsoluteValue: res = BindingHelpers.AddPythonBoxing(MakeUnaryOperation(operation, args[0], "__abs__", null)); break; case PythonOperationKind.Compare: res = MakeSortComparisonRule(args, operation, operation.Operation); Debug.Assert(res.LimitType == typeof(int)); break; case PythonOperationKind.GetEnumeratorForIteration: res = MakeEnumeratorOperation(operation, args[0]); break; default: res = BindingHelpers.AddPythonBoxing(MakeBinaryOperation(operation, args, operation.Operation, null)); break; } return BindingHelpers.AddDynamicTestAndDefer(operation, res, args, valInfo, deferType); }
public static DynamicMetaObject/*!*/ Operation(PythonOperationBinder/*!*/ operation, params DynamicMetaObject/*!*/[]/*!*/ args) { if (args.Length == 1) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback PythonOp " + " " + operation.Operation + " " + args[0].LimitType); } else { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback PythonOp " + " " + operation.Operation + " " + args[0].LimitType + ", " + args[1].LimitType); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString()); if (BindingHelpers.NeedsDeferral(args)) { return operation.Defer(args); } return MakeOperationRule(operation, args); }
private static DynamicMetaObject/*!*/ MakeHashOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/ self) { self = self.Restrict(self.GetLimitType()); BinderState state = BinderState.GetBinderState(operation); SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(state, Symbols.Hash, self); DynamicMetaObject res = func.Target; if (func.ReturnType != typeof(int)) { if (func.ReturnType == typeof(BigInteger)) { // Python 2.5 defines the result of returning a long as hashing the long res = new DynamicMetaObject( HashBigInt(operation, res.Expression), res.Restrictions ); } else if (func.ReturnType == typeof(object)) { // need to get the integer value here... ParameterExpression tempVar = Ast.Parameter(typeof(object), "hashTemp"); res = new DynamicMetaObject( Expression.Block( new [] { tempVar }, Expression.Assign(tempVar, res.Expression), Expression.Condition( Expression.TypeIs(tempVar, typeof(int)), Expression.Convert(tempVar, typeof(int)), Expression.Condition( Expression.TypeIs(tempVar, typeof(BigInteger)), HashBigInt(operation, tempVar), HashConvertToInt(state, tempVar) ) ) ), res.Restrictions ); } else { // need to convert unknown value to object res = new DynamicMetaObject( HashConvertToInt(state, res.Expression), res.Restrictions ); } } return res; }
private DynamicMetaObject/*!*/ MakeIsCallable(PythonOperationBinder/*!*/ operation) { DynamicMetaObject self = Restrict(typeof(OldInstance)); return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("OldInstanceIsCallable"), AstUtils.Constant(PythonContext.GetPythonContext(operation).SharedContext), self.Expression ), self.Restrictions ); }
private static DynamicMetaObject/*!*/ MakeIscallableOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/[]/*!*/ args) { // Certain non-python types (encountered during interop) are callable, but don't have // a __call__ attribute. The default base binder also checks these, but since we're overriding // the base binder, we check them here. DynamicMetaObject self = args[0]; // only applies when called from a Python site if (typeof(Delegate).IsAssignableFrom(self.GetLimitType()) || typeof(MethodGroup).IsAssignableFrom(self.GetLimitType())) { return new DynamicMetaObject( AstUtils.Constant(true), self.Restrict(self.GetLimitType()).Restrictions ); } PythonContext state = PythonContext.GetPythonContext(operation); Expression isCallable = Ast.NotEqual( Binders.TryGet( PythonContext.GetCodeContext(operation), state, typeof(object), "__call__", self.Expression ), AstUtils.Constant(OperationFailed.Value) ); return new DynamicMetaObject( isCallable, self.Restrict(self.GetLimitType()).Restrictions ); }
private static DynamicMetaObject MakeEnumeratorOperation(PythonOperationBinder operation, DynamicMetaObject self) { if (self.GetLimitType() == typeof(string)) { self = self.Restrict(self.GetLimitType()); return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("StringEnumerator"), self.Expression ), self.Restrictions ); } else if (self.GetLimitType() == typeof(Bytes)) { self = self.Restrict(self.GetLimitType()); if (operation.Context.PythonOptions.Python30) { return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("BytesIntEnumerator"), self.Expression ), self.Restrictions ); } else { return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("BytesEnumerator"), self.Expression ), self.Restrictions ); } } else if ((self.Value is IEnumerable || typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) && !(self.Value is PythonGenerator)) { self = self.Restrict(self.GetLimitType()); return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("GetEnumeratorFromEnumerable"), Expression.Convert( self.Expression, typeof(IEnumerable) ) ), self.Restrictions ); } else if (self.Value is IEnumerator || // check for COM object (and fast check when we have values) typeof(IEnumerator).IsAssignableFrom(self.GetLimitType())) { // check if we don't have a value DynamicMetaObject ieres = new DynamicMetaObject( MakeEnumeratorResult( Ast.Convert( self.Expression, typeof(IEnumerator) ) ), self.Restrict(self.GetLimitType()).Restrictions ); #if FEATURE_COM if (Microsoft.Scripting.ComInterop.ComBinder.IsComObject(self.Value)) { ieres = new DynamicMetaObject( MakeEnumeratorResult( Expression.Convert( self.Expression, typeof(IEnumerator) ) ), ieres.Restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.TypeIs(self.Expression, typeof(IEnumerator)) ) ) ); } #endif return ieres; } ParameterExpression tmp = Ast.Parameter(typeof(IEnumerator), "enum"); IPythonConvertible pyConv = self as IPythonConvertible; PythonConversionBinder convBinder = PythonContext.GetPythonContext(operation).Convert(typeof(IEnumerator), ConversionResultKind.ExplicitTry); DynamicMetaObject res; if (pyConv != null) { res = pyConv.BindConvert(convBinder); } else { res = convBinder.Bind(self, new DynamicMetaObject[0]); } return new DynamicMetaObject( Expression.Block( new[] { tmp }, Ast.Condition( Ast.NotEqual( Ast.Assign(tmp, res.Expression), AstUtils.Constant(null) ), MakeEnumeratorResult(tmp), Ast.Call( typeof(PythonOps).GetMethod("ThrowTypeErrorForBadIteration"), PythonContext.GetCodeContext(operation), self.Expression ) ) ), res.Restrictions ); }
public static DynamicMetaObject/*!*/ Operation(PythonOperationBinder/*!*/ operation, params DynamicMetaObject/*!*/[]/*!*/ args) { if (args.Length == 1) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback PythonOp " + " " + operation.Operation + " " + args[0].LimitType); } else { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback PythonOp " + " " + operation.Operation + " " + args[0].LimitType + ", " + args[1].LimitType); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString()); if (BindingHelpers.NeedsDeferral(args)) { return operation.Defer(args); } ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args); DynamicMetaObject res = AddPythonBoxing(MakeOperationRule(operation, args)); return BindingHelpers.AddDynamicTestAndDefer(operation, res, args, valInfo); }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { if (action.Operation == PythonOperationKind.IsCallable) { return new DynamicMetaObject( AstUtils.Constant(true), Restrictions.Merge(BindingRestrictions.GetTypeRestriction(Expression, typeof(OldClass))) ); } return null; }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { if (action.Operation == PythonOperationKind.IsCallable) { DynamicMetaObject self = Restrict(Value.GetType()); return new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("UserObjectIsCallable"), AstUtils.Constant(PythonContext.GetPythonContext(action).SharedContext), self.Expression ), self.Restrictions ); } return null; }
private static DynamicMetaObject/*!*/ MakeMemberNamesOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject[] args) { DynamicMetaObject self = args[0]; CodeContext context; if (args.Length > 1 && args[0].GetLimitType() == typeof(CodeContext)) { self = args[1]; context = (CodeContext)args[0].Value; } else { context = PythonContext.GetPythonContext(operation).SharedContext; } if (typeof(IMembersList).IsAssignableFrom(self.GetLimitType())) { return MakeIMembersListRule(PythonContext.GetCodeContext(operation), self); } PythonType pt = DynamicHelpers.GetPythonType(self.Value); List<string> strNames = GetMemberNames(context, pt, self.Value); if (pt.IsSystemType) { return new DynamicMetaObject( AstUtils.Constant(strNames), BindingRestrictions.GetInstanceRestriction(self.Expression, self.Value).Merge(self.Restrictions) ); } return new DynamicMetaObject( AstUtils.Constant(strNames), BindingRestrictions.GetInstanceRestriction(self.Expression, self.Value).Merge(self.Restrictions) ); }
private static DynamicMetaObject MakeEnumeratorOperation(PythonOperationBinder operation, DynamicMetaObject self) { if (self.GetLimitType() == typeof(string)) { self = self.Restrict(self.GetLimitType()); return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("StringEnumerator"), self.Expression ), self.Restrictions ); } else if (self.GetLimitType() == typeof(PythonDictionary)) { self = self.Restrict(self.GetLimitType()); return new DynamicMetaObject( Expression.Call( typeof(PythonOps).GetMethod("MakeDictionaryKeyEnumerator"), self.Expression ), self.Restrictions ); } else if (self.Value is IEnumerable || typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) { self = self.Restrict(self.GetLimitType()); return new DynamicMetaObject( Expression.Call( Expression.Convert( self.Expression, typeof(IEnumerable) ), typeof(IEnumerable).GetMethod("GetEnumerator") ), self.Restrictions ); } else if (self.Value is IEnumerator || // check for COM object (and fast check when we have values) typeof(IEnumerator).IsAssignableFrom(self.GetLimitType())) { // check if we don't have a value DynamicMetaObject ieres = self.Restrict(self.GetLimitType()); #if !SILVERLIGHT if (ComOps.IsComObject(self.Value)) { ieres = new DynamicMetaObject( self.Expression, ieres.Restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.TypeIs(self.Expression, typeof(IEnumerator)) ) ) ); } #endif return ieres; } ParameterExpression tmp = Ast.Parameter(typeof(IEnumerator), "enum"); DynamicMetaObject res = self.BindConvert(new ConversionBinder(BinderState.GetBinderState(operation), typeof(IEnumerator), ConversionResultKind.ExplicitTry)); return new DynamicMetaObject( Expression.Block( new[] { tmp }, Ast.Condition( Ast.NotEqual( Ast.Assign(tmp, res.Expression), AstUtils.Constant(null) ), tmp, Ast.Call( typeof(PythonOps).GetMethod("ThrowTypeErrorForBadIteration"), BinderState.GetCodeContext(operation), self.Expression ) ) ), res.Restrictions ); }
private static DynamicMetaObject/*!*/ MakeHashOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/ self) { self = self.Restrict(self.GetLimitType()); PythonContext state = PythonContext.GetPythonContext(operation); SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(state, "__hash__", self); DynamicMetaObject res = func.Target; if (func.IsNull) { // Python 2.6 setting __hash__ = None makes the type unhashable res = new DynamicMetaObject( operation.Throw( Expression.Call( typeof(PythonOps).GetMethod("TypeErrorForUnhashableObject"), self.Expression ), typeof(int) ), res.Restrictions ); } else if (func.ReturnType != typeof(int)) { if (func.ReturnType == typeof(BigInteger)) { // Python 2.5 defines the result of returning a long as hashing the long res = new DynamicMetaObject( HashBigInt(operation, res.Expression), res.Restrictions ); } else if (func.ReturnType == typeof(object)) { // need to get the integer value here... ParameterExpression tempVar = Ast.Parameter(typeof(object), "hashTemp"); res = new DynamicMetaObject( Expression.Block( new[] { tempVar }, Expression.Assign(tempVar, res.Expression), Expression.Condition( Expression.TypeIs(tempVar, typeof(int)), Expression.Convert(tempVar, typeof(int)), Expression.Condition( Expression.TypeIs(tempVar, typeof(BigInteger)), HashBigInt(operation, tempVar), HashConvertToInt(state, tempVar) ) ) ), res.Restrictions ); } else { // need to convert unknown value to object res = new DynamicMetaObject( HashConvertToInt(state, res.Expression), res.Restrictions ); } } return res; }
private static DynamicExpression/*!*/ HashBigInt(PythonOperationBinder/*!*/ operation, Expression/*!*/ expression) { return DynamicExpression.Dynamic( operation, typeof(int), expression ); }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { switch (action.Operation) { case PythonOperationKind.CallSignatures: return PythonProtocol.MakeCallSignatureOperation(this, Value.Template.Targets); } return null; }
private static DynamicMetaObject/*!*/ MakeDocumentationOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/[]/*!*/ args) { PythonContext state = PythonContext.GetPythonContext(operation); return new DynamicMetaObject( Binders.Convert( PythonContext.GetCodeContext(operation), state, typeof(string), ConversionResultKind.ExplicitCast, Binders.Get( PythonContext.GetCodeContext(operation), state, typeof(object), "__doc__", args[0].Expression ) ), args[0].Restrictions ); }
internal SetIndexAdapter(PythonOperationBinder opBinder) { _opBinder = opBinder; }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass PythonOperation " + action.Operation); if (action.Operation == PythonOperationKind.IsCallable) { return MakeIsCallable(action); } return null; }
DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) { switch (action.Operation) { case PythonOperationKind.CallSignatures: return MakeCallSignatureRule(this); case PythonOperationKind.IsCallable: return MakeIsCallableRule(this); } return null; }
internal PythonOperationBinder/*!*/ Operation(PythonOperationKind operation) { if (_operationBinders == null) { Interlocked.CompareExchange( ref _operationBinders, new Dictionary<PythonOperationKind, PythonOperationBinder>(), null ); } lock (_operationBinders) { PythonOperationBinder res; if (!_operationBinders.TryGetValue(operation, out res)) { _operationBinders[operation] = res = new PythonOperationBinder(this, operation); } return res; } }
private static DynamicMetaObject/*!*/ MakeOperationRule(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/[]/*!*/ args) { switch (NormalizeOperator(operation.Operation)) { case PythonOperationKind.Documentation: return MakeDocumentationOperation(operation, args); case PythonOperationKind.MemberNames: return MakeMemberNamesOperation(operation, args); case PythonOperationKind.CallSignatures: return MakeCallSignatureOperation(args[0], CompilerHelpers.GetMethodTargets(args[0].Value)); case PythonOperationKind.IsCallable: return MakeIscallableOperation(operation, args); case PythonOperationKind.Hash: return MakeHashOperation(operation, args[0]); case PythonOperationKind.Not: return MakeUnaryNotOperation(operation, args[0]); case PythonOperationKind.Contains: return MakeContainsOperation(operation, args); case PythonOperationKind.AbsoluteValue: return MakeUnaryOperation(operation, args[0], Symbols.AbsoluteValue); case PythonOperationKind.Compare: return MakeSortComparisonRule(args, operation, operation.Operation); case PythonOperationKind.GetEnumeratorForIteration: return MakeEnumeratorOperation(operation, args[0]); default: return MakeBinaryOperation(operation, args, operation.Operation, null); } }