public EObject update_counter(final EObject key, final EObject upd) {
return in_tx(new WithMap<EObject>() {
@Override
protected EObject run(IPersistentMap map) {
ETuple rec = (ETuple) map.valAt(key);
if (rec == null)
return null; // fail with badarg
// TODO: figure out match/equals semantics
if (type == Native.am_set) {
if (!key.equalsExactly( get_key(rec) )) {
return null;
}
}
EInteger incr;
ETuple one;
if ((incr=upd.testInteger()) != null) {
int idx = keypos1+1;
rec = update(rec, idx, incr);
if (rec == null) return null;
map = map.assoc(get_key(rec), rec);
set(map);
return rec.elm(idx);
} else if ((one=upd.testTuple()) != null) {
if (one.arity() == 2) {
ESmall eidx = one.elm(1).testSmall();
incr = one.elm(2).testInteger();
if (eidx == null || eidx.value > rec.arity() || incr == null) return null;
int idx = eidx.value;
rec = update(rec, idx, incr);
if (rec == null) return null;
map = map.assoc(get_key(rec), rec);
set(map);
return rec.elm(idx);
} else if (one.arity() == 4){
ESmall eidx = one.elm(1).testSmall();
incr = one.elm(2).testInteger();
EInteger threshold = one.elm(3).testInteger();
EInteger setvalue = one.elm(4).testInteger();
if (eidx == null || eidx.value > rec.arity() || incr == null
|| threshold == null || setvalue == null) return null;
int idx = eidx.value;
rec = update(rec, idx, incr, threshold, setvalue);