Heron References

Heron reference types are a cross between C style pointers and C++ references. A reference is a handle to a value, which can be shared without copying the value. A variable is also a handle for a value, but copying a variable results in the copying of the value it represents.

In Heron there are several different kinds of references, that represent different kinds of concerns. The two principal kinds of references are strong references which are denoted by a caret or hat symbol ( ^ ) and the weak references which are denoted by an ampersand ( & ). Other references are the result of specific operations and exist primarily for typecasting.

Strong References

A strong reference represents a deletable handle to a dynamically allocated object. When dynamically allocating an object it must be passed to a strong reference, a failure to do so causes a compile-time error. The delete operation may also only ever be applied to strong references. It can be said that a strong reference indicates ownership of an object, and that ownership can be shared with other strong references.

New References

The result of a new operation is actually a new-reference which is a separate kind of reference type. A new-reference is only used for being assigned to a strong reference, and supports no other operations.

Weak References

The more common reference in code, is the weak reference. The weak reference can be assigned from a strong reference, or from the result of an address-of operation. A weak reference does not represent any kind of ownership of the object, and can not be deleted. This reflects the reality that the majority of time, in any code that uses pointers, it is inappropriate to allow explicit deletion of pointers.

Address References

The result of the address-of operation ( @ ) is an address reference. An address reference can only be assigned to a weak reference for the obvious reason that deletion of a value object is a clear error. This kind of error detection is not possible in a single pointer/reference system such is found in C++

References Example

Here is a code snippet which demonstrates how references can and can't be used:
    MyObject obj;
    MyObject^ strong_ref;
    MyObject& weak_ref;
    weak_ref = new MyObject; // compiler error: can't assign a new-reference to a weak-references
    strong_ref = new MyObject;
    strong_ref = @value; // compiler error: can't assign an address-reference to a strong-reference
    weak_ref = @value;
    delete strong_ref;
    delete weak_ref; // compiler error: can't delete weak references
  

Reference Assignment Table

The following table shows which references can be assigned to which references. The top line is the rvalue ( right hand side of an assignment statement )

strongweakaddressnew
strong yes no no yes
weak yes yes yes no

Reference Differentiation Motivation

The reason for the differentiation into strong and weak references is to make explicit ownership semantics. In other words, it is important to identify which references may or may not delete a dynamically allocated object. Traditionally languages with pointers such as C++ and Pascal represents dynamic objects using raw pointers. A raw pointer does not indicate whether that reference is expected to delete or not the value being referenced. This can lead to numerous errors, and requires extra code commenting. It is preferable to have programmer intention explicit within the code. It reduces the possibility of error, and the need for commenting.

Garbage Collection

Clearly Heron has no pre-defined notion of a garbage collector. A Heron implementation can easily choose to provide a garbage collection mechanism. It doesn't conflict with any part of the language, except for one fact: the delete should still remain valid as an indication of programmer intention to no longer use an object, and to trigger a destructor. In the case of a premature call to delete during a non-GC implementation it would eventually result in an error when the object is accessed again later. It would be a good idea for a GC implementation to throw an error earlier, because a GC can triviallly determine that the object is still live. Premature deletion, indicates a specification conflict on behalf of a programmer.

It was important for Heron to allow low-level implementation which don't require a garbage collection mechanism, because it is more appropriate to do manual resource allocation for certain classes of programs.

Copyright 2004, Christopher Diggins, http://www.cdiggins.com