Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site utcsri.UUCP Path: utzoo!utcsri!greg From: greg@utcsri.UUCP (Gregory Smith) Newsgroups: net.lang.c Subject: Re: Boolean Operators Slighted in C Message-ID: <2741@utcsri.UUCP> Date: Fri, 9-May-86 12:57:07 EDT Article-I.D.: utcsri.2741 Posted: Fri May 9 12:57:07 1986 Date-Received: Fri, 9-May-86 15:01:26 EDT References: <602@brl-smoke.ARPA> Reply-To: greg@utcsri.UUCP (Gregory Smith) Organization: CSRI, University of Toronto Lines: 148 Summary: Ok, I'll bite... In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: >2) More of the same. We all know about *++p. But what if I want to jump > more than one element? I can't write *(p += 2); Or maybe I > want to write `p = &(i += 5). You can write *(p += 2). For *p++, you can write *((p += 2 ) - 2 ) if you really want to. If p is a register, there will be little penalty over dereferencing *before* the p+=2. Why you wanna do p = &(i += 5 ) ?????? Like your immortal `exit(1,fprintf(stderr,"Arrg!!\n"))' this is an artificial combination of two unconnected statements. What's wrong with `i+=5; p= &i'? ( You probably prefer i+=5,p= &i; ) > >3) Exchange operator. This has probably been discussed before, so pardon > me if I blunder into that pit. BUT, DMR has stated that one of > the reasons that exponentiation was left out was because no > (or few, if any) machine could do it inline, and therefore > all the compiler would be doing is a function call anyway. > By the same reasoning, exchange CAN be done efficiently by > some machines, and the hack of a temporary variable and > three assignments is a rather stale idiom. The three > statement XOR trick avoids the temporary, at the expense > of execution time and clarity. > Good stuff. Even machines without an EXG can use a scratch register, which is better than using a user-supplied temp. What, by the way, is the XOR trick? >4) Allow complex statements to be considered as expressions so that > the comma operator can be used to avoid braces, as in > > if (e) x = y, return z; > Errr... well.... I'm not a compiler guru, but.... In the current ( conventional ) setup, compilation of expressions is done separately from 'statement processing' ( i.e. returns, ifs, whiles, cases, etc ). Your suggestion would require that the two be entwined together, which would make generation of really good code a difficult thing. Currently, when an expression is found, a tree is built, then the tree is crunched upon, and the code is generated. If every statement was an expression, then expression trees would need to have nodes for ifs and whiles, etc... ( starting to get LISPy). This could of course get very messy, and a really good coder is already a fairly messy thing to do. Besides, I don't think this would help very much, except for Obfuscated C entries. >5) Allow immediate constants. Currently, there is only one special > case, that of a character array. One can say char *p = "string"; > and have the string squirreled away and the (magic) address > stuffed into the pointer. Why not int *p = &5; where the > integer five is whisked away and replaced by its address. > Sure would eliminate a lot of housekeeping variables. > Fine by me. I would also like to suggest struct constants/rvalues. Suppose I have struct foo{ int f1; char f2; char *bar; } foo_var; I'd like to write something like this ( an executable statement ): foo_var = struct foo{ /* set structure value */ .bar = "Ergo Sum"; .f1 = 73; .f2 = '?'; }; This allows the use of unnamed (structure constants). #define cmplx(a,b) struct complex { .r=(a); .i=(b); } #define J cmplx( 0.0,1.0 ) cvar1 = cmul( cvar2, cmplx( 2.0, 1.02 ) ); I think it is important that the member names be used instead of the order. Also, it would be nice if the compiler were smart in cases like xchar = struct foo{ .bar="??"; .f2 = ychar+1; .f1 = func(i); }.f2; not to generate all the code to compute f1 and bar ( Holy side-effects, Batman! ). The above line could arise by a macro expansion. I have though out many of the implementation details, and I *still* think it's a good idea :-). I am very open to suggestions about the syntax. I will ramble on about/ argue about this later if you want ( and probably if you don't want 8-) <- peril-sensitive sunglasses. ). >6) Eliminate arrays altogether! Well not exactly, but make all > arrays vectored in all dimensions. This would show > those quiche eaters what a real tough language C is :-). > Array syntax would still be available of course, but would > be translated into glorious pointer notation. And it wouldn't > matter whether a variable was defined differently than it > was declared (char x[] or char *x). > Fully vectored arrays were used in B, and I like C's stuff better. You can always set up vectored arrays if you want - and still say array[i][j][k] into the bargain. Of course, you have to set up the vectors yourself... > >8) Allow formal arguments to be declared AFTER the opening brace. > This would allow prioritization of register variables. > Well, register arguments need to copied from the stack anyway, so you can declare your own with an explicit copy. But it wouldn't hurt to let the compiler do it. Since it silly ( presently ) to say `foo(p){ register char *p;...' this could be taken as an argument declaration. I have a related suggestion. Suppose I have the following: f(){ ... { int x,y; ... } { double xy; ... } } I would expect x and y to share the same stack space with xy. Now look at this ( assume 4 regs available ): f(){ register i,j,k,l,m; /* more vars than regs available */ { register ii ..... }; } I think the inner loop should push 'l' ( the lowest priority reg var ) on the stack and keep 'ii' in that reg, since ii will probably get more use in the inner block. The register priority would become ii/i/j/k, so if a further nested block said 'register a,b', the next regs to be kicked out would be j and k, leaving the priority as a/b/ii/i. At the end of the block, the value of l would be popped. If the block were the body of a loop, the pushing/popping would need to be done outside the actual loop, for speed. Inside the loop, of course, 'l' would be addressed as an auto. This allows C programmers one more advantage previously available only to assembler programmers: the re-use of registers for completely different things. The problem is that it would make jumping into/out of blocks a mess. I guess the compiler would have to detect this and generate 'fix' code for the jumps. -- "Canabee be said2b or not2b anin tire b, if half thabee isnotabee, due2 somain chunt injury?" - Eric's Dilemma ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg