I'd put it differently because I don't like conflating precedence with
order of evaluation. I'd cite the fact that function arguments are
fully evaluated before the function is called as the "model" for inside
out macro expansion.
Now I'm lost. Is that a rewording of my description, or is it supposed to
support the opposite behavior? I interpret it as supporting my definition,
not the "correct" one.
The problematic version is this:
#define f(a,b) a##b
#define g(a) #a
g(f(1,2))
Trying to make an analogy in proper (non-preprocessor) C, I'd write this:
char *f(char *a, char *b)
{
return strcat(strcpy(malloc(strlen(a)+strlen(b)+1), a), b);
}
char *g(char *a)
{
return strcat(strcat(strcpy(malloc(strlen(a)+3), "\""), a), "\"");
}
int main(void)
{
char *result = g(f("1","2"));
puts(result);
}
So my description of the sane preprocessor follows what normal C code does.
And this is a case where order of evaluation is determined by precedence.
There's no way you can call g until the result of f is known. Mentioning
"evaluation order" is always a good way to start a thousand-post thread
about sequence points so I tried to avoid it until now. I known order isn't
the same as precedence, in an expression like foo()+bar()*baz(). But in this
case, I don't see how you can separate them.
Yes, I did. The rebuttal is that expanding "inside out" precludes an
important use case. I gave that usage but it is true that I left out
the fact that inside out expansion makes it impossible (without
introducing a new quoting mechanism into the pre-processor). You are an
intelligent poster, and I would not presume to patronise you by spelling
it out like that.
Well I wasn't kidding; I really wouldn't mind seeing someone spell out the
rules for nested preprocessor expressions involving both "#" and "##",
because I really don't understand them. I knew my answers to "what will the
output be" were wrong, because I've got enough experience to know that cpp is
scary. I suspected that one of them would output "12" and the other would
output something silly. And I was right about that! But I didn't know which
would be which.
These dark corners of the preprocessor have been explained in one of 2 ways:
1. Useful Idiom Cookbook, with explanations of what the idioms do, but not
much detail on why. They have entries like
#define Str(x) #x
#define Xstr(x) Str(x)
I've used that one a few times. Each time I need it, I have to go find it in
one of my older projects and copy it. I can't write it from scratch. It just
doesn't make sense to me. How an Xstr and Str not do the same thing? The Xstr
definition says to me "do the same thing Str does", but to cpp it says
something else.
2. Standardese, in which every detail is given, enough to reimplement cpp
from scratch, but no rationale.
I'd like to see something in between, in which the individual steps are
actually explained in a manner that makes intuitive sense. Starting from
"these are the idioms we want to support" and working backward to generate
the rules is not helpful.
Your rule is not enough to define the semantics of a macro processor, so
it is not fair to ask for as simple a rule that does. I could, however,
say that "C expands macros left to right" which is short and sweet and
says about as much about the real semantics as your rule does about the
putative semantics of you sane pre-processor. The rationale for this
simple rule is that permits functional forms to be quoted using #.
It sounds like a good start. But since I know how yacc works, I also know
that the main C grammar is also parsed "left to right", with shift and reduce
operations. In other words, this thing I wrote above:
char *result = g(f("1","2"));
can also be parsed left to right, and the result is still that the value
returned by f() is given to g(). I can't see any other meaning it might have.
But when we convert it to the closest possible equivalent with preprocessor
macros, it changes into one of those other meanings that I can't see.