As a structure, a vtable also has a vtable, which is also a structure. Structures, their vtables, the vtables of the vtables, and so on form a tree of structures. Making a new structure adds a leaf to the tree, and if that structure is a vtable, it may be used to create other leaves.
If you traverse up the tree of vtables, via calling
struct-vtable
, eventually you reach a root which is the vtable of
itself:
scheme@(guile-user)> (current-module) $1 = #<directory (guile-user) 221b090> scheme@(guile-user)> (struct-vtable $1) $2 = #<record-type module> scheme@(guile-user)> (struct-vtable $2) $3 = #<<standard-vtable> 12c30a0> scheme@(guile-user)> (struct-vtable $3) $4 = #<<standard-vtable> 12c3fa0> scheme@(guile-user)> (struct-vtable $4) $5 = #<<standard-vtable> 12c3fa0> scheme@(guile-user)> <standard-vtable> $6 = #<<standard-vtable> 12c3fa0>
In this example, we can say that $1
is an instance of $2
,
$2
is an instance of $3
, $3
is an instance of
$4
, and $4
, strangely enough, is an instance of itself.
The value bound to $4
in this console session also bound to
<standard-vtable>
in the default environment.
A meta-vtable, useful for making new vtables.
All of these values are structures. All but $1
are vtables. As
$2
is an instance of $3
, and $3
is a vtable, we can
say that $3
is a meta-vtable: a vtable that can create
vtables.
With this definition, we can specify more precisely what a vtable is: a vtable is a structure made from a meta-vtable. Making a structure from a meta-vtable runs some special checks to ensure that the first field of the structure is a valid layout. Additionally, if these checks see that the layout of the child vtable contains all the required fields of a vtable, in the correct order, then the child vtable will also be a meta-table, inheriting a magical bit from the parent.
Return #t
if obj is a vtable structure: an instance of a
meta-vtable.
<standard-vtable>
is a root of the vtable tree. (Normally there
is only one root in a given Guile process, but due to some legacy
interfaces there may be more than one.)
The set of required fields of a vtable is the set of fields in the
<standard-vtable>
, and is bound to standard-vtable-fields
in the default environment. It is possible to create a meta-vtable that
with additional fields in its layout, which can be used to create
vtables with additional data:
scheme@(guile-user)> (struct-ref $3 vtable-index-layout) $6 = pwuhuhpwphuhuhpwpwpw scheme@(guile-user)> (struct-ref $4 vtable-index-layout) $7 = pwuhuhpwphuhuh scheme@(guile-user)> standard-vtable-fields $8 = "pwuhuhpwphuhuh" scheme@(guile-user)> (struct-ref $2 vtable-offset-user) $9 = module
In this continuation of our earlier example, $2
is a vtable that
has extra fields, because its vtable, $3
, was made from a
meta-vtable with an extended layout. vtable-offset-user
is a
convenient definition that indicates the number of fields in
standard-vtable-fields
.
A string containing the ordered set of fields that a vtable must have.
The first index in a vtable that is available for a user.
Return a structure layout symbol, from a fields string.
fields is as described under make-vtable
(see Vtables). An invalid fields string is an error.
With these definitions, one can define make-vtable
in this way:
(define* (make-vtable fields #:optional printer) (make-struct/no-tail <standard-vtable> (make-struct-layout fields) printer))