From post@volker-wysk.de Mon Nov  5 22:38:28 2001
Received: from volker (mail@dsl-213-023-038-160.arcor-ip.net [213.23.38.160])
	by swi.psy.uva.nl (8.11.2/8.11.2) with ESMTP id fA5LcRt06121;
	Mon, 5 Nov 2001 22:38:27 +0100 (MET)
Received: from localhost ([127.0.0.1] ident=v)
	by volker with esmtp (Exim 3.22 #1 (Debian))
	id 160rR4-0000jh-00; Mon, 05 Nov 2001 22:37:38 +0100
Date: Mon, 5 Nov 2001 22:37:38 +0100 (CET)
From: Volker Wysk <post@volker-wysk.de>
X-X-Sender:  <v@volker>
To: <prolog@swi.psy.uva.nl>, Jan Wielemaker <jan@swi.psy.uva.nl>
Subject: Re: [SWIPL] no copy semantics for PlTerm, in the C++ interface
In-Reply-To: <01110512044400.05649@gollem>
Message-ID: <Pine.LNX.4.31.0111052141510.2810-100000@volker>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII

On Mon, 5 Nov 2001, Jan Wielemaker wrote:

> >I'm a little confused now. As far as I can tell from the SWI-Prolog
> >documentation, we have
> >- Terms inside the Prolog machine
> >- pointers inside Prolog to terms (= variable bindings?)
> >- corresponding term_t values on the C side
> >- PlTerm objects
>
> term_t is the same as PlTerm.  term_t is an indirect reference.  It is
> the index of a cell on the local stack containing the value (or a
> reference to the value, but the C/C++ user doesn't need to be aware
> of this.
>
> If you use plain copy of the term_t value, both refer to the same
> value-cell.  And thus:
>
>    <x bound to foo(1)>
>    term_t y = x;
>    PL_put_atom_chars(y, "hello");
>    <both x and y refer to the atom 'hello'>
>
> If you want to see PlTerm objects as holders for a Prolog term writing
> to the copy should not affect the original.  SWI-Prolog defines
> PL_copy_term_ref(), which createa a new term-reference which points to
> the same Prolog term.  Further unification inside this term affects
> both, but assignments using PL_put_* affects only the addressed
> reference.

So the cells on the local stack are references to terms, and PlTerm
objects as well as term_t values are references to references to terms.
The comparision functions - PlTerm::operator==, PlTerm::operator> and so
on - are wrong in this case. They don't compare the values of PlTerm
objects (which are indexes for the local stack), but the terms refered to
by the term references refered to by the indexes. [ Isn't declarative
programming much less of a headache than this? ;-) ]

For instance, if you stored PlTerms in a sorted container, such as a
map<>, you could affect the comparision order of the PlTerms by operations
which either change the terms referred to indirectly, or the term
references refered to. You would mess up the container as a side effect.
This would make it impossible to store PlTerms in sorted containers.

In order to fix that, one could rename PlTerm to PlTermRefRef, and make
the comparision methods compare the term_t values (the stack indexes) the
objects contain. This way, PlTerm objects would behave exactly like
pointers of some type Term**.

Additionaly, one could introduce a class named PlTermRef, which behaves
like a term reference. That is, like a pointer to terms, instead of a
pointer to pointers to terms. One would have to make the object a unique
representation of its term reference. One would have to hide the stack
index inside, so the term reference can't be manipulated except via the
PlTermRef object.


> Maybe some C++ experts can make a neat SWI-cpp.h that complies with
> STL and uses templates?  My C++ knowledge is too limited.  I can help
> with correct implementation though.

I've taken a look at SWI-cpp.h. It doesn't look very difficult to do this.
I'd volunteer to do the C++ things.


Volker

