This is the mail archive of the
guile@sourceware.cygnus.com
mailing list for the Guile project.
Macros, SCM and strict typing.
- To: Guile Mailing List <guile at sourceware dot cygnus dot com>
- Subject: Macros, SCM and strict typing.
- From: Dirk Herrmann <dirk at ida dot ing dot tu-bs dot de>
- Date: Tue, 14 Mar 2000 16:55:41 +0100 (MET)
Hello!
The last two days I tried to get guile compiled with SCM, SCM_PACK and
SCM_UNPACK defined as
typedef union { scm_bits_t n; } SCM
static SCM scm_pack (scm_bits_t x) { SCM s; s.n = x; return s; }
#define SCM_PACK(x) scm_pack (x)
#define SCM_UNPACK(x) ((x).n)
This experiment exposed a _lot_ of problems, most of which arise from the
fact, that up to now there has not been a clear distinction between real
scheme values, and between other C values that just happen to be stored
in a SCM variable. Defining SCM as a void*, however, does not expose
these problems.
Example:
The macro SCM_SETCDR is used to store real scheme values in a cons cell,
but also to store smob data in such a cons cell. The difference is, that
a SCM variable which holds smob data (which is some arbitrary C value and
not a real scheme value) is conceptually different from a SCM variable,
that actually holds a scheme value.
Consider the two different alternatives to define SCM_SETCDR:
#define SCM_SETCDR(x, v) (SCM_CDR (x) = (v))
and
#define SCM_SETCDR(x, v) (SCM_CDR (x) = SCM_PACK(v))
If we would use the C function declaration syntax, the first macro could
be defined as:
void SCM_SETCDR (SCM x, SCM v)
while the second corresponds to
void SCM_SETCDR (SCM x, scm_bits_t v)
Let's assume we were using the second interpretation of the macro. This
allows easily to store scm_bits_t objects into cell cdrs, but is
inconvenient when just storing SCM values:
SCM x;
SCM y;
...
SCM_SETCDR (x, SCM_UNPACK (y));
This, to me, is not a very beautiful solution. I like the other
interpretation of the SCM_SETCDR macro much better, because it more
closely matches the concept of 'set-cdr!'. However, when SCM_SETCDR
expects a SCM value as its parameter, setting the smob data or the data
field of lots of other guile internal data types look as follows:
SCM x;
scm_bits_t y
...
SCM_SETCDR (x, SCM_PACK (y));
I consider this not very fortunate also, because I think SCM_PACK should
only be used to transform a scheme value from its representation as a
scm_bits_t value to its representation as a SCM value. It should not be
used to 'cast' arbitrary data to a SCM value. Taking the name SCM_PACK,
(which I like very much because it implies some kind if transformation
that should inhibit the user from fiddling with bits from SCM objects), it
even _sounds_ as if it might be unsafe to 'pack' arbitrary data (which, as
I said, is alright to keep users from trying to be too clever).
I think the consequence is, that we should be able to distinguish between
SCM values as elements of a cons cell, and scm_bits_t values that are
smob data entries, which happen to also be stored in the cdr of a cons
cell.
The consequence, which is already partly followed in guile, is, that
setting the cdr of a cons cell to aribtrary C data, should not be done via
SCM_SETCDR. For smobs, there is already a macro SCM_SET_SMOB_DATA, which
forms such an abstraction layer. This abstraction is, however, not used
very consequently throughout guile yet.
Conclusion:
-----------
To be able to use a union datatype for SCM values requires to be quite
more specific about what types of arguments the different guile macros
will expect. I think this is beneficial, since the result will be a much
more clearer separation of concepts in guiles API. (Remember: Defining
SCM as a union is for finding typing problems during development only!)
Since I already put a lot of effort into the whole thing, I will present a
couple of suggestions for how the different macro arguments should be
typed. I will write this in a following mail.
Best regards
Dirk Herrmann