Saturday, September 30, 2006

Restricted pointers and heap classes

Ik think I have found a solution for the pointer issues I described in my last writing. And this solution is called 'restricted pointers'. The idea is introducing a new kind of pointer type. The syntax is not fixed yet, but I think I will use an ampersand ('&') as it resembles the 'reference' from C++.

The 'normal' pointer type that Hyper already has, resembles the pointers from C++; they can point to things just anywhere. The new restricted pointer type will be primarily used to point to stack objects. Such a restricted pointer should be impossible to copy outside of the stack that carries the object it points to. So you will not be able to use a restricted pointer in a class field, or pass it to code on another thread. Also, a restricted pointer will be guaranteed to be not null. If you know C++ you will see that this looks a lot similar to C++ references. But C++ references are references and restricted pointers are not references; variables of a restricted pointer type will be changeable to point to another thing, and that is not possible in C++ with references.

So whats the use of this new pointer type? It will be used to guard things on the stack. You will get a restricted pointer to a stack variable and you will not be able to carry that pointer outside of the lifespan of that stack variable. If the compiler auto-references a value on the stack (or a literal) then it will have a restricted pointer type:

var x : & const byte = 29 # 'x' is a restricted pointer

Of course a normal pointer will be convertable to a restricted pointer, it will just restrict its use of the thing pointed to (it will not be storable outside the stack). But this conversion will require the insertion of a runtime check for null, because normal pointers can be null and restricted ones cannot. And a conversion from restricted to normal pointer will not be allowed.

Another protection measure we have to take is to forbid procedures to return just any restricted pointer. After all, allowing that would allow a procedure to return a pointer to a variable in that procedure and that ceases to exist. But returning a restricted pointer that was retrieved as a parameter for the procedure will be allowed. Another important issue is the this pointer. It will no longer have a pointer type, but a restricted pointer type. The reason for this is that a procedure cannot know at compile time (for all uses) if the object it belongs to is on the stack or not. Examples:
class C
public:
# some code here ...

procedure p1() : * C
return this # ERROR: this object could be on the stack
end procedure

static procedure p2() : & C
var c : C
return c # ERROR: c is on the stack and will be destroyed
end procedure

static procedure p3(c : & C) : & C
return c # OK : c still exists when pointer is returned
end

end class
The fact that a class cannot use its this pointer anymore in any way it would want could sometimes be very annoying. This inspired me to create 'heap classes'. These classes are declared to be always on the heap and never on the stack. This could be useful for some types with a long lifetime, like a GUI widget or a ServerSocket. For these classes the this pointer would be of a normal pointer type, instead of a restricted type, because such classes can never be on the stack anyway. The compiler also would not auto-generate an assignment operator, because a copy-by-value operation will in general be unneeded or unwanted for heap objects. A possible syntax for declaring a heap class would be the addition of an asterisk to indicate the use of a normal pointer for this. Example:
class * Widget
# this is a heap class
end

So this is my proposed solution for the pointer issues. It would be a simple solution for the copy-constructor-called-with-null-argument problem: copy constructors will use as argument type a restricted pointer from now on. The compiler will prevent a null value being assigned to a restricted pointer. And restricted pointers will also be useful for memory management: a procedure that takes a restricted pointer actually guarantees that it will not store the pointer on some place. Instead, it will probably use the info on that object (or copy the object entirely) and then discard the pointer. This will avoid an unnecessary copy for safety purposes.

Comments are of course welcome.

No comments: