sparse: replace 'IntStack' with generic list implementation
Apart from reducing the amount of code to maintain going forwards, this removes
several warts:
1. `IntStack_push` returned a value indicating whether it succeeded or failed.
The caller was ignoring this. We now exit on push failure.
2. `IntStack_pop` used an awkward flag-based protocol to detect an empty
stack. We now use a cleaner “is empty” guard on the pop call.
3. Iterating over all stack elements sometimes used < length and sometimes
≤ last. There were reasons for this (`SIZE_MAX` was used as a sentinel
last value, and length was calculated based on last). But it led to code
that was harder than necessary to understand at the call site.