Only fetch production values on an as-needed basis

Previously the code would call the reader for every production attribute of a
step after the step was created. Now we track all the steps we've created and
look for the productions we need for a new step.

This can avoid extra work in the case where a step may have many productions
only some of which are needed for a given run.