private static void MakeDictionaryDeleteTarget(DeleteBindingInfo/*!*/ info) { info.Body.FinishCondition( Ast.Call( typeof(UserTypeOps).GetMethod("RemoveDictionaryValue"), Ast.Convert(info.Args[0].Expression, typeof(IPythonObject)), AstUtils.Constant(SymbolTable.StringToId(info.Action.Name)) ) ); }
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 MakeDeleteAttrTarget(DeleteBindingInfo/*!*/ info, IPythonObject self, PythonTypeSlot dts) { ParameterExpression tmp = Ast.Variable(typeof(object), "boundVal"); info.Body.AddVariable(tmp); // call __delattr__ info.Body.AddCondition( Ast.Call( TypeInfo._PythonOps.SlotTryGetBoundValue, Ast.Constant(BinderState.GetBinderState(info.Action).Context), AstUtils.Convert(AstUtils.WeakConstant(dts), typeof(PythonTypeSlot)), AstUtils.Convert(info.Args[0].Expression, typeof(object)), AstUtils.Convert(AstUtils.WeakConstant(self.PythonType), typeof(PythonType)), tmp ), Ast.Dynamic( new PythonInvokeBinder( BinderState.GetBinderState(info.Action), new CallSignature(1) ), typeof(object), BinderState.GetCodeContext(info.Action), tmp, Ast.Constant(info.Action.Name) ) ); }
private DynamicMetaObject/*!*/ MakeDeleteMemberRule(DeleteBindingInfo/*!*/ info) { CodeContext context = BinderState.GetBinderState(info.Action).Context; DynamicMetaObject self = info.Args[0].Restrict(info.Args[0].GetRuntimeType()); IPythonObject sdo = info.Args[0].Value as IPythonObject; if (info.Action.Name == "__class__") { return new DynamicMetaObject( Ast.Throw( Ast.New( typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }), Ast.Constant("can't delete __class__ attribute") ) ), self.Restrictions ); } // call __delattr__ if it exists PythonTypeSlot dts; if (sdo.PythonType.TryResolveSlot(context, Symbols.DelAttr, out dts) && !IsStandardObjectMethod(dts)) { MakeDeleteAttrTarget(info, sdo, dts); } // then see if we have a delete descriptor sdo.PythonType.TryResolveSlot(context, SymbolTable.StringToId(info.Action.Name), out dts); ReflectedSlotProperty rsp = dts as ReflectedSlotProperty; if (rsp != null) { MakeSlotsDeleteTarget(info, rsp); } if (!info.Body.IsFinal && dts != null) { MakeSlotDelete(info, dts); } if (!info.Body.IsFinal && sdo.HasDictionary) { // finally if we have a dictionary set the value there. MakeDictionaryDeleteTarget(info); } if (!info.Body.IsFinal) { // otherwise fallback info.Body.FinishCondition( FallbackDeleteError(info.Action, info.Args).Expression ); } DynamicMetaObject res = info.Body.GetMetaObject(info.Args); res = new DynamicMetaObject( res.Expression, self.Restrictions.Merge(res.Restrictions) ); return BindingHelpers.AddDynamicTestAndDefer( info.Action, res, info.Args, info.Validation ); }