[net.lang] Language Comparison, Stacks, etc

Richard@houxk.UUCP (10/12/83)

This is a open request to this newgroup for information, opinions and
examples. I am a casual user of Pascal and C.

Recently,  I read a Consultants report done by BBN for Lawrence Livermore Labs
comparing and contrasting 4 different high level languages: Ada, Praxis, 
Pascal and C. The document is available as a DoD report.

There were a few questions I had regarding recommendations of the report. 

1)	BBN said that the lack of a variant record structure in C was a 
	serious weakness. I didn't feel that way based on my frequency of 
	it's use in Pascal. Am I mistaken? Are there serious examples of 
	places where it is ABSOLUTELY needed?
2)	What is overloading? Ada is claimed to have too complicated a 
	scope rule due to overloading. Could someone tell me in plain english
	what is overloading AND is it a frill?
3)	What is the Pascal mechanism used by the compiler to implement 
	the display mechanism? As I understand it, the display is a way
	for a called procedure to determine the values of a caller procedures
	local variables. It seems to be a secondary stack whose contents
	are those stack addresses at which the starting addresses
	of each procedure frame resides. Is this correct. If so, do compilers
	allocate this secondary stack pointer (display stack pointer) as
	a general purpose register (e.g. %r3 of VAX-11/180) or in a fixed
	memory address?
4)	One unrelated but interesting question: Is a negative growing
	stack frame discipline better or worse than positive growing
	stack frame discipline? Is a ngs discipline re-traceable 
	or reconstructable if the stack frame gets broken during run
	time? Is there a public domain recovery procedure for ngs short
	of killing the process?

Regards,
(No Flames please, just illumination)
Richard Trauben 
AT&T Bell Labs
(201) 949-0088

leichter@yale-com.UUCP (Jerry Leichter) (10/12/83)

Overloading, as the term is used in ADA, refers to the use of a single symbol
to denote a number of different functions, depending on the types of its
arguments.  Thus, in some languages, the "+" in a+b could be integer addition,
real addition, or even string concatenation, depending on whether a and b were
integers, reals, or strings.  Because of its multiplicity of types, and the
mechanisms it provides for the user to define new types and extend existing (or
new) operators to them, ADA makes a bigger issue of overloading than earlier
languages - although the idea has obviously been around since at least FORTRAN.

I find the argument that "C doesn't have varient records" strange.  It does;
that's what unions are.  What it doesn't have is the ability to have the
compiler insert varient-dependent code for you, as PASCAL and some other
languages do.  This isn't surprising, since the ability to make any sense of
such automatic code insertion seems inextricably bound up with a stricter
type mechanism than C supports - i.e. this criticism seems to be just another
way of saying "C doesn't have strong typing".

I know of no reason to suppose that there is any difference between negative
and positive growing stack disciplines EXCEPT in cases where you want to grow
the stack dynamically in a paged environment, want to be able to allocate
less than a full page to the stack, AND your hardware doesn't support the
right kind of limitation.  This is vague; here's a concrete example.  On
11's and VAXes, stacks grow downward (toward smaller memory locations) and
pages are 512 bytes.  Suppose I want a 256-byte stack (or a k*512+256 byte
stack; it's the same issue) and I want the memory mapping hardware to give
me an interrupt when I overflow.  So I have to map 256 bytes.  No problem;
on almost any machine, I can map the bottom 256 bytes of the page, and start
the stack at the last mapped word.  When the stack overflows the bottom of
the page, I'll know about it.  Problem:  Suppose I want to extend the stack.
I can do this by adding a WHOLE other page with addresses BELOW the bottom
of what I already have, but I cannot re-use the upper half of my already-
mapped page, nor is there any way to add less than a whole new page - unless
I'm willing to move the existing stack.  This problem does not arise on an
11 or VAX, since I can tell the memory mapping hardware to map the TOP 256
(or whatever) bytes of a page, rather than the BOTTOM ones, if I want.  Such
downward-growing pages are typically used exactly for stack space.

BTW, you left out another distinction I can make in maintaining stacks,
independently of growth direction:  Does the stack pointer point to the
last element put on the stack, or the the next element to be put there?
On the 11, stack manipulation is based on the auto-increment and auto-
decrement addressing modes.  Thus

	mov	item,-(r1)	*r1-- = item	push item
(oops, wrote the C backwards!  should be:
				*--r1 = item
	mov	(r1)+,item	item = *r1++	pop item

This implements a downward-growing stack in which the stack pointer (r1)
points to the top item on the stack.  It works that way because -(r1) is
a PRE-decrement, but (r1)+ is a POST-increment.  I could just as well have
done:

	mov	item,(r1)+	*r1++ = item	push item
	mov	-(r1),item	item = *--r1	pop item

That would implement an upward-growing stack in which the stack pointer points
to the "next" item.  The downward-growing stacks used by just about all 11
and VAX code are essentially a matter of convention - a convention strongly
encouraged by the hardware, which uses it for its own stack manipulation (on
subroutine calls and interrupts) and the various operating systems.
						-- Jerry
				decvax!yale-comix!leichter leichter@yale

mark@cbosgd.UUCP (Mark Horton) (10/14/83)

C not only has variant records (e.g. unions), but it is possible to
have DYNAMIC sized records, of a sort.  E.g.
	struct string {
		short length;
		char body[1];
	} *p;
	...
	p = malloc(sizeof (struct string) + strlen(str));
	p->length = strlen(str);
	strcpy(p->body, str);
Try doing THAT in Pascal!

A display is not part of the Pascal Language.  It's a technique a
compiler writer can use in a block structured language to implement
block structure.  It's basically an array of frame pointers, one
for each level of static scoping.  There are other implementations,
for example the P compiler uses a "static link" to the stack frame
of the next static level - to reference a variable 3 levels out,
you follow a chain of static pointers of length 3.  There is a special
pointer for global variables, since they are a common case.  In
ordinary Pascal programs that aren't nested very deep, this works
reasonably well, but in a deeply nested program a display can be
much much faster.