@record Trapman { look, lookuid, add, clr, reset, list, copy }; rdsetfmt(@record Trap { uid, mid, fn, desc, clr }, @lambda(t) { sprintfa("[ %u %u %a %a ]", t.uid, t.mid, t.fn, t.desc);}); @define _mktrapman(uidmap, midmap, nextid) { @local look, lookuid, add, clr, list, reset, _copy; @define look(mid) { return midmap[mid]; } @define lookuid(uid) { return uidmap[uid]; } @define add(mid, fn, desc, clr) { @local t, uid; uid = nextid++; t = Trap(uid, mid, fn, desc, clr); uidmap[uid] = t; midmap[mid] = t; return uid; } @define clr(uid) { @local t; t = uidmap[uid]; if(t == nil) error("no such trap: %a", uid); tabdelete(uidmap, t.uid); tabdelete(midmap, t.mid); if(t.clr != nil) t.clr(); } @define list() { @local k; k = tabkeys(uidmap); sort(k, @lambda(a,b){ return a-b; }); return map(@lambda(uid){ uidmap[uid]; }, k); } @define reset() { @local k; k = tabkeys(uidmap); sort(k, @lambda(a,b){ return a-b; }); foreach(clr, k); nextid = 0; } @define _copy() { return _mktrapman(copy(uidmap), copy(midmap), nextid); } return Trapman(look, lookuid, add, clr, reset, list, _copy); } @define mktrapman() { @local nextid, uidmap, midmap; nextid = 0; uidmap = [:]; midmap = [:]; return _mktrapman(uidmap, midmap, nextid); }