`nullOr`'s merge function requires definitions to all be null or all be
non-null. It was being used where the intent was that null be used as a
value representing unset, and as such the merge should return null if
all definitions are null and ignore nulls otherwise. This adds a type
with that merge semantics.
Using `perSystem` to implement per-system attributes ties all the
per-system attributes together; all the `perSystem` functions must run
to determine output attrs. By generating them separately, the generation
can be done lazily.