static PropertyDescriptor[] GetPropertiesImpl(object self, Attribute[] attributes) { IList <object> attrNames = PythonOps.GetAttrNames(DefaultContext.DefaultCLS, self); List <PropertyDescriptor> descrs = new List <PropertyDescriptor>(); if (attrNames != null) { foreach (object o in attrNames) { string s = o as string; if (s == null) { continue; } PythonTypeSlot attrSlot; PythonType dt = DynamicHelpers.GetPythonType(self); dt.TryResolveSlot(DefaultContext.DefaultCLS, s, out attrSlot); object attrVal = ObjectOps.__getattribute__(DefaultContext.DefaultCLS, self, s); Type attrType = (attrVal == null) ? typeof(NoneTypeOps) : attrVal.GetType(); if ((attrSlot != null && ShouldIncludeProperty(attrSlot, attributes)) || (attrSlot == null && ShouldIncludeInstanceMember(s, attributes))) { descrs.Add(new SuperDynamicObjectPropertyDescriptor(s, attrType, self.GetType())); } } } return(descrs.ToArray()); }
private static bool IsBuiltinConversion(CodeContext /*!*/ context, PythonTypeSlot /*!*/ pts, string name, PythonType /*!*/ selfType) { Type baseType = selfType.UnderlyingSystemType.BaseType; Type tmpType = baseType; do { if (tmpType.IsGenericType && tmpType.GetGenericTypeDefinition() == typeof(Extensible <>)) { baseType = tmpType.GetGenericArguments()[0]; break; } tmpType = tmpType.BaseType; } while (tmpType != null); PythonType ptBase = DynamicHelpers.GetPythonTypeFromType(baseType); PythonTypeSlot baseSlot; if (ptBase.TryResolveSlot(context, name, out baseSlot) && pts == baseSlot) { return(true); } return(false); }
internal static DynamicMetaObject ConvertToIEnumerator(DynamicMetaObjectBinder /*!*/ conversion, DynamicMetaObject /*!*/ metaUserObject) { PythonType pt = MetaPythonObject.GetPythonType(metaUserObject); PythonContext state = PythonContext.GetPythonContext(conversion); CodeContext context = state.SharedContext; PythonTypeSlot pts; if (pt.TryResolveSlot(context, "__iter__", out pts)) { ParameterExpression tmp = Ast.Parameter(typeof(object), "iterVal"); return(new DynamicMetaObject( Expression.Block( new[] { tmp }, Expression.Call( typeof(PythonOps).GetMethod("CreatePythonEnumerator"), Ast.Block( MetaPythonObject.MakeTryGetTypeMember( state, pts, metaUserObject.Expression, tmp ), Ast.Dynamic( new PythonInvokeBinder( state, new CallSignature(0) ), typeof(object), AstUtils.Constant(context), tmp ) ) ) ), metaUserObject.Restrictions )); } else if (pt.TryResolveSlot(context, "__getitem__", out pts)) { return(MakeGetItemIterable(metaUserObject, state, pts, "CreateItemEnumerator")); } return(null); }
internal static DynamicMetaObject ConvertToIEnumerable(DynamicMetaObjectBinder /*!*/ conversion, DynamicMetaObject /*!*/ metaUserObject) { PythonType pt = MetaPythonObject.GetPythonType(metaUserObject); PythonContext pyContext = PythonContext.GetPythonContext(conversion); CodeContext context = pyContext.SharedContext; PythonTypeSlot pts; if (pt.TryResolveSlot(context, "__iter__", out pts)) { return(MakeIterRule(metaUserObject, "CreatePythonEnumerable")); } else if (pt.TryResolveSlot(context, "__getitem__", out pts)) { return(MakeGetItemIterable(metaUserObject, pyContext, pts, "CreateItemEnumerable")); } return(null); }
private static void AddFinalizer(CodeContext /*!*/ context, PythonType dt, object newObject) { // check if object has finalizer... if (dt.TryResolveSlot(context, "__del__", out _)) { IWeakReferenceable iwr = context.LanguageContext.ConvertToWeakReferenceable(newObject); Debug.Assert(iwr != null); InstanceFinalizer nif = new InstanceFinalizer(context, newObject); iwr.SetFinalizer(new WeakRefTracker(iwr, nif, nif)); } }
internal static bool TryGetOperator(CodeContext context, object o, string name, out object callable) { PythonType pt = DynamicHelpers.GetPythonType(o); if (pt.TryResolveSlot(context, name, out PythonTypeSlot pts) && pts.TryGetValue(context, o, pt, out callable)) { return(true); } callable = default; return(false); }
/// <summary> /// Determines if a type member can be imported. This is used to treat static types like modules. /// </summary> private static bool IsStaticTypeMemberInAll(CodeContext /*!*/ context, PythonType /*!*/ pt, string name, out object res) { PythonTypeSlot pts; res = null; if (pt.TryResolveSlot(context, name, out pts)) { if (name == "__doc__" || name == "__class__") { // these exist but we don't want to clobber __doc__ on import * or bring in __class__ return(false); } else if (pts is ReflectedGetterSetter) { // property or indexer, these fetch the value at runtime, the user needs to explicitly // import them using from type import property return(false); } ReflectedField rf = pts as ReflectedField; if (rf != null && !rf._info.IsInitOnly && !rf._info.IsLiteral) { // only bring in read-only fields, if the value can change the user needs to explicitly // import by name return(false); } BuiltinMethodDescriptor method = pts as BuiltinMethodDescriptor; if (method != null && (!method.DeclaringType.IsSealed() || !method.DeclaringType.IsAbstract())) { // inherited object member on a static class (GetHashCode, Equals, etc...) return(false); } BuiltinFunction bf = pts as BuiltinFunction; if (bf != null && (!bf.DeclaringType.IsSealed() || !bf.DeclaringType.IsAbstract())) { // __new__/ReferenceEquals inherited from object return(false); } if (pts.TryGetValue(context, null, pt, out res)) { return(true); } } res = null; return(false); }
private static object GetTypeNew(CodeContext /*!*/ context, PythonType dt) { PythonTypeSlot dts; if (!dt.TryResolveSlot(context, "__new__", out dts)) { throw PythonOps.TypeError("cannot create instances of {0}", dt.Name); } object newInst; bool res = dts.TryGetValue(context, dt, dt, out newInst); Debug.Assert(res); return(newInst); }
static PropertyDescriptor[] GetPropertiesImpl(object self, Attribute[] attributes) { IList <object> attrNames = PythonOps.GetAttrNames(DefaultContext.DefaultCLS, self); List <PropertyDescriptor> descrs = new List <PropertyDescriptor>(); if (attrNames != null) { foreach (object o in attrNames) { if (!(o is string s)) { continue; } PythonTypeSlot attrSlot = null; object attrVal; if (self is OldInstance) { if (((OldInstance)self)._class.TryLookupSlot(s, out attrVal)) { attrSlot = attrVal as PythonTypeSlot; } else if (!((OldInstance)self).Dictionary.TryGetValue(s, out attrVal)) { attrVal = ObjectOps.__getattribute__(DefaultContext.DefaultCLS, self, s); } } else { PythonType dt = DynamicHelpers.GetPythonType(self); dt.TryResolveSlot(DefaultContext.DefaultCLS, s, out attrSlot); attrVal = ObjectOps.__getattribute__(DefaultContext.DefaultCLS, self, s); } Type attrType = (attrVal == null) ? typeof(NoneTypeOps) : attrVal.GetType(); if ((attrSlot != null && ShouldIncludeProperty(attrSlot, attributes)) || (attrSlot == null && ShouldIncludeInstanceMember(s, attributes))) { descrs.Add(new SuperDynamicObjectPropertyDescriptor(s, attrType, self.GetType())); } } } return(descrs.ToArray()); }
internal static bool TryInvokeTernaryOperator(CodeContext context, object o, object arg1, object arg2, string name, out object value) { PerfTrack.NoteEvent(PerfTrack.Categories.Temporary, "TernaryOp " + CompilerHelpers.GetType(o).Name + " " + name); PythonTypeSlot pts; PythonType pt = DynamicHelpers.GetPythonType(o); object callable; if (pt.TryResolveSlot(context, name, out pts) && pts.TryGetValue(context, o, pt, out callable)) { value = PythonCalls.Call(context, callable, arg1, arg2); return(true); } value = null; return(false); }
/// <summary> /// Tries to get the BuiltinFunction for the given name on the type of the provided MetaObject. /// /// Succeeds if the MetaObject is a BuiltinFunction or BuiltinMethodDescriptor. /// </summary> internal static bool TryGetStaticFunction(PythonContext /*!*/ state, string op, DynamicMetaObject /*!*/ mo, out BuiltinFunction function) { PythonType type = MetaPythonObject.GetPythonType(mo); function = null; if (!String.IsNullOrEmpty(op)) { PythonTypeSlot xSlot; object val; if (type.TryResolveSlot(state.SharedContext, op, out xSlot) && xSlot.TryGetValue(state.SharedContext, null, type, out val)) { function = TryConvertToBuiltinFunction(val); if (function == null) { return(false); } } } return(true); }
private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner, Func <DynamicMetaObject> fallback, Func <Expression, Expression> resultConverter) { PythonType pt = ((IPythonObject)self.Value).PythonType; PythonTypeSlot pts; CodeContext context = PythonContext.GetPythonContext(convertToAction).SharedContext; ValidationInfo valInfo = BindingHelpers.GetValidationInfo(this, pt); if (pt.TryResolveSlot(context, name, out pts) && !IsBuiltinConversion(context, pts, name, pt)) { ParameterExpression tmp = Ast.Variable(typeof(object), "func"); Expression callExpr = resultConverter( Ast.Call( PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)), Ast.Dynamic( PythonContext.GetPythonContext(convertToAction).InvokeNone, typeof(object), PythonContext.GetCodeContext(convertToAction), tmp ) ) ); if (typeof(Extensible <>).MakeGenericType(toType).IsAssignableFrom(self.GetLimitType())) { // if we're doing a conversion to the underlying type and we're an // Extensible<T> of that type: // if an extensible type returns it's self in a conversion, then we need // to actually return the underlying value. If an extensible just keeps // returning more instances of it's self a stack overflow occurs - both // behaviors match CPython. callExpr = AstUtils.Convert(AddExtensibleSelfCheck(convertToAction, toType, self, callExpr), typeof(object)); } return(BindingHelpers.AddDynamicTestAndDefer( convertToAction, new DynamicMetaObject( Ast.Condition( MakeTryGetTypeMember( PythonContext.GetPythonContext(convertToAction), pts, self.Expression, tmp ), callExpr, AstUtils.Convert( ConversionFallback(convertToAction), typeof(object) ) ), self.Restrict(self.GetRuntimeType()).Restrictions ), new DynamicMetaObject[] { this }, valInfo, tmp )); } return(fallback()); }
public TResult MakeTypeGetMember() { PythonTypeSlot pts; bool isFinal = false, metaOnly = false; CodeContext lookupContext = _context.LanguageContext.SharedClsContext; // first look in the meta-class to see if we have a get/set descriptor PythonType metaType = DynamicHelpers.GetPythonType(Value); foreach (PythonType pt in metaType.ResolutionOrder) { if (pt.TryLookupSlot(lookupContext, _name, out pts) && pts.IsSetDescriptor(lookupContext, metaType)) { if (AddMetaSlotAccess(metaType, pts)) { metaOnly = isFinal = true; break; } } } if (!isFinal) { // then search the MRO to see if we have the value foreach (PythonType pt in Value.ResolutionOrder) { if (pt.IsOldClass) { // mixed new-style/old-style class, search the one slot in it's MRO for the member AddOldClassAccess(pt); } else if (pt.TryLookupSlot(lookupContext, _name, out pts)) { if (AddSlotAccess(pt, pts)) { isFinal = true; break; } } } } if (!isFinal) { // then go back to the meta class to see if we have a normal attribute foreach (PythonType pt in metaType.ResolutionOrder) { if (pt.OldClass != null) { // mixed new-style/old-style class, just call our version of __getattribute__ // and let it sort it out at runtime. AddMetaOldClassAccess(); isFinal = true; break; } else if (pt.TryLookupSlot(lookupContext, _name, out pts)) { if (AddMetaSlotAccess(metaType, pts)) { isFinal = true; break; } } } } if (!isFinal) { // the member doesn't exist anywhere in the type hierarchy, see if // we define __getattr__ on our meta type. if (metaType.TryResolveSlot(_context, "__getattr__", out pts) && !pts.IsSetDescriptor(lookupContext, metaType)) // we tried get/set descriptors initially { AddMetaGetAttribute(metaType, pts); isFinal = pts.GetAlwaysSucceeds; } } if (!isFinal) { AddError(); } return(Finish(metaOnly)); }
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 TResult MakeTypeGetMember() { PythonTypeSlot pts; bool isFinal = false, metaOnly = false; CodeContext lookupContext = PythonContext.GetContext(_context).SharedClsContext; // first look in the meta-class to see if we have a get/set descriptor PythonType metaType = DynamicHelpers.GetPythonType(Value); foreach (PythonType pt in metaType.ResolutionOrder) { if (pt.TryLookupSlot(lookupContext, _name, out pts) && pts.IsSetDescriptor(lookupContext, metaType)) { if (AddMetaSlotAccess(metaType, pts)) { metaOnly = isFinal = true; break; } } } if (!isFinal) { // then search the MRO to see if we have the value foreach (PythonType pt in Value.ResolutionOrder) { if (pt.TryLookupSlot(lookupContext, _name, out pts)) { if (AddSlotAccess(pt, pts)) { isFinal = true; break; } } } } if (!isFinal) { // then go back to the meta class to see if we have a normal attribute foreach (PythonType pt in metaType.ResolutionOrder) { if (pt.TryLookupSlot(lookupContext, _name, out pts)) { if (AddMetaSlotAccess(metaType, pts)) { isFinal = true; break; } } } } if (!isFinal) { // the member doesn't exist anywhere in the type hierarchy, see if // we define __getattr__ on our meta type. if (metaType.TryResolveSlot(_context, "__getattr__", out pts) && !pts.IsSetDescriptor(lookupContext, metaType)) // we tried get/set descriptors initially { AddMetaGetAttribute(metaType, pts); isFinal = pts.GetAlwaysSucceeds; } } if (!isFinal) { AddError(); } return(Finish(metaOnly)); }