/* Function: tp_iget * Failsafe attribute lookup. * * This is like <tp_get>, except it will return false if the attribute lookup * failed. Otherwise, it will return true, and the object will be returned * over the reference parameter r. */ int tp_iget(TP,tp_obj *r, tp_obj self, tp_obj k) { if (self.type == TP_DICT) { int n = _tp_dict_find(tp,self.dict.val,k); if (n == -1) { return 0; } *r = self.dict.val->items[n].val; tp_grey(tp,*r); return 1; } if (self.type == TP_LIST && !self.list.val->len) { return 0; } *r = tp_get(tp,self,k); tp_grey(tp,*r); return 1; }
int tp_iget(TP,tp_obj *r, tp_obj self, tp_obj k) { if (obj_type(self) == TP_DICT) { int n = _tp_dict_find(tp, tp_dict_val(self),k); if (n == -1) { return 0; } *r = tp_dict_val(self)->items[n].val; tp_grey(tp,*r); return 1; } if (obj_type(self) == TP_LIST && !tp_list_val(self)->len) { return 0; } *r = tp_get(tp,self,k); tp_grey(tp,*r); return 1; }
tp_obj tp_track(TP,tp_obj v) { if (v.type == TP_STRING) { int i = _tp_dict_find(tp,tp->strings,v); if (i != -1) { tp_delete(tp,v); v = tp->strings->items[i].key; tp_grey(tp,v); return v; } _tp_dict_setx(tp,tp->strings,v,tp_True); } tp_gcinc(tp); tp_grey(tp,v); return v; }
void tp_follow(TP,tp_obj v) { int type = v.type; if (type == TP_LIST) { int n; for (n=0; n<v.list.val->len; n++) { tp_grey(tp,v.list.val->items[n]); } } if (type == TP_DICT) { int i; for (i=0; i<v.dict.val->len; i++) { int n = _tp_dict_next(tp,v.dict.val); tp_grey(tp,v.dict.val->items[n].key); tp_grey(tp,v.dict.val->items[n].val); } } if (type == TP_FNC) { tp_grey(tp,v.fnc.info->self); tp_grey(tp,v.fnc.info->globals); } }
tp_obj tp_track(TP,tp_obj v) { tp_gcinc(tp); tp_grey(tp,v); return v; }