Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Kaz Kylheku <643-408-1753@kylheku.com> Newsgroups: comp.lang.c Subject: Re: Loops (was Re: do { quit; } else { }) Date: Tue, 22 Apr 2025 19:26:19 -0000 (UTC) Organization: A noiseless patient Spider Lines: 117 Message-ID: <20250422103555.547@kylheku.com> References: <87ecxmv4t4.fsf@nosuchdomain.example.com> <20250420200823.908@kylheku.com> <20250421113640.839@kylheku.com> <20250421125957.29@kylheku.com> Injection-Date: Tue, 22 Apr 2025 21:26:19 +0200 (CEST) Injection-Info: dont-email.me; posting-host="537fe17c48f9c04d98dc75d8e3fbb7fc"; logging-data="1325735"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/W09XgjKSs0nOTQh/1cMWohm4ZLWQk+1E=" User-Agent: slrn/pre1.0.4-9 (Linux) Cancel-Lock: sha1:ZKidUiz40wjPxkj1hj+hydBIzvM= Bytes: 6166 On 2025-04-22, bart wrote: > BTW here is that macro definition from Lua: > > #define op_arith(L,iop,fop) { \ > TValue *v1 = vRB(i); \ > TValue *v2 = vRC(i); \ > op_arith_aux(L, v1, v2, iop, fop); } I'm assuming that op_arith is called numerous times to define handling for various VM opcodes. It *reliably* writes a bunch of code that would otherwise require a lot of error-prone copy and paste. This is language extension; the LUA maintainers have written themselves an op_arith language feature. The generated codee is large and complex, but at least you can see it. If that language feature were wired into the compiler, it would only be harder to work with. All that morass of code would be hidden inside, generated into some intermediate representation (that you can perhaps intercept and get in some readable form, in a language/notation you will have to learn). > It calls yet more macros, and those in turn call others; here are a few > for vRB: > > #define vRB(i) s2v(RB(i)) > #define s2v(o) (&(o)->val) > #define RB(i) (base+GETARG_B(i)) > #define GETARG_A(i) getarg(i, POS_A, SIZE_A) > #define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0))) > #define cast_int(i) cast(int, (i)) > #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) > #define cast(t, exp) ((t)(exp)) Some of these look like low value. For instance cast_int(x) saves no characters over cast(int,x), and ony one character over cast(int, x), and that is longer than just (int)(x), not to mention (int)x situations where you can omit parentheses. I've only defined cast macros for the purpose of switching between C casts and C++ casts. If that's not going on here, it's just gratuitous macrology. The switching I'm talking about is this: #ifdef __cplusplus #define strip_qual(TYPE, EXPR) (const_cast(EXPR)) #define convert(TYPE, EXPR) (static_cast(EXPR)) #define coerce(TYPE, EXPR) (reinterpret_cast(EXPR)) #else #define strip_qual(TYPE, EXPR) ((TYPE) (EXPR)) #define convert(TYPE, EXPR) ((TYPE) (EXPR)) #define coerce(TYPE, EXPR) ((TYPE) (EXPR)) #endif The purpose is to gain access to the finer-grained C++ casts when the code is compiled as C++, but fall back on the C casts when it is compiled as C. These macros *do* something, so they are needed. I don't want to have #ifdef __cplusplus all over the place and write the same expressions twice with different casts. > So what language would say this program is written in? Obviously C. C has preprocessing and so, the above is what C sometimes looks like. It's obviously not written in the C-without-preprocessing subset of C. >> I would expect that Lua has more than one artithemetic >> operation, so sharing code saves coding effort (actually, most >> of tag mainipulations probably can be shared by all Lua instructions). > > Any reason to uses *seven* levels of macro invocation? That is all in > one branch. It allows the code to be built up in small chunks that are easy to understand (when looking at the macro definitions). If all else is equal, such as the sizes of the code mountains, one layer of macro to generate the mountain of code is almost always going to be objectively worse than a macro defined in several hierarchical levels that offer some meaningful "chunking" to someone reading the code. The definition will likely be more condensed, due to certain lower level macros are used more than once in the higher level ones. > Do you think that's too many? Perhaps only 3 levels would have sufficed. Low-value macros that only add levels of expansion without payoff should be avoided. If there are 7 levels, but 4 of them are some low-value syntactic sugar, a case can be made for reducing. If we go by the chunking concept in cognitive psychology, that people do well with an abstraction layer that has about 7 chunks of content, in 7 layers of 7 chunks, we get a hierarchy with 800,000 items at the leaf level, which is an improbable morass. In 7 layers of macros, some of the layers are going to have low branching factors, just providing some minor notations, sometimes of little value. > Or would you automatically say it was reasonable no matter how many > levels there were, just to disagee with me and to side with a fellow C > programmer? You're trying to say that C is a bad language because you can have 7 or more layers of macro expansion, but you're not considering how bizarre and crippling restriction it would be to put a cap on it. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca