[m-dev.] For review: Add implementation of reference types (global heap)

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Jun 10 22:52:10 AEST 1998


On 10-Jun-1998, Peter Schachte <pets at students.cs.mu.oz.au> wrote:
> On Wed, 10 Jun 1998, Fergus Henderson wrote:
> 
> > On 10-Jun-1998, Peter Schachte <pets at students.cs.mu.oz.au> wrote:
> > > Now that I think about it,
> > > 
> > > 	:- type nb_reference(T) == c_pointer.
> > > 
> > > isn't really what I want to write.  In fact
> > > 
> > > 	:- type nb_reference(T) ---> nb_reference(c_pointer).
> > > 
> > > isn't quite right, either, because I don't want even this module to be
> > > trying to poke around inside it.
> > 
> > The declaration you're talking about doesn't let this module
> > poke around inside it.  So I don't see what you're complaining about.
> 
> Well, I can confuse myself by doing:
> 
> 	X = nb_reference(Y)
> 
> That's really nonsensical and shouldn't be allowed.

Think of the `nb_reference' constructor/deconstructor as a cast operator
that casts from `c_pointer' to `nb_reference' or vice versa.
Then it is no longer nonsensical.

Whether or not it should be allowed is another question.
But any language can be abused.  We should not try to protect against
every possible kind of abuse, only against the ones that do cause
problems in practice.  I don't think this is one of those cases.

> > > The type should be abstract even in this
> > > module. What I'd really rather write is just
> > > 
> > > 	:- type nb_reference(T).
> > > 
> > > (which already appears in the interface section).  The type is defined
> > > entirely in C, and as far as Mercury is concerned, it's a Word and that's
> > > all it needs to know. 
> > 
> > Well, if we were going to allow something like this, I think we should
> > require some kind of explicit declaration, rather than just
> > assuming that if it is not defined here then it is defined elsewhere.
> 
> But as far as this module, and in fact all the Mercury code, is concerned,
> it doesn't matter whether or not it is defined.  Maybe I'm interfacing to
> assembler code, and there is no explicit type declaration anywhere.

Even if this were true (as Tom noted, io__write et al mean that it's not)
I would not considered this to be sufficient justification for departing
from the general principle that every declaration should have a corresponding
definition, regardless of whether or not that definition ends up actually
being used.

> > Declaring a type and not defining it ought to be an error
> > (just as declaring a predicate or function and not definition it is
> > an error).
> 
> That's the status quo I'm proposing to change.

Fair enough, but I find your arguments so far unconvincing.
I prefer favouring uniformity (consistency) of the language rules,
and better (earlier) error detection, rather than making an exception
in this case simply for the sake of less typing.

To elaborate on the error detection issue, my point here is that
allowing declarations without definitions could lead to undetected
errors in library modules.  For example, if I have a library module

	:- module foo.
	:- interface.
	:- type some_very_long_name.
	...
	:- implementation.
	:- type some_very_longname ---> ...		% oops, misspelt

then the fact that the name is misspelt in the definition could go
undetected at compile time.  It might only be detected at link time or
even run time, and only if you link against something that makes use of
the type_info for the type `some_very_long_name'.

Thus, if we were going to add the feature you want, I would much
prefer a syntax which required some explicit definition of the type. 

Your suggestion of `:- type foo is opaque.' is not a bad one, but
this raises an immediate question: how many bits should the Mercury
system use to store a value of this type?
The current Mercury implementation uses a fixed number of bits
for values of any type, but this need not be true in general.
Using `c_pointer' immediately answers that question:
the answer is "the same number of bits as in a C `void *'".

> > But you can already accomplish basically the same thing, using the
> > `c_pointer' abstract data type, so I don't think this sort of
> > extension would be worthwhile.
> 
> It's not really the same thing.  The current way is really a lie.  I'm
> saying that this type has terms of the form nb_reference(X), which I can
> unwrap if I want. That's certainly not how I've been thinking of that type. 

This is your strongest argument.  The current method works,
and is no problem in practice, but you can argue that it doesn't
follow the principle "say what you mean".  Arguably we should
provide some syntactic sugar that has the same effect but whose
syntax more closely corresponds with what you want to say.

But this issue comes up only rarely, so I'm not sure that it's
worth a language extension.

> Right now, Mercury has no straightforward way (that I know of) to declare a
> type all instances of which are opaque (to Mercury code) and can't be
> unified or otherwise confused with other such types.  Have I missed
> something?

The unit of encapsulation in Mercury is the module, not the type,
but you can of course use nested modules:

	:- type foo == opaque:foo.
	:- module opaque.
	:- interface 
		:- type foo.
	:- implementation.
		:- type foo == c_pointer.
	:- end_module nested.

I prefer the simpler `:- type foo ---> foo(c_pointer).', though.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.



More information about the developers mailing list