private static DynamicMetaObject MakeSlotDelete(DeleteBindingInfo/*!*/ info, PythonTypeSlot/*!*/ dts) { // users can subclass PythonProperty so check the type explicitly // and only in-line the ones we fully understand. if (dts.GetType() == typeof(PythonProperty)) { // properties are mutable so we generate code to get the value rather // than burning it into the rule. Expression deleter = Ast.Property( Ast.Convert(AstUtils.WeakConstant(dts), typeof(PythonProperty)), "fdel" ); ParameterExpression tmpDeleter = Ast.Variable(typeof(object), "tmpDel"); info.Body.AddVariable(tmpDeleter); info.Body.FinishCondition( Ast.Block( Ast.Assign(tmpDeleter, deleter), Ast.Condition( Ast.NotEqual( tmpDeleter, Ast.Constant(null) ), Ast.Dynamic( new PythonInvokeBinder( BinderState.GetBinderState(info.Action), new CallSignature(1) ), typeof(void), Ast.Constant(BinderState.GetBinderState(info.Action).Context), tmpDeleter, info.Args[0].Expression ), Ast.Throw(Ast.Call(typeof(PythonOps).GetMethod("UndeletableProperty"))) ) ) ); return info.Body.GetMetaObject(); } info.Body.AddCondition( Ast.Call( typeof(PythonOps).GetMethod("SlotTryDeleteValue"), Ast.Constant(BinderState.GetBinderState(info.Action).Context), AstUtils.Convert(AstUtils.WeakConstant(dts), typeof(PythonTypeSlot)), AstUtils.Convert(info.Args[0].Expression, typeof(object)), Ast.Convert( Ast.Property( Ast.Convert( info.Args[0].Expression, typeof(IPythonObject)), TypeInfo._IPythonObject.PythonType ), typeof(PythonType) ) ), Ast.Constant(null) ); return null; }
private static void MakeSlotAccess(GetBindingInfo/*!*/ info, PythonTypeSlot dts) { ReflectedSlotProperty rsp = dts as ReflectedSlotProperty; if (rsp != null) { // we need to fall back to __getattr__ if the value is not defined, so call it and check the result. info.Body.AddCondition( Ast.NotEqual( Ast.Assign( info.Result, Ast.ArrayAccess( Ast.Call( Ast.Convert(info.Self, typeof(IObjectWithSlots)), typeof(IObjectWithSlots).GetMethod("GetSlots") ), Ast.Constant(rsp.Index) ) ), Ast.Field(null, typeof(Uninitialized).GetField("Instance")) ), info.Result ); return; } PythonTypeUserDescriptorSlot slot = dts as PythonTypeUserDescriptorSlot; if (slot != null && !(slot.Value is PythonTypeSlot)) { PythonType slottype = DynamicHelpers.GetPythonType(slot.Value); if (slottype.IsSystemType) { // this is a user slot that's known not to be a descriptor // so we can just burn the value in. For it to change the // slot will need to be replaced reving the type version. info.Body.FinishCondition( AstUtils.Convert(AstUtils.WeakConstant(slot.Value), typeof(object)) ); return; } } // users can subclass PythonProperty so check the type explicitly // and only in-line the ones we fully understand. if (dts.GetType() == typeof(PythonProperty)) { // properties are mutable so we generate code to get the value rather // than burning it into the rule. Expression getter = Ast.Property( Ast.Convert(AstUtils.WeakConstant(dts), typeof(PythonProperty)), "fget" ); ParameterExpression tmpGetter = Ast.Variable(typeof(object), "tmpGet"); info.Body.AddVariable(tmpGetter); info.Body.FinishCondition( Ast.Block( Ast.Assign(tmpGetter, getter), Ast.Condition( Ast.NotEqual( tmpGetter, Ast.Constant(null) ), Ast.Dynamic( new PythonInvokeBinder( BinderState.GetBinderState(info.Action), new CallSignature(1) ), typeof(object), Ast.Constant(BinderState.GetBinderState(info.Action).Context), tmpGetter, info.Self ), Ast.Throw(Ast.Call(typeof(PythonOps).GetMethod("UnreadableProperty")), typeof(object)) ) ) ); return; } Expression tryGet = Ast.Call( TypeInfo._PythonOps.SlotTryGetBoundValue, Ast.Constant(BinderState.GetBinderState(info.Action).Context), Ast.Convert(AstUtils.WeakConstant(dts), typeof(PythonTypeSlot)), AstUtils.Convert(info.Self, typeof(object)), Ast.Property( Ast.Convert( info.Self, typeof(IPythonObject)), TypeInfo._IPythonObject.PythonType ), info.Result ); if (dts.GetAlwaysSucceeds) { info.Body.FinishCondition( Ast.Block(tryGet, info.Result) ); } else { info.Body.AddCondition( tryGet, info.Result ); } }