kwh@bentley.UUCP (KW Heuer) (05/16/86)
In article <2741@utcsri.UUCP> greg@utcsri.UUCP writes: >In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: >>3) Exchange operator. ... > >Good stuff. Even machines without an EXG can use a scratch register, which >is better than using a user-supplied temp. This could be considered a special case of my ",," operator: to exchange x and y, write "x = (y ,, (y = x))". >What, by the way, is the XOR trick? "x ^= y; y ^= x; x ^= y;". Not useful for floats or structs. >>5) Allow immediate constants. [Generalization of quoted strings.] >>... Why not int *p = &5 ... Does "&5" point to a character, short, int, unsigned, or long constant? (No fair using the left side of the assignment to disambiguate!) >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{ .bar = "Ergo Sum"; .f1 = 73; .f2 = '?'; }; > >This allows the use of unnamed (structure constants). ... I think it is >important that the member names be used instead of the order. Yes, because then you could use unions too. In fact, a similar notation would allow the compile-time initialization of a union, something I've wanted for some time. (I hear ANSI wants to use the first member of the union for initializations. Sorry folks, I want to initialize an array[2] of union {int;char*} to { {12}, {"foo"} }.) >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. Umm... I think it's better if the compiler does include the call to func(). The constant assignment to ".bar" can be optimized out, of course, and the structure itself need not exist. (xchar = (void)func(i),ychar+1) >>6) Eliminate arrays altogether! You want to take them *out* of the language? I say let's put them *in*! As it stands, arrays are half-implemented. >>And it wouldn't matter whether a variable was defined differently than it >>was declared (char x[] or char *x). I don't get it. If "char *x" is valid for all array/pointer variables, where does the memory come from, malloc()? >>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. (Sorry I had to quote so much here.) This has *nothing* to do with the C language; we are now in the realm of compiler implementation. Here's a counter-proposal: compilers should allocate registers based on the last declaration instead of the first. (This is quite legal; "register" has no guaranteed semantics.) In the above example, i and j would be auto, while k, l, m, and ii would be register. No need to save registers in the middle of a function. Better yet, Let's make the compilers smart enough to allocate registers on their own, and make the "register" keyword obsolete! (DEC did this.) Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
franka@mmintl.UUCP (Frank Adams) (05/21/86)
In article <826@bentley.UUCP> kwh@bentley.UUCP writes: >In article <2741@utcsri.UUCP> greg@utcsri.UUCP writes: >>In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes: >>>3) Exchange operator. ... >> >>Good stuff. Even machines without an EXG can use a scratch register, which >>is better than using a user-supplied temp. > >This could be considered a special case of my ",," operator: to exchange x >and y, write "x = (y ,, (y = x))". I would prefer a syntax like "{x, y} = {y, x};" It's more readable. (BTW, a really good optimizing compiler can optimize out the temporary. I'm not fully up on what optimizers are doing these days, but I doubt that there are many compilers which do this. Optimizing it out is easier if it is declared locally ("{int temp = x; x = y; y = temp;}") instead of being declared at the top of the routine.) Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
kwh@bentley.UUCP (KW Heuer) (05/26/86)
In article <1483@mmintl.UUCP> mmintl!franka (Frank Adams) writes: >In article <826@bentley.UUCP> kwh@bentley.UUCP writes: >>[Swap] could be considered a special case of my ",," operator: to exchange >>x and y, write "x = (y ,, (y = x))". > >I would prefer a syntax like "{x, y} = {y, x};" It's more readable. Yes, for a swap. The real power of ",," is for removing explicit temporary once-only variables in general; for example, it allows the function int pop() { int temp1; struct stack *temp2; temp1 = stk->top; temp2 = stk->next; free(stk); stk = temp2; return (temp1); } to be abbreviated to the macro #define pop() (stk->top,,(stk=(stk->next,,free(stk)))) (A sort of generalization of the postfix operators. "++x" means "x=x+1", but "x++" means "x,,(x=x+1)".) >(BTW, a really good optimizing compiler can optimize out the temporary. I'm >not fully up on what optimizers are doing these days, but I doubt that there >are many compilers which do this. Optimizing it out is easier if it is >declared locally ("{int temp = x; x = y; y = temp;}") instead of being >declared at the top of the routine.) Unfortunately, I think the "clue" gets lost before the optimizing phase. Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
ron@brl-sem.ARPA (Ron Natalie <ron>) (06/01/86)
In article <856@bentley.UUCP>, kwh@bentley.UUCP (KW Heuer) writes: > > >(BTW, a really good optimizing compiler can optimize out the temporary. I'm > >not fully up on what optimizers are doing these days, but I doubt that there > >are many compilers which do this. Optimizing it out is easier if it is > >declared locally ("{int temp = x; x = y; y = temp;}") instead of being > >declared at the top of the routine.) > > Unfortunately, I think the "clue" gets lost before the optimizing phase. > Eh? Unless you have a machine that has an exchange operator, the compiler is going to have to allocate a temporary anyhow. I can't see yow a compiler could generate better code for x,,y than what most compilers (even before optimization do for {register temp =x; x=y; y=temp}. -Ron INEWS SUCKS INEWS SUCKS INEWS SUCKS INEWS SUCKS