6.6.18.4 Meta-Vtables

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.

Scheme Variable: <standard-vtable>

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.

Scheme Procedure: struct-vtable? obj
C Function: scm_struct_vtable_p (obj)

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.

Scheme Variable: standard-vtable-fields

A string containing the ordered set of fields that a vtable must have.

Scheme Variable: vtable-offset-user

The first index in a vtable that is available for a user.

Scheme Procedure: make-struct-layout fields
C Function: scm_make_struct_layout (fields)

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))