This doesn't cover *all* the variables yet, just the ones that were
previously passed in as arguments. I'll expand this later to separate
the macro parsing from the execution of the functions themselves.
substituteParams has become a thin wrapper around the new evaluateMacros
function, and will become more of a compatibility shim as refactorings
and rewrites are done.