Swap by name

Chris Torek chris at maryland.ARPA
Fri Jul 4 12:12:00 AEST 1986


	From: Root Boy Jim <rbj at icst-cmr.arpa>

	I seem to remember three types (possibly four) of parameter passing:

	1) Call by value	C scalars
	2) Call by reference	C pointers, arrays, Fortran variables
	3) Call by name		Algol call by name (it also does val & ref)

The fourth method (as you mention later) is call by value-result.

	Call by reference went something like this: the calling
	routine would pass the string representation of the argument
	and the caller would parse it to figure out the argument.

This much work is not necessary.  You simply build static links or
a display and use conventional non-local references in the thunk
procedures.  Each thunk procedure returns a pointer to the variable
that represents the evaluation of the appropriate argument, as
performed in the context of the caller.  (If a compiler-generated
thunk requires a temporary variable---all expression-thunks do---that
temporary is unnamed, so the fact that a Pascal-ish thunk would be
nested one level greater than the caller is irrelevant.  To put it
another way, a compiler can do whatever it wants. :-) )

	From: Doug Gwyn (VLD/VMB) <seismo!BRL.ARPA!gwyn>

[Giving equal time to UUCP domains . . . :-)]

	No, you just implemented an elaborate form of "call by reference".

I merely chose a poor example.  Call by reference and call by name
often have identical effects.  See my followup for a better example.
(Incidentally, my expression `example', contained in a comment,
has a different problem: it returns the address of a stack variable
that is no longer active by the time the caller uses it.  `t' should
have been declared `static'.  This is what comes of dashing off an
article just before bed . . . .)

It is possible to implement full call by name in C, but it is
difficult, for nonlocal reference is difficult; and no one ever
used call by name after Algol anyway---most likely because everyone
thinks it is terrible.  Nonlocal reference *is* possible, but
probably best left to a compiler.  Kludges are not too hard to
write, but are error-prone: the programmer must keep track of the
lexical level of each routine, and know how many levels up to look,
and at what offset, for each nonlocal variable.

The other three of Root Boy's methods of parameter passing are also
available to C programmers.  Call by value is of course trivial.
Call by reference is easy to achieve using pointers (though in fact
the call is still `by value': the value of the pointer expression).
Call by value-result is also easy enough in C, though as with call
by reference, it requires cooperation of both caller and callee:

	/* Call by value-result */
	f()
	{
		int i, j;

		i = 1;
		j = 2;
		call_by_value_result(&i, &j);
	}

	call_by_value_result(addr1, addr2)
		int *addr1, *addr2;
	{
		/* perform the entry protocol: obtain the arguments */
		int arg1 = *addr1, arg2 = *addr2;

		/*
		 * code dealing with `arg1' and `arg2' as though
		 * those were the arguments; no `return's; then:
		 */

		/* perform the exit protocol: modify the arguments */
		*addr1 = arg1;
		*addr2 = arg2;
	}

The entry protocol is the `value' part; the exit protocol supplies
the `result'.  Incidentally, call by value-result is a legal
implementation in at least one of the many FORTRAN standards.  It
tends to surprise those who alias a variable and depend on call by
reference to modify two parameters at once:

	PROGRAM CALLBY
	INTEGER ARG
C Translate the following two PRINTs as appropriate for whatever
C compiler restrictions you have.
	PRINT *, ' If it says "3 3" then "7 7", you have call by reference;'
	PRINT *, ' if it says "3 3" then "7 3", you have call by value-result.'
	ARG = 3
	CALL TESTIT (ARG, ARG)
C N.B.: If value-result, ARG could be either 3 or 7 now!
	STOP
	END

	SUBROUTINE TESTIT (I, J)
	INTEGER I, J
	PRINT *, I, J
	I = 7
	PRINT *, I, J
	RETURN
	END



More information about the Comp.lang.c mailing list