[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

extending defstruct



    Date: 16 Apr 86 23:55 EST
    From: Dave.Touretzky@A.CS.CMU.EDU

    I want to modify my suggestion for the syntax of byte fields in defstruct in
    response to David Plummer's note.  First, in order to be compatible with
    existing CLtL syntax (as opposed to Zetalisp), the first element of the slot
    description should be a *list* of byte field descriptions; thus we follow
    the convention that the car of a slot descriptor names the slot(s), and the
    cdr contains default values and options.  Second, there is no need for a
    :byte-field keyword, since the shape of every byte field *must* be specified.

Even so, I think the :byte-field keyword should be there for
consistency.  There's another reason: consider the possibility of
boolean fields (NIL/T instead of 0/1).  This could look like
:boolean-field instead of :byte-field.  There is no reason why bytes and
booleans can't be mixed.  Also, there is no hard reason why a boolean
field need be 1 bit wide.  (This assumes any 1 is truth, and that
setting to truth sets all bits.)  Also, the shape of every byte field
does NOT need to be specified.  Consider
    (defstruct thingie
      (foo 'default-foo-value)
      ((whole-second-slot 0 :type fixnum)
       (low-bar nil (byte 8 0))
       (mid-bar #x00 (byte 8 8) :read-only t)
       (high-bar #x1a (byte 8 16)))
      (baz 'default-baz-value))
This is a natural place to declare the whole-second-slot to be of type
fixnum.

    So I propose the following:

	    (defstruct thingie
	      (foo 'default-foo-value)
	      ((low-bar nil (byte 8 0))
	       (mid-bar #x00 (byte 8 8) :read-only t)
	       (high-bar #x1a (byte 8 16)))
	      (baz 'default-baz-value))

    Some notes:  (1) A slot that is divided up into byte fields should be
    restricted to type fixnum unless the user explicitly specifies that it
    should be a bignum (or something else) via the :type keyword.  So byte
    specifiers that exceed the dimensions of a fixnum (or whatever type is
    specified) should generate an error.  
I disagree with this because it can lead to non-portable code, that is,
it depends on the size of fixnums.  I think the default should be
integer and the user must explicitly state fixnum.  As stated above, the
:TYPE keyword could be awkward in the individual bytes and is better
placed in the whole slot descriptor.
    (2) the list of byte field descriptors
    may also contain as its first element a symbol, in which case the symbol is
    taken to be the name of the entire slot.
I'm confused.  Maybe that's why you had an extra (, for a total of
three, before low-bar?  I think there is too much symmetry being broken.
    (3) Per Plummer's suggestion, a
    default value of NIL for a byte field means ``no default.''  (4) If the user
    specifies incompatible defaults for overlapping byte fields, an error
    should be generated.  (5) If overlapping byte fields are both filled by a
    constructor, or if one is filled by a default and the other by a
    constructor, the results of the operation are undefined.

    Here's another example:

	    (defstruct gadget
	      (common-name nil)
	      ((feature-bits
		(input-size nil (byte 3 0))
		(output-size nil (byte 3 3) :read-only t)
		(clock-pins nil (byte 2 6))
		(internal-store nil (byte 10 8)))
	       #x12345 :type fixnum)
	      (gadget-cost :type short-float))
[Gadget-cost default??]


    The slot GADGET-FEATURE-BITS is of type fixnum and is divided into four
    byte fields.  Note that in this example we gave the entire slot a default
    value rather than giving the byte fields separate defaults.

For comparison, this is how it would look in my proposed scheme, with
some more things that use the boolean-field feature.

	    (defstruct gadget
	      (common-name nil)
	      ((feature-bits #x12345 :type fixnum)
	       (input-size nil :byte-field (byte 3 0))
	       (output-size nil :byte-field (byte 3 3) :read-only t)
	       (clock-pins nil :byte-field (byte 2 6))
	       (internal-store nil :byte-field (byte 10 8))
	       (something-on-p nil :boolean-field (byte 3 18))
	       (foo-on nil :boolean-field (byte 1 18))
	       (bar-on nil :boolean-field (byte 1 19))
	       (baz-on nil :boolean-field (byte 1 20)))
	      (gadget-cost 0.0 :type short-float))