The fact that C can be relatively easily and predictably converted into reasonably efficient assembly doesn't make it an assembler.
All compiled languages are "restricted on the basis of being functionally equivalent to the input code", unless you meant something by that statement that I don't understand. The reason I'm uncertain is because I wouldn't presume that you are asserting that all deterministically compiled, correct compilers are high-level assembly languages.
I would add to what he writes in the article, however (and I did in a comment there): C doesn't model the von Neumann architecture very well. It lets you create data structures just fine, but the capability to create code, dynamically, at runtime, surely the defining characteristic of a shared instruction-data architecture, is all but completely absent.
Perhaps I've been unclear. C has characteristics of high-level assembly language because it allows you to directly integrate direct machine opcodes transformations directly into the syntax of the language itself instead of into the compiler/interpreter. In other words, C has an element of predictability in the opcodes it will generate for a given architecture. The exact opcodes it generates (SIMD, etc) aren't extremely important as long as this capability is preserved.
The fact that C can be relatively easily and predictably converted into reasonably efficient assembly doesn't make it an assembler.
You make some good points and there is one which I thought about but didn't touch on because I didn't think it was important.
Consider: most systems and kernel developers do not write C. That is, they do not simply target "the C programming language." Instead, they often target GCC or the Intel C compiler. Even more, they usually target an architecture. In theory one may have to deal with many of the complexities of different implementations, but in practice development is usually restricted (or sometimes duplicated). I think that you may be taking my position a bit too concretely: I don't support the statement that all opcode output is predictable, nor do I support the statement that no other language has elements of the same techniques which make C so useful for systems development.
Simply, view my post as a (possibly slightly exaggerated) relation of the systems C development process from one low-level kernel developer to another. From the birds' eye view (which is the feeling I get from the original post) C may look abstracted and neat, but my experience says that the opposite is in fact true and that things tend to get a lot more dirty in the details.
I don't think C is necessarily predictable in the opcodes it will produce for any given architecture. The code produced for a big switch statement will differ hugely between compilers for the same architecture; some use binary searches, some use hash tables, some use multiple indirect jumps, etc.
And conversely, there are many other languages that have a similar degree of predictability in the code they produce for a given architecture; Pascal, for one, which is almost isomorphic with C in most practical implementations.
All compiled languages are "restricted on the basis of being functionally equivalent to the input code", unless you meant something by that statement that I don't understand. The reason I'm uncertain is because I wouldn't presume that you are asserting that all deterministically compiled, correct compilers are high-level assembly languages.
I would add to what he writes in the article, however (and I did in a comment there): C doesn't model the von Neumann architecture very well. It lets you create data structures just fine, but the capability to create code, dynamically, at runtime, surely the defining characteristic of a shared instruction-data architecture, is all but completely absent.