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]

Macros, SCM and strict typing.


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


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