Extensible shape API

Step 1 to full extensibility.

I plan to split the shape definitions out into separate files later, but for now I want the diff to be meaningful.