[net.lang.c] More extensions to C

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