This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: struct experts?


Dirk Herrmann <dirk@ida.ing.tu-bs.de> writes:

> As I've learned now, structs are to be replaced.  Still, I think that we
> will not be able to do everything in one big step, i. e. integrate goops
> + integrate the new gengc + integrate the environments + replace structs +
> replace smobs + change numbers.c to use goops + ...
> 
> Therefore, I'm more in favor of proceeding in smaller steps, at least it
> is the way that I'd like to contribute to guile.  Therefore, I would like
> to get a better understanding of how structs work and why they are
> implemented this way.  Even if they are replaced some day, there is
> probabaly still a lot to be learned from the current
> implementation.  Thus, my short term goal is to clean up the current 
> struct implementation, which will make it easier to replace them in the
> long term.

While I strongly suggest *not* cleaning up the struct implementation,
I got a minute over, and will try to do some explaining.

> * Why does every _instance_ of a struct hold a setter field?  wouldn't a
>   single setter field for the corresponding struct type be enough?

Firstly, structs are not divided into classes and instances.  Structs
are symmetric in this respect: The thing corresponding to classes is
called "vtable".  Every struct can be a vtable for some other struct,
including itself.  (The difference between this situation and GOOPS is
that every GOOPS instance *can't* be a class for another instance; in
GOOPS, classes and instances usually have different structure.)

Structs were originally designed to be symmetric.  This is not some
later add-on.

The normal case is a chain of three structs: 1. the vtable-vtable,
which is the vtable of 2. the "type" struct, which is the vtable of
the "instances".  For records this is: 1. record-type-vtable, 2. the
record type returned from `make-record-type', and, 3. the records.
The vtable-vtable is also the vtable of itself.  This corresponds to
GOOPS' 1. <class>, 2. <my-class>, 3. instances of <my-class>.

Regarding your question: It is not true that every "instance" hold a
setter field.  Only "entities" hold a setter field.

GOOPS supports two kinds of funcallable instances: <operator> and
<entity>.  For <operator>s, the procedure and setter are stored in the
class.  For <entity>s, they are stored in the instance.  Since GOOPS
is based on structs, I've added support for both kinds to structs.

[Structs were complex to begin with.  When making my extensions, I've
been concerned with getting GOOPS up and running, not with getting the
maximally beautiful solution.  It was decided that structs should be
replaced already when Jim became maintainer, and this is the
assumption I've worked under.]

Typical examples: A matrix in my matrix library can operate on a
vector.  The method of its operation is the same for all instances, so
it is naturally an <operator>.  One generic function behaves
differently from another, so it is naturally an <entity>.

It is important to note that the class of an <operator> can itself be
an <entity>.  (I originally thought I was crazy building in support
for this, but then the need arose in one of my applications!)

> * What is the purpose of the procedure slot, which is also provided for
>   every instance?

Again, it is not provided for every instance.  The purpose is to hold
the procedure describing the behaviour of entities.

> * Why does every _instance_ of a struct hold a destructor field?  Again,
>   one destructor for the struct type should be enough.

The destructor in struct V describes how to destroy structs which have
V as vtable.  The symmetry of structs demands that all structs have
destructors, since, at any time, the user can use the "instance" as
vtable.

This is not the case in GOOPS, since normal GOOPS instances have a
special "light" representation: it only contains storage for the slot
values, and no more.

> * What is the meaning of the 'user' fields of a vtable?  In struct.h there
>   is an identifier scm_vtable_offset_user defined.

Fields at scm_vtable_offset_user are user defined, lower indices are
defined (and required) by the system.

> * What is the reason that the car element of a struct points to the vtable
>   _data_ rather than the vtable?  It may be a performance consideration,
>   but it complicates the code a lot and I wonder if it is really such a
>   common operation to access the vtable data.

The vtable data is accessed all the time: in GC and when deciding how
to access a slot.

> * Currently, a struct is distinguished from a gloc (whatever that is) by
>   the following property:  If the 'car' of the cell points to a memory
>   region of scm_bits_t entries, where the second entry is zero, then it is
>   a struct.  Is there a different way to distinguish this?

No, or rather: not until now.  The type space is currently quite
filled.  The only alternatived which existed previously was to
introduce yet another malloc block, which would decrease performance
noticeably.

This is one of the reasons why we have introduced the double cells:
They will make new kinds of representations possible, and will allow
us to make the type space less crowded.

So, what about cleaning up structs using this technique?

No, we want to use that energy in constructing the *real* solution.
The amount of work in changing the struct representation in this
respect would be less than, but of the same order of magnitude as
making the new record representation.


Hope this makes some thing clearer,

Best regards,
/mdj

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]