It basically makes a special-case out of a specific template. This is like saying "if you see a program that does X, instead of executing it, execute something else instead".
True! But this is a valid way to get backwards compatibility when extending a syntax. For example, C preprocessor directives like "#ifdef" are actually comments, but when a compliant preprocessor is present, they are executed before the actual code is compiled. Now, Alan Snyder, when he pushed for the addition of the preprocessor could have instead opted to add "eval" to C or he could have added special operators or keywords. But arguably, using a preprocessor with a backwards compatible syntax for this situation was a better choice.
I don't follow the argument that it's somehow best to solve the issue of moving the script from scriptPubKey to scriptSig on the scripting language level.
The reason we get these awkward domain-specific proposals (OP_DOSOMETHINGVERYSPECIFIC) or ultra-powerful proposals (OP_EVAL) is precisely because
it's not generally the job of a programming language to move its own code from one place to another.
For example, to implement OP_CODEHASHCHECK we would need to change EvalScript to know about where scriptSig ends and scriptPubKey begins. The scripting language is not meant to be aware of the block chain, it is meant to be a simple, stack-based language.
P2SH does not require any change to EvalScript. That's because P2SH is not a change to the scripting language at all. It is a backwards compatible change to the block chain, allowing for a hash to reside in the transaction output and for the script to be executed to reside in the corresponding input. That strikes me as much
cleaner than meta-opcodes which hack into the interpreter to move code around.
To clarify: I'm not arguing that implementation concerns should guide our protocol-level decisions, but what I am saying is that in this case the implementation hacks hint at a design-level problem. Namely that we are trying to make a scripting language do a preprocessor's job.
Finally, this provides a very pragmatic reason for P2SH. Because it doesn't change EvalScript, it doesn't require nearly as much testing as the other proposals. I'm ok with Luke's idea (in fact I suggested to roconnor that he drop backward compatibility from his OP_CODEHASH proposal and that would have been CHC/CHV), but I prefer P2SH and I would request a much longer testing period if CHC/CHV was accepted.