Refactor the ndarray adaptor and expose the array flags

This uses a cleaner pattern in the C implementation, instead of computing all pointers by hand.
The main reason is we advertise `(data, shape, strides)` as "llarray", a minimal low-level array representation.  It is sort of a ABI at this point.  I can "fix this" by removing `parent` and improving callwrapper.py.