This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

NICE Language Committee: ms-addr

-----------------------------------------------------------
Key: MS-ADDR
Title: Taking the address of a feature.
Current status: under discussion
-----------------------------------------------------------
Proposal (Michael Schweitzer)

It is currently only permitted to take the address of a feature
as part of the list of actual arguments of a call. An assignment
of the form
            p := $feature_name,

where `p' is a local entity or an attribute of type POINTER
is not permitted. This is an exception to the otherwise general
rule that everything that can be used as an actual argument can
also be used as the right hand side of an assignment (and vice versa).

Proposal:

I propose that the construct 'Address' should no longer be part of
the construct 'Actual'. Instead it should become one of the alternatives
of construct 'Expression'. The syntax should be

            Address = "$" Feature_name

This is an expression of type POINTER. 'Feature_name' must be the
final name of a feature of the class which is not a constant
attribute.

Required changes:

Minimal changes in the syntax (which must be corrected anyway
since it currently reads '$Identifier' instead of '$Feature_name').
The semantics (p. 405) remain the same.

-----------------------------------------------------------
Agreement (Steve Tynor)

I support this. Our customers have specifically requested this and the
Tower compiler now handles it.

| This is an expression of type POINTER. 'Feature_name' must be the
| final name of a feature of the class which is not a constant
| attribute.

Why should it be restricted to features of the class and not an Entity?
It is sometimes useful to pass the address of a local variable, Current
or Result.  I believe the ISE compiler supports this (it was a source of
early incompatibility back in the dark ages of TowerEiffel's infancy).

So, perhaps

	Address = "$" Entity_or_feature_name
	Entity_or_feature_name = Entity | Feature_name

(I'm definitely open to suggestions for a better name for
Entity_or_feature_name).
----------------------------------------------------------
Rebuttal (Bertrand Meyer)

This proposal does not seem to fulfil any useful purpose
and creates major implementation difficulties.

Values of the Address type were explicitly introduced for
passing to external routines and nothing else. There is
no clear use for keeping them in Eiffel attributes or other
entities.

Accepting this proposal would make it impossible to write
a safe garbage collector, or at least make this task very
difficult. Assume u is an attribute of type POINTER.
If u is assigned the value of $a, where a is an attribute,
then the associated object must be explored by the garbage
collector (e.g. for marking). But later on u may be assigned
the value of $r where r is a routine. In this case the GC should
not follow the reference. But how can the GC distinguish between
references to objects and references to routines?

I suggest we reject this proposal.

-----------------------------------------------------------
Steve Tynor, 31 March 1994, reply to BM

In TowerEiffel a POINTER is not traced by the memory manager unless
explicitly asked to via `adopt', whether in C or in Eiffel.

| But how can the GC distinguish between
| references to objects and references to routines?

In the same way that it handles CECIL's `wean' and `adopt' functions (or
whatever equivalent features it provides for external C references). In
TowerEiffel, we provide `wean' and `adopt' as features of class MEMORY:

   adopt (ptr : POINTER) is
	 -- Inform the garbage collector that you have taken the address of an
	 -- Eiffel object and are either storing its address in a POINTER
	 -- attribute, or are passing it to an external function. Corresponds
	 -- to the CECIL `adopt' function.
      require
	 non_null: ptr /= null_pointer;
	 -- `ptr' is a pointer to an Eiffel reference, not an expanded object.

   wean (ptr : POINTER) is
	 -- Inform the garbage collector that you are no longer storing the
	 -- address of an Eiffel object in a POINTER attribute, or have
	 -- finished passing it to an external function. Corresponds to the
	 -- CECIL `wean' function.
      require
	 non_null: ptr /= null_pointer;
	 -- `ptr' is a pointer to an Eiffel reference, not an expanded object.

-----------------------------------------------------------
Bertrand Meyer, 31 March 1994, reply to ST

I don't think you got my point.

u := $a



-- Various things happen to the object attached to a
-- so that it becomes unreachable.

-- The garbage collector collects it.

-- 10 hours later:

p (u)


We are passing to p a reference to an object that
does not exist any more.

`adopt' is for Cecil, that is to say, for using
Eiffel software from C. Within Eiffel software
I don't think anyone should be required to use
features such as `adopt' or `wean'. The risk of
forgetting such a call is high, and is precisely the
kind of thing that automatic GC is meant to avoid.
In addition these calls are eminently non-portable.

-- BM
-----------------------------------------------------------
Steve Tynor, 1 April 1994, reply to BM

My point is that this is not fundamentally different than holding a
reference `outside' of Eiffel (which is what CECIL's `adopt' function is
for: to inform the collector that you are holding a reference to an
object that it might not otherwise find.). The `adopt' feature in class
MEMORY serves the same purpose for references turned into POINTERs but
held on the Eiffel side.

So one would program your example above as:


	adopt ($a);
	u := $a;
	-- 10 hours later:
	p (u);
	wean (u);

which is really no different conceptually, except that you avoid
requiring the programmer to write some messy C code, as:

	extern_set_u ($a);
	-- 10 hours later:
	extern_p;

and in the C externs:

	#include 
	EIF_POINTER my_ref;
	void extern_set_u (EIF_POINTER u)
	{
	   adopt (u);
	   my_ref = u;
	}
	void extern_p ()
	{
	   /* do something with `my_ref' */
	   wean (my_ref);
  	}

-----------------------------------------------------------
Reply: Bertrand Meyer (1 April 1994, to Steve Tynor)

In this case, it seems cleaner to be able to keep the Eiffel-reference
bookeeping in the .e file rather than requiring an escape to C.
`adopt' is for Cecil, that is to say, for using
Eiffel software from C. Within Eiffel software
I don't think anyone should be required to use
features such as `adopt' or `wean'. The risk of
forgetting such a call is high, and is precisely the
kind of thing that automatic GC is meant to avoid.
In addition these calls are eminently non-portable.

-- BM

-----------------------------------------------------------
Reply: Michael Schweitzer (Early April 1994, to BM)

I think it is very difficult to prevent assigning the
address of an Eiffel object to an attribute of type POINTER.
One could, for example, have an external routine

        attach_pointer (addr1, addr2)

which stores 'addr2' in the location to which 'addr1'
points (i.e in C:  *addr1 = addr2;). Then the call

        attach_pointer ($p_a, $attr),

where 'p_a' is an attribute of type POINTER and 'attr'
is some other attribute, will have the desired (or
rather undesired) effect.

The obvious way to make all this impossible is to say
that an attribute may not be of type POINTER. But this
is, in my opinion, a bad idea. Attributes of type POINTER
are sometimes necessary to store a reference to some
non-Eiffel resource (such as an X-Window data structure).
Another possible solution is to restrict the address
operator to routines only. If one cannot take the
address of an attribute, the problem vanishes. But then
we must still deal with the situation that a function
can be redefined to be an attribute.

I think that the question can be split into two:

    1) Should it be possible to assign the address
       of an attribute to another attribute _in Eiffel_?

    2) Should it be possible at all. That is, if we find
       a way to avoid it inside of Eiffel code, should we
       try to make it impossible in external routines as
       well?

Perhaps we should put MS-ADDR into catalog 3 now? At
least for a while.


[... Two lines of Michael's message, now irrelevant, omitted ...]

Best regards,
    Michael