A type-theoretic foundation for programming with higher-order abstract syntax and first-class substitutions