This is guile.info, produced by makeinfo version 6.8 from guile.texi.

This manual documents Guile version 3.0.11.

   Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software
Foundation, Inc.
Copyright (C) 2021 Maxime Devos
Copyright (C) 2024 Tomas Volf

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
copy of the license is included in the section entitled “GNU Free
Documentation License.”

   Additionally, the documentation of the SRFI 64 module is adapted from
its specification text, which is made available under the following
Expat license:

     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation
     files (the "Software"), to deal in the Software without
     restriction, including without limitation the rights to use, copy,
     modify, merge, publish, distribute, sublicense, and/or sell copies
     of the Software, and to permit persons to whom the Software is
     furnished to do so, subject to the following conditions:

     The above copyright notice and this permission notice shall be
     included in all copies or substantial portions of the Software.

     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     SOFTWARE.

   Additionally, the documentation of the SRFI 197 module is adapted
from its specification text, which is made available under the following
MIT license:

     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation
     files (the "Software"), to deal in the Software without
     restriction, including without limitation the rights to use, copy,
     modify, merge, publish, distribute, sublicense, and/or sell copies
     of the Software, and to permit persons to whom the Software is
     furnished to do so, subject to the following conditions:

     The above copyright notice and this permission notice shall be
     included in all copies or substantial portions of the Software.

     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     SOFTWARE.

INFO-DIR-SECTION The Algorithmic Language Scheme
START-INFO-DIR-ENTRY
* Guile Reference: (guile).     The Guile reference manual.
END-INFO-DIR-ENTRY


File: guile.info,  Node: File Tree Walk,  Next: Queues,  Prev: Formatted Output,  Up: Guile Modules

7.12 File Tree Walk
===================

The functions in this section traverse a tree of files and directories.
They come in two flavors: the first one is a high-level functional
interface, and the second one is similar to the C ‘ftw’ and ‘nftw’
routines (*note (libc)Working with Directory Trees::).

     (use-modules (ice-9 ftw))

 -- Scheme Procedure: file-system-tree file-name [enter? [stat]]
     Return a tree of the form ‘(FILE-NAME STAT CHILDREN ...)’ where
     STAT is the result of ‘(STAT FILE-NAME)’ and CHILDREN are similar
     structures for each file contained in FILE-NAME when it designates
     a directory.

     The optional ENTER? predicate is invoked as ‘(ENTER? NAME STAT)’
     and should return true to allow recursion into directory NAME; the
     default value is a procedure that always returns ‘#t’.  When a
     directory does not match ENTER?, it nonetheless appears in the
     resulting tree, only with zero children.

     The STAT argument is optional and defaults to ‘lstat’, as for
     ‘file-system-fold’ (see below.)

     The example below shows how to obtain a hierarchical listing of the
     files under the ‘module/language’ directory in the Guile source
     tree, discarding their ‘stat’ info:

          (use-modules (ice-9 match))

          (define remove-stat
            ;; Remove the `stat' object the `file-system-tree' provides
            ;; for each file in the tree.
            (match-lambda
              ((name stat)              ; flat file
               name)
              ((name stat children ...) ; directory
               (list name (map remove-stat children)))))

          (let ((dir (string-append (assq-ref %guile-build-info 'top_srcdir)
                                    "/module/language")))
            (remove-stat (file-system-tree dir)))

          ⇒
          ("language"
           (("value" ("spec.go" "spec.scm"))
            ("scheme"
             ("spec.go"
              "spec.scm"
              "compile-tree-il.scm"
              "decompile-tree-il.scm"
              "decompile-tree-il.go"
              "compile-tree-il.go"))
            ("tree-il"
             ("spec.go"
              "fix-letrec.go"
              "inline.go"
              "fix-letrec.scm"
              "compile-glil.go"
              "spec.scm"
              "optimize.scm"
              "primitives.scm"
              ...))
            ...))

   It is often desirable to process directories entries directly, rather
than building up a tree of entries in memory, like ‘file-system-tree’
does.  The following procedure, a “combinator”, is designed to allow
directory entries to be processed directly as a directory tree is
traversed; in fact, ‘file-system-tree’ is implemented in terms of it.

 -- Scheme Procedure: file-system-fold enter? leaf down up skip error
          init file-name [stat]
     Traverse the directory at FILE-NAME, recursively, and return the
     result of the successive applications of the LEAF, DOWN, UP, and
     SKIP procedures as described below.

     Enter sub-directories only when ‘(ENTER? PATH STAT RESULT)’ returns
     true.  When a sub-directory is entered, call ‘(DOWN PATH STAT
     RESULT)’, where PATH is the path of the sub-directory and STAT the
     result of ‘(false-if-exception (STAT PATH))’; when it is left, call
     ‘(UP PATH STAT RESULT)’.

     For each file in a directory, call ‘(LEAF PATH STAT RESULT)’.

     When ENTER? returns ‘#f’, or when an unreadable directory is
     encountered, call ‘(SKIP PATH STAT RESULT)’.

     When FILE-NAME names a flat file, ‘(LEAF PATH STAT INIT)’ is
     returned.

     When an ‘opendir’ or STAT call fails, call ‘(ERROR PATH STAT ERRNO
     RESULT)’, with ERRNO being the operating system error number that
     was raised—e.g., ‘EACCES’—and STAT either ‘#f’ or the result of the
     STAT call for that entry, when available.

     The special ‘.’ and ‘..’ entries are not passed to these
     procedures.  The PATH argument to the procedures is a full file
     name—e.g., ‘"../foo/bar/gnu"’; if FILE-NAME is an absolute file
     name, then PATH is also an absolute file name.  Files and
     directories, as identified by their device/inode number pair, are
     traversed only once.

     The optional STAT argument defaults to ‘lstat’, which means that
     symbolic links are not followed; the ‘stat’ procedure can be used
     instead when symbolic links are to be followed (*note stat: File
     System.).

     The example below illustrates the use of ‘file-system-fold’:

          (define (total-file-size file-name)
            "Return the size in bytes of the files under FILE-NAME (similar
          to `du --apparent-size' with GNU Coreutils.)"

            (define (enter? name stat result)
              ;; Skip version control directories.
              (not (member (basename name) '(".git" ".svn" "CVS"))))
            (define (leaf name stat result)
              ;; Return RESULT plus the size of the file at NAME.
              (+ result (stat:size stat)))

            ;; Count zero bytes for directories.
            (define (down name stat result) result)
            (define (up name stat result) result)

            ;; Likewise for skipped directories.
            (define (skip name stat result) result)

            ;; Ignore unreadable files/directories but warn the user.
            (define (error name stat errno result)
              (format (current-error-port) "warning: ~a: ~a~%"
                      name (strerror errno))
              result)

            (file-system-fold enter? leaf down up skip error
                                     0  ; initial counter is zero bytes
                                     file-name))

          (total-file-size ".")
          ⇒ 8217554

          (total-file-size "/dev/null")
          ⇒ 0

   The alternative C-like functions are described below.

 -- Scheme Procedure: scandir name [select? [entry<?]]
     Return the list of the names of files contained in directory NAME
     that match predicate SELECT? (by default, all files).  The returned
     list of file names is sorted according to ENTRY<?, which defaults
     to ‘string-locale<?’ such that file names are sorted in the
     locale’s alphabetical order (*note Text Collation::).  Return ‘#f’
     when NAME is unreadable or is not a directory.

     This procedure is modeled after the C library function of the same
     name (*note (libc)Scanning Directory Content::).

 -- Scheme Procedure: ftw startname proc ['hash-size n]
     Walk the file system tree descending from STARTNAME, calling PROC
     for each file and directory.

     Hard links and symbolic links are followed.  A file or directory is
     reported to PROC only once, and skipped if seen again in another
     place.  One consequence of this is that ‘ftw’ is safe against
     circularly linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag)’ and it should
     return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’
     (*note File System::) on FILENAME.  FLAG is one of the following
     symbols,

     ‘regular’
          FILENAME is a file, this includes special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘invalid-stat’
          An error occurred when calling ‘stat’, so nothing is known.
          STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won’t be recursed into.

     ‘symlink’
          FILENAME is a dangling symbolic link.  Symbolic links are
          normally followed and their target reported, the link itself
          is reported if the target does not exist.

     The return value from ‘ftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     Optional argument symbol ‘hash-size’ and an integer can be given to
     set the size of the hash table used to track items already visited.
     (*note Hash Table Reference::)

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.

 -- Scheme Procedure: nftw startname proc ['chdir] ['depth] ['hash-size
          n] ['mount] ['physical]
     Walk the file system tree starting at STARTNAME, calling PROC for
     each file and directory.  ‘nftw’ has extra features over the basic
     ‘ftw’ described above.

     Like ‘ftw’, hard links and symbolic links are followed.  A file or
     directory is reported to PROC only once, and skipped if seen again
     in another place.  One consequence of this is that ‘nftw’ is safe
     against circular linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag base level)’ and it
     should return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’ on
     FILENAME (*note File System::).  BASE is an integer offset into
     FILENAME which is where the basename for this item begins.  LEVEL
     is an integer giving the directory nesting level, starting from 0
     for the contents of STARTNAME (or that item itself if it’s a file).
     FLAG is one of the following symbols,

     ‘regular’
          FILENAME is a file, including special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘directory-processed’
          FILENAME is a directory, and its contents have all been
          visited.  This flag is given instead of ‘directory’ when the
          ‘depth’ option below is used.

     ‘invalid-stat’
          An error occurred when applying ‘stat’ to FILENAME, so nothing
          is known about it.  STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won’t be recursed into.

     ‘stale-symlink’
          FILENAME is a dangling symbolic link.  Links are normally
          followed and their target reported, the link itself is
          reported if its target does not exist.

     ‘symlink’
          When the ‘physical’ option described below is used, this
          indicates FILENAME is a symbolic link whose target exists (and
          is not being followed).

     The following optional arguments can be given to modify the way
     ‘nftw’ works.  Each is passed as a symbol (and ‘hash-size’ takes a
     following integer value).

     ‘chdir’
          Change to the directory containing the item before calling
          PROC.  When ‘nftw’ returns the original current directory is
          restored.

          Under this option, generally the BASE parameter to each PROC
          call should be used to pick out the base part of the FILENAME.
          The FILENAME is still a path but with a changed directory it
          won’t be valid (unless the STARTNAME directory was absolute).

     ‘depth’
          Visit files “depth first”, meaning PROC is called for the
          contents of each directory before it’s called for the
          directory itself.  Normally a directory is reported first,
          then its contents.

          Under this option, the FLAG to PROC for a directory is
          ‘directory-processed’ instead of ‘directory’.

     ‘hash-size N’
          Set the size of the hash table used to track items already
          visited.  (*note Hash Table Reference::)

     ‘mount’
          Don’t cross a mount point, meaning only visit items on the
          same file system as STARTNAME (ie. the same ‘stat:dev’).

     ‘physical’
          Don’t follow symbolic links, instead report them to PROC as
          ‘symlink’.  Dangling links (those whose target doesn’t exist)
          are still reported as ‘stale-symlink’.

     The return value from ‘nftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.


File: guile.info,  Node: Queues,  Next: Streams,  Prev: File Tree Walk,  Up: Guile Modules

7.13 Queues
===========

The functions in this section are provided by

     (use-modules (ice-9 q))

   This module implements queues holding arbitrary scheme objects and
designed for efficient first-in / first-out operations.

   ‘make-q’ creates a queue, and objects are entered and removed with
‘enq!’ and ‘deq!’.  ‘q-push!’ and ‘q-pop!’ can be used too, treating the
front of the queue like a stack.


 -- Scheme Procedure: make-q
     Return a new queue.

 -- Scheme Procedure: q? obj
     Return ‘#t’ if OBJ is a queue, or ‘#f’ if not.

     Note that queues are not a distinct class of objects but are
     implemented with cons cells.  For that reason certain list
     structures can get ‘#t’ from ‘q?’.

 -- Scheme Procedure: enq! q obj
     Add OBJ to the rear of Q, and return Q.

 -- Scheme Procedure: deq! q
 -- Scheme Procedure: q-pop! q
     Remove and return the front element from Q.  If Q is empty, a
     ‘q-empty’ exception is thrown.

     ‘deq!’ and ‘q-pop!’ are the same operation, the two names just let
     an application match ‘enq!’ with ‘deq!’, or ‘q-push!’ with
     ‘q-pop!’.

 -- Scheme Procedure: q-push! q obj
     Add OBJ to the front of Q, and return Q.

 -- Scheme Procedure: q-length q
     Return the number of elements in Q.

 -- Scheme Procedure: q-empty? q
     Return true if Q is empty.

 -- Scheme Procedure: q-empty-check q
     Throw a ‘q-empty’ exception if Q is empty.

 -- Scheme Procedure: q-front q
     Return the first element of Q (without removing it).  If Q is
     empty, a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-rear q
     Return the last element of Q (without removing it).  If Q is empty,
     a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-remove! q obj
     Remove all occurrences of OBJ from Q, and return Q.  OBJ is
     compared to queue elements using ‘eq?’.


   The ‘q-empty’ exceptions described above are thrown just as ‘(throw
'q-empty)’, there’s no message etc like an error throw.

   A queue is implemented as a cons cell, the ‘car’ containing a list of
queued elements, and the ‘cdr’ being the last cell in that list (for
ease of enqueuing).

     (LIST . LAST-CELL)

If the queue is empty, LIST is the empty list and LAST-CELL is ‘#f’.

   An application can directly access the queue list if desired, for
instance to search the elements or to insert at a specific point.

 -- Scheme Procedure: sync-q! q
     Recompute the LAST-CELL field in Q.

     All the operations above maintain LAST-CELL as described, so
     normally there’s no need for ‘sync-q!’.  But if an application
     modifies the queue LIST then it must either maintain LAST-CELL
     similarly, or call ‘sync-q!’ to recompute it.


File: guile.info,  Node: Streams,  Next: Buffered Input,  Prev: Queues,  Up: Guile Modules

7.14 Streams
============

This section documents Guile’s legacy stream module.  For a more
complete and portable stream library, *note SRFI-41::.

   A stream represents a sequence of values, each of which is calculated
only when required.  This allows large or even infinite sequences to be
represented and manipulated with familiar operations like “car”, “cdr”,
“map” or “fold”.  In such manipulations only as much as needed is
actually held in memory at any one time.  The functions in this section
are available from

     (use-modules (ice-9 streams))

   Streams are implemented using promises (*note Delayed Evaluation::),
which is how the underlying calculation of values is made only when
needed, and the values then retained so the calculation is not repeated.

Here is a simple example producing a stream of all odd numbers,

     (define odds (make-stream (lambda (state)
                                 (cons state (+ state 2)))
                               1))
     (stream-car odds)              ⇒ 1
     (stream-car (stream-cdr odds)) ⇒ 3

‘stream-map’ could be used to derive a stream of odd squares,

     (define (square n) (* n n))
     (define oddsquares (stream-map square odds))

   These are infinite sequences, so it’s not possible to convert them to
a list, but they could be printed (infinitely) with for example

     (stream-for-each (lambda (n sq)
                        (format #t "~a squared is ~a\n" n sq))
                      odds oddsquares)
     ⊣
     1 squared is 1
     3 squared is 9
     5 squared is 25
     7 squared is 49
     ...


 -- Scheme Procedure: make-stream proc initial-state
     Return a new stream, formed by calling PROC successively.

     Each call is ‘(PROC STATE)’, it should return a pair, the ‘car’
     being the value for the stream, and the ‘cdr’ being the new STATE
     for the next call.  For the first call STATE is the given
     INITIAL-STATE.  At the end of the stream, PROC should return some
     non-pair object.

 -- Scheme Procedure: stream-car stream
     Return the first element from STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-cdr stream
     Return a stream which is the second and subsequent elements of
     STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-null? stream
     Return true if STREAM is empty.

 -- Scheme Procedure: list->stream list
 -- Scheme Procedure: vector->stream vector
     Return a stream with the contents of LIST or VECTOR.

     LIST or VECTOR should not be modified subsequently, since it’s
     unspecified whether changes there will be reflected in the stream
     returned.

 -- Scheme Procedure: port->stream port readproc
     Return a stream which is the values obtained by reading from PORT
     using READPROC.  Each read call is ‘(READPROC PORT)’, and it should
     return an EOF object (*note Binary I/O::) at the end of input.

     For example a stream of characters from a file,

          (port->stream (open-input-file "/foo/bar.txt") read-char)

 -- Scheme Procedure: stream->list stream
     Return a list which is the entire contents of STREAM.

 -- Scheme Procedure: stream->reversed-list stream
     Return a list which is the entire contents of STREAM, but in
     reverse order.

 -- Scheme Procedure: stream->list&length stream
     Return two values (*note Multiple Values::), being firstly a list
     which is the entire contents of STREAM, and secondly the number of
     elements in that list.

 -- Scheme Procedure: stream->reversed-list&length stream
     Return two values (*note Multiple Values::) being firstly a list
     which is the entire contents of STREAM, but in reverse order, and
     secondly the number of elements in that list.

 -- Scheme Procedure: stream->vector stream
     Return a vector which is the entire contents of STREAM.

 -- Function: stream-fold proc init stream1 stream2 ...
     Apply PROC successively over the elements of the given streams,
     from first to last until the end of the shortest stream is reached.
     Return the result from the last PROC call.

     Each call is ‘(PROC elem1 elem2 ... prev)’, where each ELEM is from
     the corresponding STREAM.  PREV is the return from the previous
     PROC call, or the given INIT for the first call.

 -- Function: stream-for-each proc stream1 stream2 ...
     Call PROC on the elements from the given STREAMs.  The return value
     is unspecified.

     Each call is ‘(PROC elem1 elem2 ...)’, where each ELEM is from the
     corresponding STREAM.  ‘stream-for-each’ stops when it reaches the
     end of the shortest STREAM.

 -- Function: stream-map proc stream1 stream2 ...
     Return a new stream which is the results of applying PROC to the
     elements of the given STREAMs.

     Each call is ‘(PROC elem1 elem2 ...)’, where each ELEM is from the
     corresponding STREAM.  The new stream ends when the end of the
     shortest given STREAM is reached.


File: guile.info,  Node: Buffered Input,  Next: Expect,  Prev: Streams,  Up: Guile Modules

7.15 Buffered Input
===================

The following functions are provided by

     (use-modules (ice-9 buffered-input))

   A buffered input port allows a reader function to return chunks of
characters which are to be handed out on reading the port.  A notion of
further input for an application level logical expression is maintained
too, and passed through to the reader.

 -- Scheme Procedure: make-buffered-input-port reader
     Create an input port which returns characters obtained from the
     given READER function.  READER is called (READER cont), and should
     return a string or an EOF object.

     The new port gives precisely the characters returned by READER,
     nothing is added, so if any newline characters or other separators
     are desired they must come from the reader function.

     The CONT parameter to READER is ‘#f’ for initial input, or ‘#t’
     when continuing an expression.  This is an application level
     notion, set with ‘set-buffered-input-continuation?!’ below.  If the
     user has entered a partial expression then it allows READER for
     instance to give a different prompt to show more is required.

 -- Scheme Procedure: make-line-buffered-input-port reader
     Create an input port which returns characters obtained from the
     specified READER function, similar to ‘make-buffered-input-port’
     above, but where READER is expected to be a line-oriented.

     READER is called (READER cont), and should return a string or an
     EOF object as above.  Each string is a line of input without a
     newline character, the port code inserts a newline after each
     string.

 -- Scheme Procedure: set-buffered-input-continuation?! port cont
     Set the input continuation flag for a given buffered input PORT.

     An application uses this by calling with a CONT flag of ‘#f’ when
     beginning to read a new logical expression.  For example with the
     Scheme ‘read’ function (*note Scheme Read::),

          (define my-port (make-buffered-input-port my-reader))

          (set-buffered-input-continuation?! my-port #f)
          (let ((obj (read my-port)))
            ...


File: guile.info,  Node: Expect,  Next: sxml-match,  Prev: Buffered Input,  Up: Guile Modules

7.16 Expect
===========

The macros in this section are made available with:

     (use-modules (ice-9 expect))

   ‘expect’ is a macro for selecting actions based on the output from a
port.  The name comes from a tool of similar functionality by Don Libes.
Actions can be taken when a particular string is matched, when a timeout
occurs, or when end-of-file is seen on the port.  The ‘expect’ macro is
described below; ‘expect-strings’ is a front-end to ‘expect’ based on
regexec (see the regular expression documentation).

 -- Macro: expect-strings clause ...
     By default, ‘expect-strings’ will read from the current input port.
     The first term in each clause consists of an expression evaluating
     to a string pattern (regular expression).  As characters are read
     one-by-one from the port, they are accumulated in a buffer string
     which is matched against each of the patterns.  When a pattern
     matches, the remaining expression(s) in the clause are evaluated
     and the value of the last is returned.  For example:

          (with-input-from-file "/etc/passwd"
            (lambda ()
              (expect-strings
                ("^nobody" (display "Got a nobody user.\n")
                           (display "That's no problem.\n"))
                ("^daemon" (display "Got a daemon user.\n")))))

     The regular expression is compiled with the ‘REG_NEWLINE’ flag, so
     that the ^ and $ anchors will match at any newline, not just at the
     start and end of the string.

     There are two other ways to write a clause:

     The expression(s) to evaluate can be omitted, in which case the
     result of the regular expression match (converted to strings, as
     obtained from regexec with match-pick set to "") will be returned
     if the pattern matches.

     The symbol ‘=>’ can be used to indicate that the expression is a
     procedure which will accept the result of a successful regular
     expression match.  E.g.,

          ("^daemon" => write)
          ("^d(aemon)" => (lambda args (for-each write args)))
          ("^da(em)on" => (lambda (all sub)
                            (write all) (newline)
                            (write sub) (newline)))

     The order of the substrings corresponds to the order in which the
     opening brackets occur.

     A number of variables can be used to control the behavior of
     ‘expect’ (and ‘expect-strings’).  Most have default top-level
     bindings to the value ‘#f’, which produces the default behavior.
     They can be redefined at the top level or locally bound in a form
     enclosing the expect expression.

     ‘expect-port’
          A port to read characters from, instead of the current input
          port.
     ‘expect-timeout’
          ‘expect’ will terminate after this number of seconds,
          returning ‘#f’ or the value returned by expect-timeout-proc.
     ‘expect-timeout-proc’
          A procedure called if timeout occurs.  The procedure takes a
          single argument: the accumulated string.
     ‘expect-eof-proc’
          A procedure called if end-of-file is detected on the input
          port.  The procedure takes a single argument: the accumulated
          string.
     ‘expect-char-proc’
          A procedure to be called every time a character is read from
          the port.  The procedure takes a single argument: the
          character which was read.
     ‘expect-strings-compile-flags’
          Flags to be used when compiling a regular expression, which
          are passed to ‘make-regexp’ *Note Regexp Functions::.  The
          default value is ‘regexp/newline’.
     ‘expect-strings-exec-flags’
          Flags to be used when executing a regular expression, which
          are passed to regexp-exec *Note Regexp Functions::.  The
          default value is ‘regexp/noteol’, which prevents ‘$’ from
          matching the end of the string while it is still accumulating,
          but still allows it to match after a line break or at the end
          of file.

     Here’s an example using all of the variables:

          (let ((expect-port (open-input-file "/etc/passwd"))
                (expect-timeout 1)
                (expect-timeout-proc
                  (lambda (s) (display "Times up!\n")))
                (expect-eof-proc
                  (lambda (s) (display "Reached the end of the file!\n")))
                (expect-char-proc display)
                (expect-strings-compile-flags (logior regexp/newline regexp/icase))
                (expect-strings-exec-flags 0))
             (expect-strings
               ("^nobody"  (display "Got a nobody user\n"))))

 -- Macro: expect clause ...
     ‘expect’ is used in the same way as ‘expect-strings’, but tests are
     specified not as patterns, but as procedures.  The procedures are
     called in turn after each character is read from the port, with two
     arguments: the value of the accumulated string and a flag to
     indicate whether end-of-file has been reached.  The flag will
     usually be ‘#f’, but if end-of-file is reached, the procedures are
     called an additional time with the final accumulated string and
     ‘#t’.

     The test is successful if the procedure returns a non-false value.

     If the ‘=>’ syntax is used, then if the test succeeds it must
     return a list containing the arguments to be provided to the
     corresponding expression.

     In the following example, a string will only be matched at the
     beginning of the file:

          (let ((expect-port (open-input-file "/etc/passwd")))
            (expect
               ((lambda (s eof?) (string=? s "fnord!"))
                  (display "Got a nobody user!\n"))))

     The control variables described for ‘expect-strings’ also influence
     the behavior of ‘expect’, with the exception of variables whose
     names begin with ‘expect-strings-’.


File: guile.info,  Node: sxml-match,  Next: The Scheme shell (scsh),  Prev: Expect,  Up: Guile Modules

7.17 ‘sxml-match’: Pattern Matching of SXML
===========================================

The ‘(sxml match)’ module provides syntactic forms for pattern matching
of SXML trees, in a “by example” style reminiscent of the pattern
matching of the ‘syntax-rules’ and ‘syntax-case’ macro systems.  *Note
SXML::, for more information on SXML.

   The following example(1) provides a brief illustration, transforming
a music album catalog language into HTML.

     (define (album->html x)
       (sxml-match x
         ((album (@ (title ,t)) (catalog (num ,n) (fmt ,f)) ...)
          `(ul (li ,t)
               (li (b ,n) (i ,f)) ...))))

   Three macros are provided: ‘sxml-match’, ‘sxml-match-let’, and
‘sxml-match-let*’.

   Compared to a standard s-expression pattern matcher (*note Pattern
Matching::), ‘sxml-match’ provides the following benefits:

   • matching of SXML elements does not depend on any degree of
     normalization of the SXML;
   • matching of SXML attributes (within an element) is under-ordered;
     the order of the attributes specified within the pattern need not
     match the ordering with the element being matched;
   • all attributes specified in the pattern must be present in the
     element being matched; in the spirit that XML is ’extensible’, the
     element being matched may include additional attributes not
     specified in the pattern.

   The present module is a descendant of WebIt!, and was inspired by an
s-expression pattern matcher developed by Erik Hilsdale, Dan Friedman,
and Kent Dybvig at Indiana University.

Syntax
------

‘sxml-match’ provides ‘case’-like form for pattern matching of XML
nodes.

 -- Scheme Syntax: sxml-match input-expression clause1 clause2 ...
     Match INPUT-EXPRESSION, an SXML tree, according to the given
     CLAUSEs (one or more), each consisting of a pattern and one or more
     expressions to be evaluated if the pattern match succeeds.
     Optionally, each CLAUSE within ‘sxml-match’ may include a “guard
     expression”.

   The pattern notation is based on that of Scheme’s ‘syntax-rules’ and
‘syntax-case’ macro systems.  The grammar for the ‘sxml-match’ syntax is
given below:

match-form ::= (sxml-match input-expression
                 clause+)

clause ::= [node-pattern action-expression+]
         | [node-pattern (guard expression*) action-expression+]

node-pattern ::= literal-pattern
               | pat-var-or-cata
               | element-pattern
               | list-pattern

literal-pattern ::= string
                  | character
                  | number
                  | #t
                  | #f

attr-list-pattern ::= (@ attribute-pattern*)
                    | (@ attribute-pattern* . pat-var-or-cata)

attribute-pattern ::= (tag-symbol attr-val-pattern)

attr-val-pattern ::= literal-pattern
                   | pat-var-or-cata
                   | (pat-var-or-cata default-value-expr)

element-pattern ::= (tag-symbol attr-list-pattern?)
                  | (tag-symbol attr-list-pattern? nodeset-pattern)
                  | (tag-symbol attr-list-pattern?
                                nodeset-pattern? . pat-var-or-cata)

list-pattern ::= (list nodeset-pattern)
               | (list nodeset-pattern? . pat-var-or-cata)
               | (list)

nodeset-pattern ::= node-pattern
                  | node-pattern ...
                  | node-pattern nodeset-pattern
                  | node-pattern ... nodeset-pattern

pat-var-or-cata ::= (unquote var-symbol)
                  | (unquote [var-symbol*])
                  | (unquote [cata-expression -> var-symbol*])

   Within a list or element body pattern, ellipses may appear only once,
but may be followed by zero or more node patterns.

   Guard expressions cannot refer to the return values of catamorphisms.

   Ellipses in the output expressions must appear only in an expression
context; ellipses are not allowed in a syntactic form.

   The sections below illustrate specific aspects of the ‘sxml-match’
pattern matcher.

Matching XML Elements
---------------------

The example below illustrates the pattern matching of an XML element:

     (sxml-match '(e (@ (i 1)) 3 4 5)
       ((e (@ (i ,d)) ,a ,b ,c) (list d a b c))
       (,otherwise #f))

   Each clause in ‘sxml-match’ contains two parts: a pattern and one or
more expressions which are evaluated if the pattern is successfully
match.  The example above matches an element ‘e’ with an attribute ‘i’
and three children.

   Pattern variables must be “unquoted” in the pattern.  The above
expression binds D to ‘1’, A to ‘3’, B to ‘4’, and C to ‘5’.

Ellipses in Patterns
--------------------

As in ‘syntax-rules’, ellipses may be used to specify a repeated
pattern.  Note that the pattern ‘item ...’ specifies zero-or-more
matches of the pattern ‘item’.

   The use of ellipses in a pattern is illustrated in the code fragment
below, where nested ellipses are used to match the children of repeated
instances of an ‘a’ element, within an element ‘d’.

     (define x '(d (a 1 2 3) (a 4 5) (a 6 7 8) (a 9 10)))

     (sxml-match x
       ((d (a ,b ...) ...)
        (list (list b ...) ...)))

   The above expression returns a value of ‘((1 2 3) (4 5) (6 7 8) (9
10))’.

Ellipses in Quasiquote’d Output
-------------------------------

Within the body of an ‘sxml-match’ form, a slightly extended version of
quasiquote is provided, which allows the use of ellipses.  This is
illustrated in the example below.

     (sxml-match '(e 3 4 5 6 7)
       ((e ,i ... 6 7) `("start" ,(list 'wrap i) ... "end"))
       (,otherwise #f))

   The general pattern is that ‘`(something ,i ...)’ is rewritten as
‘`(something ,@i)’.

Matching Nodesets
-----------------

A nodeset pattern is designated by a list in the pattern, beginning the
identifier list.  The example below illustrates matching a nodeset.

     (sxml-match '("i" "j" "k" "l" "m")
       ((list ,a ,b ,c ,d ,e)
        `((p ,a) (p ,b) (p ,c) (p ,d) (p ,e))))

   This example wraps each nodeset item in an HTML paragraph element.
This example can be rewritten and simplified through using ellipsis:

     (sxml-match '("i" "j" "k" "l" "m")
       ((list ,i ...)
        `((p ,i) ...)))

   This version will match nodesets of any length, and wrap each item in
the nodeset in an HTML paragraph element.

Matching the “Rest” of a Nodeset
--------------------------------

Matching the “rest” of a nodeset is achieved by using a ‘. rest)’
pattern at the end of an element or nodeset pattern.

   This is illustrated in the example below:

     (sxml-match '(e 3 (f 4 5 6) 7)
       ((e ,a (f . ,y) ,d)
        (list a y d)))

   The above expression returns ‘(3 (4 5 6) 7)’.

Matching the Unmatched Attributes
---------------------------------

Sometimes it is useful to bind a list of attributes present in the
element being matched, but which do not appear in the pattern.  This is
achieved by using a ‘. rest)’ pattern at the end of the attribute list
pattern.  This is illustrated in the example below:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)) 4 5 6)
       ((a (@ (y ,www) . ,qqq) ,t ,u ,v)
        (list www qqq t u v)))

   The above expression matches the attribute ‘y’ and binds a list of
the remaining attributes to the variable QQQ.  The result of the above
expression is ‘(2 ((z 1) (x 3)) 4 5 6)’.

   This type of pattern also allows the binding of all attributes:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)))
       ((a (@ . ,qqq))
        qqq))

Default Values in Attribute Patterns
------------------------------------

It is possible to specify a default value for an attribute which is used
if the attribute is not present in the element being matched.  This is
illustrated in the following example:

     (sxml-match '(e 3 4 5)
       ((e (@ (z (,d 1))) ,a ,b ,c) (list d a b c)))

   The value ‘1’ is used when the attribute ‘z’ is absent from the
element ‘e’.

Guards in Patterns
------------------

Guards may be added to a pattern clause via the ‘guard’ keyword.  A
guard expression may include zero or more expressions which are
evaluated only if the pattern is matched.  The body of the clause is
only evaluated if the guard expressions evaluate to ‘#t’.

   The use of guard expressions is illustrated below:

     (sxml-match '(a 2 3)
       ((a ,n) (guard (number? n)) n)
       ((a ,m ,n) (guard (number? m) (number? n)) (+ m n)))

Catamorphisms
-------------

The example below illustrates the use of explicit recursion within an
‘sxml-match’ form.  This example implements a simple calculator for the
basic arithmetic operations, which are represented by the XML elements
‘plus’, ‘minus’, ‘times’, and ‘div’.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           (,i (guard (integer? i)) i)
           ((plus ,x ,y) (+ (simple-eval x) (simple-eval y)))
           ((times ,x ,y) (* (simple-eval x) (simple-eval y)))
           ((minus ,x ,y) (- (simple-eval x) (simple-eval y)))
           ((div ,x ,y) (/ (simple-eval x) (simple-eval y)))
           (,otherwise (error "simple-eval: invalid expression" x)))))

   Using the catamorphism feature of ‘sxml-match’, a more concise
version of ‘simple-eval’ can be written.  The pattern ‘,(x)’ recursively
invokes the pattern matcher on the value bound in this position.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           (,i (guard (integer? i)) i)
           ((plus ,(x) ,(y)) (+ x y))
           ((times ,(x) ,(y)) (* x y))
           ((minus ,(x) ,(y)) (- x y))
           ((div ,(x) ,(y)) (/ x y))
           (,otherwise (error "simple-eval: invalid expression" x)))))

Named-Catamorphisms
-------------------

It is also possible to explicitly name the operator in the “cata”
position.  Where ‘,(id*)’ recurs to the top of the current ‘sxml-match’,
‘,(cata -> id*)’ recurs to ‘cata’.  ‘cata’ must evaluate to a procedure
which takes one argument, and returns as many values as there are
identifiers following ‘->’.

   Named catamorphism patterns allow processing to be split into
multiple, mutually recursive procedures.  This is illustrated in the
example below: a transformation that formats a “TV Guide” into HTML.

     (define (tv-guide->html g)
       (define (cast-list cl)
         (sxml-match cl
           ((CastList (CastMember (Character (Name ,ch)) (Actor (Name ,a))) ...)
            `(div (ul (li ,ch ": " ,a) ...)))))
       (define (prog p)
         (sxml-match p
           ((Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...))
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...)))
           ((Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...)
                     ,(cast-list -> cl))
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...)
                  ,cl))))
       (sxml-match g
         ((TVGuide (@ (start ,start-date)
                      (end ,end-date))
                   (Channel (Name ,nm) ,(prog -> p) ...) ...)
          `(html (head (title "TV Guide"))
                 (body (h1 "TV Guide")
                       (div (h2 ,nm) ,p ...) ...)))))

‘sxml-match-let’ and ‘sxml-match-let*’
--------------------------------------

 -- Scheme Syntax: sxml-match-let ((pat expr) ...) expression0
          expression ...
 -- Scheme Syntax: sxml-match-let* ((pat expr) ...) expression0
          expression ...
     These forms generalize the ‘let’ and ‘let*’ forms of Scheme to
     allow an XML pattern in the binding position, rather than a simple
     variable.

   For example, the expression below:

     (sxml-match-let (((a ,i ,j) '(a 1 2)))
       (+ i j))

   binds the variables I and J to ‘1’ and ‘2’ in the XML value given.

   ---------- Footnotes ----------

   (1) This example is taken from a paper by Krishnamurthi et al.  Their
paper was the first to show the usefulness of the ‘syntax-rules’ style
of pattern matching for transformation of XML, though the language
described, XT3D, is an XML language.


File: guile.info,  Node: The Scheme shell (scsh),  Next: Curried Definitions,  Prev: sxml-match,  Up: Guile Modules

7.18 The Scheme shell (scsh)
============================

An incomplete port of the Scheme shell (scsh) was once available for
Guile as a separate package.  However this code has bitrotten somewhat.
The pieces are available in Guile’s legacy CVS repository, which may be
browsed at
<http://cvs.savannah.gnu.org/viewvc/guile/guile-scsh/?root=guile>.

   For information about scsh see <http://www.scsh.net/>.

   This bitrotting is a bit of a shame, as there is a good deal of
well-written Scheme code in scsh.  Adopting this code and porting it to
current Guile should be an educational experience, in addition to
providing something of value to Guile folks.


File: guile.info,  Node: Curried Definitions,  Next: Statprof,  Prev: The Scheme shell (scsh),  Up: Guile Modules

7.19 Curried Definitions
========================

The macros in this section are provided by
     (use-modules (ice-9 curried-definitions))
and replace those provided by default.

   Prior to Guile 2.0, Guile provided a type of definition known
colloquially as a “curried definition”.  The idea is to extend the
syntax of ‘define’ so that you can conveniently define procedures that
return procedures, up to any desired depth.

   For example,
     (define ((foo x) y)
       (list x y))
   is a convenience form of
     (define foo
       (lambda (x)
         (lambda (y)
           (list x y))))

 -- Scheme Syntax: define (... (name args ...) ...) body ...
 -- Scheme Syntax: define* (... (name args ...) ...) body ...
 -- Scheme Syntax: define-public (... (name args ...) ...) body ...

     Create a top level variable NAME bound to the procedure with
     parameter list ARGS.  If NAME is itself a formal parameter list,
     then a higher order procedure is created using that
     formal-parameter list, and returning a procedure that has parameter
     list ARGS.  This nesting may occur to arbitrary depth.

     ‘define*’ is similar but the formal parameter lists take additional
     options as described in *note lambda* and define*::.  For example,
          (define* ((foo #:keys (bar 'baz) (quux 'zot)) frotz #:rest rest)
            (list bar quux frotz rest))

          ((foo #:quux 'foo) 1 2 3 4 5)
          ⇒ (baz foo 1 (2 3 4 5))

     ‘define-public’ is similar to ‘define’ but it also adds NAME to the
     list of exported bindings of the current module.


File: guile.info,  Node: Statprof,  Next: SXML,  Prev: Curried Definitions,  Up: Guile Modules

7.20 Statprof
=============

Statprof is a statistical profiler for Guile.

   A simple use of statprof would look like this:

     (use-modules (statprof))
     (statprof (lambda ()
                 (map 1+ (iota 1000000))
                 #f))

   This would run the thunk with statistical profiling, finally
displaying a flat table of statistics which could look something like
this:

     %     cumulative   self
     time   seconds     seconds  procedure
      57.14  39769.73      0.07  ice-9/boot-9.scm:249:5:map1
      28.57      0.04      0.04  ice-9/boot-9.scm:1165:0:iota
      14.29      0.02      0.02  1+
       0.00      0.12      0.00  <current input>:2:10
     ---
     Sample count: 7
     Total time: 0.123490713 seconds (0.201983993 seconds in GC)

   All of the numerical data with the exception of the calls column is
statistically approximate.  In the following column descriptions, and in
all of statprof, “time” refers to execution time (both user and system),
not wall clock time.

   The ‘% time’ column indicates the percentage of the run-time time
spent inside the procedure itself (not counting children).  It is
calculated as ‘self seconds’, measuring the amount of time spent in the
procedure, divided by the total run-time.

   ‘cumulative seconds’ also counts time spent in children of a
function.  For recursive functions, this can exceed the total time, as
in our example above, because each activation on the stack adds to the
cumulative time.

   Finally, the GC time measures the time spent in the garbage
collector.  On systems with multiple cores, this time can be larger than
the run time, because it counts time spent in all threads, and will run
the “marking” phase of GC in parallel.  If GC time is a significant
fraction of the run time, that means that most time in your program is
spent allocating objects and cleaning up after those allocations.  To
speed up your program, one good place to start would be to look at how
to reduce the allocation rate.

   Statprof’s main mode of operation is as a statistical profiler.
However statprof can also run in a “precise” mode as well.  Pass the
‘#:count-calls? #t’ keyword argument to ‘statprof’ to record all calls:

     (use-modules (statprof))
     (statprof (lambda ()
                 (map 1+ (iota 1000000))
                 #f)
               #:count-calls? #t)

   The result has an additional ‘calls’ column:

     %     cumulative   self
     time   seconds    seconds   calls   procedure
      82.26      0.73      0.73 1000000  1+
      11.29 420925.80      0.10 1000001  ice-9/boot-9.scm:249:5:map1
       4.84      0.06      0.04       1  ice-9/boot-9.scm:1165:0:iota
     [...]
     ---
     Sample count: 62
     Total time: 0.893098065 seconds (1.222796536 seconds in GC)

   As you can see, the profile is perturbed: ‘1+’ ends up on top,
whereas it was not marked as hot in the earlier profile.  This is
because the overhead of call-counting unfairly penalizes calls.  Still,
this precise mode can be useful at times to do algorithmic optimizations
based on the precise call counts.

Implementation notes
====================

The profiler works by setting the unix profiling signal ‘ITIMER_PROF’ to
go off after the interval you define in the call to ‘statprof-reset’.
When the signal fires, a sampling routine runs which crawls up the
stack, recording all instruction pointers into a buffer.  After the
sample is complete, the profiler resets profiling timer to fire again
after the appropriate interval.

   Later, when profiling stops, that log buffer is analyzed to produce
the “self seconds” and “cumulative seconds” statistics.  A procedure at
the top of the stack counts toward “self” samples, and everything on the
stack counts towards “cumulative” samples.

   While the profiler is running it measures how much CPU time (system
and user – which is also what ‘ITIMER_PROF’ tracks) has elapsed while
code has been executing within the profiler.  Only run time counts
towards the profile, not wall-clock time.  For example, sleeping and
waiting for input or output do not cause the timer clock to advance.

Usage
=====

 -- Scheme Procedure: statprof thunk [#:loop loop=1] [#:hz hz=100]
          [#:port port=(current-output-port)] [#:count-calls?
          count-calls?=#f] [#:display-style display-style='flat]
     Profile the execution of THUNK, and return its return values.

     The stack will be sampled HZ times per second, and the thunk itself
     will be called LOOP times.

     If COUNT-CALLS? is true, all procedure calls will be recorded.
     This operation is somewhat expensive.

     After the THUNK has been profiled, print out a profile to PORT.  If
     DISPLAY-STYLE is ‘flat’, the results will be printed as a flat
     profile.  Otherwise if DISPLAY-STYLE is ‘tree’, print the results
     as a tree profile.

     Note that ‘statprof’ requires a working profiling timer.  Some
     platforms do not support profiling timers.  ‘(provided?
     'ITIMER_PROF)’ can be used to check for support of profiling
     timers.

   Profiling can also be enabled and disabled manually.

 -- Scheme Procedure: statprof-active?
     Returns ‘#t’ if ‘statprof-start’ has been called more times than
     ‘statprof-stop’, ‘#f’ otherwise.

 -- Scheme Procedure: statprof-start
 -- Scheme Procedure: statprof-stop
     Start or stop the profiler.

 -- Scheme Procedure: statprof-reset sample-seconds sample-microseconds
          count-calls?
     Reset the profiling sample interval to SAMPLE-SECONDS and
     SAMPLE-MICROSECONDS.  If COUNT-CALLS? is true, arrange to
     instrument procedure calls as well as collecting statistical
     profiling data.

   If you use the manual ‘statprof-start’/‘statprof-stop’ interface, an
implicit statprof state will persist starting from the last call to
‘statprof-reset’, or the first call to ‘statprof-start’.  There are a
number of accessors to fetch statistics from this implicit state.

 -- Scheme Procedure: statprof-accumulated-time
     Returns the time accumulated during the last statprof run.

 -- Scheme Procedure: statprof-sample-count
     Returns the number of samples taken during the last statprof run.

 -- Scheme Procedure: statprof-fold-call-data proc init
     Fold PROC over the call-data accumulated by statprof.  This
     procedure cannot be called while statprof is active.

     PROC will be called with arguments, CALL-DATA and PRIOR-RESULT.

 -- Scheme Procedure: statprof-proc-call-data proc
     Returns the call-data associated with PROC, or ‘#f’ if none is
     available.

 -- Scheme Procedure: statprof-call-data-name cd
 -- Scheme Procedure: statprof-call-data-calls cd
 -- Scheme Procedure: statprof-call-data-cum-samples cd
 -- Scheme Procedure: statprof-call-data-self-samples cd
     Accessors for the fields in a statprof call-data object.

 -- Scheme Procedure: statprof-call-data->stats call-data
     Returns an object of type ‘statprof-stats’.

 -- Scheme Procedure: statprof-stats-proc-name stats
 -- Scheme Procedure: statprof-stats-%-time-in-proc stats
 -- Scheme Procedure: statprof-stats-cum-secs-in-proc stats
 -- Scheme Procedure: statprof-stats-self-secs-in-proc stats
 -- Scheme Procedure: statprof-stats-calls stats
 -- Scheme Procedure: statprof-stats-self-secs-per-call stats
 -- Scheme Procedure: statprof-stats-cum-secs-per-call stats
     Accessors for the fields in a ‘statprof-stats’ object.

 -- Scheme Procedure: statprof-display [port=(current-output-port)]
          [#:style style=flat]
     Displays a summary of the statistics collected.  Possible values
     for STYLE include:

     ‘flat’
          Display a traditional gprof-style flat profile.
     ‘anomalies’
          Find statistical anomalies in the data.
     ‘tree’
          Display a tree profile.

 -- Scheme Procedure: statprof-fetch-stacks
     Returns a list of stacks, as they were captured since the last call
     to ‘statprof-reset’.

 -- Scheme Procedure: statprof-fetch-call-tree [#:precise precise?=#f]
     Return a call tree for the previous statprof run.
     
     The return value is a list of nodes.  A node is a list of the form:
     @code
      node ::= (@var{proc} @var{count} . @var{nodes})
     @end code
     
     The @var{proc} is a printable representation of a procedure, as a
     string.  If @var{precise?} is false, which is the default, then a node
     corresponds to a procedure invocation.  If it is true, then a node
     corresponds to a return point in a procedure.  Passing @code{#:precise?
     #t} allows a user to distinguish different source lines in a procedure,
     but usually it is too much detail, so it is off by default.

 -- Scheme Procedure: gcprof thunk [#:loop]
     Like the ‘statprof’ procedure, but instead of profiling CPU time,
     we profile garbage collection.

     The stack will be sampled soon after every garbage collection
     during the evaluation of THUNK, yielding an approximate idea of
     what is causing allocation in your program.

     Since GC does not occur very frequently, you may need to use the
     LOOP parameter, to cause THUNK to be called LOOP times.


File: guile.info,  Node: SXML,  Next: Texinfo Processing,  Prev: Statprof,  Up: Guile Modules

7.21 SXML
=========

SXML is a native representation of XML in terms of standard Scheme data
types: lists, symbols, and strings.  For example, the simple XML
fragment:

     <parrot type="African Grey"><name>Alfie</name></parrot>

   may be represented with the following SXML:

     (parrot (@ (type "African Grey")) (name "Alfie"))

   SXML is very general, and is capable of representing all of XML.
Formally, this means that SXML is a conforming implementation of the XML
Information Set (http://www.w3.org/TR/xml-infoset/) standard.

   Guile includes several facilities for working with XML and SXML:
parsers, serializers, and transformers.

* Menu:

* SXML Overview::               XML, as it was meant to be
* Reading and Writing XML::     Convenient XML parsing and serializing
* SSAX::                        Custom functional-style XML parsers
* Transforming SXML::           Munging SXML with ‘pre-post-order’
* SXML Tree Fold::              Fold-based SXML transformations
* SXPath::                      XPath for SXML
* sxml ssax input-parse::       The SSAX tokenizer, optimized for Guile
* sxml apply-templates::        A more XSLT-like approach to SXML transformations


File: guile.info,  Node: SXML Overview,  Next: Reading and Writing XML,  Up: SXML

7.21.1 SXML Overview
--------------------

(This section needs to be written; volunteers welcome.)


File: guile.info,  Node: Reading and Writing XML,  Next: SSAX,  Prev: SXML Overview,  Up: SXML

7.21.2 Reading and Writing XML
------------------------------

The ‘(sxml simple)’ module presents a basic interface for parsing XML
from a port into the Scheme SXML format, and for serializing it back to
text.

     (use-modules (sxml simple))

 -- Scheme Procedure: xml->sxml [string-or-port] [#:namespaces='()]
          [#:declare-namespaces?=#t] [#:trim-whitespace?=#f]
          [#:entities='()] [#:default-entity-handler=#f]
          [#:doctype-handler=#f]
     Use SSAX to parse an XML document into SXML. Takes one optional
     argument, STRING-OR-PORT, which defaults to the current input port.
     Returns the resulting SXML document.  If STRING-OR-PORT is a port,
     it will be left pointing at the next available character in the
     port.

   As is normal in SXML, XML elements parse as tagged lists.
Attributes, if any, are placed after the tag, within an ‘@’ element.
The root of the resulting XML will be contained in a special tag,
‘*TOP*’.  This tag will contain the root element of the XML, but also
any prior processing instructions.

     (xml->sxml "<foo/>")
     ⇒ (*TOP* (foo))
     (xml->sxml "<foo>text</foo>")
     ⇒ (*TOP* (foo "text"))
     (xml->sxml "<foo kind=\"bar\">text</foo>")
     ⇒ (*TOP* (foo (@ (kind "bar")) "text"))
     (xml->sxml "<?xml version=\"1.0\"?><foo/>")
     ⇒ (*TOP* (*PI* xml "version=\"1.0\"") (foo))

   All namespaces in the XML document must be declared, via ‘xmlns’
attributes.  SXML elements built from non-default namespaces will have
their tags prefixed with their URI. Users can specify custom prefixes
for certain namespaces with the ‘#:namespaces’ keyword argument to
‘xml->sxml’.  A namespace can be removed by using a ‘#f’ custom prefix.

     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>")
     ⇒ (*TOP* (http://example.org/ns1:foo "text"))
     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>"
                #:namespaces '((ns1 . "http://example.org/ns1")))
     ⇒ (*TOP* (ns1:foo "text"))
     (xml->sxml "<foo xmlns:bar=\"http://example.org/ns2\"><bar:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))

   By default, namespaces passed to ‘xml->sxml’ are treated as if they
were declared on the root element.  Passing a false
‘#:declare-namespaces?’ argument will disable this behavior, requiring
in-document declarations of namespaces before use.

     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))
     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2"))
                #:declare-namespaces? #f)
     ⇒ error: undeclared namespace: `bar'

   By default, all whitespace in XML is significant.  Passing the
‘#:trim-whitespace?’ keyword argument to ‘xml->sxml’ will trim
whitespace in front, behind and between elements, treating it as
“unsignificant”.  Whitespace in text fragments is left alone.

     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>")
     ⇒ (*TOP* (foo "\n" (bar " Alfie the parrot! ") "\n"))
     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>"
                #:trim-whitespace? #t)
     ⇒ (*TOP* (foo (bar " Alfie the parrot! ")))

   Parsed entities may be declared with the ‘#:entities’ keyword
argument, or handled with the ‘#:default-entity-handler’.  By default,
only the standard ‘&lt;’, ‘&gt;’, ‘&amp;’, ‘&apos;’ and ‘&quot;’
entities are defined, as well as the ‘&#N;’ and ‘&#xN;’ (decimal and
hexadecimal) numeric character entities.

     (xml->sxml "<foo>&amp;</foo>")
     ⇒ (*TOP* (foo "&"))
     (xml->sxml "<foo>&nbsp;</foo>")
     ⇒ error: undefined entity: nbsp
     (xml->sxml "<foo>&#xA0;</foo>")
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp;</foo>"
                #:entities '((nbsp . "\xa0")))
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp; &foo;</foo>"
                #:default-entity-handler
                (lambda (port name)
                  (case name
                    ((nbsp) "\xa0")
                    (else
                     (format (current-warning-port)
                             "~a:~a:~a: undefined entitity: ~a\n"
                             (or (port-filename port) "<unknown file>")
                             (port-line port) (port-column port)
                             name)
                     (symbol->string name)))))
     ⊣ <unknown file>:0:17: undefined entitity: foo
     ⇒ (*TOP* (foo "\xa0 foo"))

   By default, ‘xml->sxml’ skips over the ‘<!DOCTYPE>’ declaration, if
any.  This behavior can be overridden with the ‘#:doctype-handler’
argument, which should be a procedure of three arguments: the “docname”
(a symbol), “systemid” (a string), and the internal doctype subset (as a
string or ‘#f’ if not present).

   The handler should return keyword arguments as multiple values, as if
it were calling its continuation with keyword arguments.  The
continuation accepts the ‘#:entities’ and ‘#:namespaces’ keyword
arguments, in the same format that ‘xml->sxml’ itself takes.  These
entities and namespaces will be prepended to those given to the
‘xml->sxml’ invocation.

     (define (handle-foo docname systemid internal-subset)
       (case docname
         ((foo)
          (values #:entities '((greets . "<i>Hello, world!</i>"))))
         (else
          (values))))

     (xml->sxml "<!DOCTYPE foo><p>&greets;</p>"
                #:doctype-handler handle-foo)
     ⇒ (*TOP* (p (i "Hello, world!")))

   If the document has no doctype declaration, the DOCTYPE-HANDLER is
invoked with ‘#f’ for the three arguments.

   In the future, the continuation may accept other keyword arguments,
for example to validate the parsed SXML against the doctype.

 -- Scheme Procedure: sxml->xml tree [port]
     Serialize the SXML tree TREE as XML. The output will be written to
     the current output port, unless the optional argument PORT is
     present.

   Output is automatically escaped as expected for a serializer.

     (sxml->xml `(code "<i>Some example</i>"))
     ⇒ <code>&lt;i&gt;Some example&lt;/i&gt;</code>

   In order to avoid some string from being escaped, it must be wrapped
in a procedure that writes the string to the ‘(current-output-port)’.

     (sxml->xml `(code ,(lambda () (display "<i>Some example</i>"))))
     ⇒ <code><i>Some example</i></code>

 -- Scheme Procedure: sxml->string sxml
     Detag an sxml tree SXML into a string.  Does not perform any
     formatting.


File: guile.info,  Node: SSAX,  Next: Transforming SXML,  Prev: Reading and Writing XML,  Up: SXML

7.21.3 SSAX: A Functional XML Parsing Toolkit
---------------------------------------------

Guile’s XML parser is based on Oleg Kiselyov’s powerful XML parsing
toolkit, SSAX.

7.21.3.1 History
................

Back in the 1990s, when the world was young again and XML was the
solution to all of its problems, there were basically two kinds of XML
parsers out there: DOM parsers and SAX parsers.

   A DOM parser reads through an entire XML document, building up a tree
of “DOM objects” representing the document structure.  They are very
easy to use, but sometimes you don’t actually want all of the
information in a document; building an object tree is not necessary if
all you want to do is to count word frequencies in a document, for
example.

   SAX parsers were created to give the programmer more control on the
parsing process.  A programmer gives the SAX parser a number of
“callbacks”: functions that will be called on various features of the
XML stream as they are encountered.  SAX parsers are more efficient, but
much harder to use, as users typically have to manually maintain a stack
of open elements.

   Kiselyov realized that the SAX programming model could be made much
simpler if the callbacks were formulated not as a linear fold across the
features of the XML stream, but as a _tree fold_ over the structure
implicit in the XML. In this way, the user has a very convenient,
functional-style interface that can still generate optimal parsers.

   The ‘xml->sxml’ interface from the ‘(sxml simple)’ module is a
DOM-style parser built using SSAX, though it returns SXML instead of DOM
objects.

7.21.3.2 Implementation
.......................

‘(sxml ssax)’ is a package of low-to-high level lexing and parsing
procedures that can be combined to yield a SAX, a DOM, a validating
parser, or a parser intended for a particular document type.  The
procedures in the package can be used separately to tokenize or parse
various pieces of XML documents.  The package supports XML Namespaces,
internal and external parsed entities, user-controlled handling of
whitespace, and validation.  This module therefore is intended to be a
framework, a set of “Lego blocks” you can use to build a parser
following any discipline and performing validation to any degree.  As an
example of the parser construction, the source file includes a
semi-validating SXML parser.

   SSAX has a “sequential” feel of SAX yet a “functional style” of DOM.
Like a SAX parser, the framework scans the document only once and
permits incremental processing.  An application that handles document
elements in order can run as efficiently as possible.  _Unlike_ a SAX
parser, the framework does not require an application register stateful
callbacks and surrender control to the parser.  Rather, it is the
application that can drive the framework – calling its functions to get
the current lexical or syntax element.  These functions do not maintain
or mutate any state save the input port.  Therefore, the framework
permits parsing of XML in a pure functional style, with the input port
being a monad (or a linear, read-once parameter).

   Besides the PORT, there is another monad – SEED.  Most of the middle-
and high-level parsers are single-threaded through the SEED.  The
functions of this framework do not process or affect the SEED in any
way: they simply pass it around as an instance of an opaque datatype.
User functions, on the other hand, can use the seed to maintain user’s
state, to accumulate parsing results, etc.  A user can freely mix their
own functions with those of the framework.  On the other hand, the user
may wish to instantiate a high-level parser: ‘SSAX:make-elem-parser’ or
‘SSAX:make-parser’.  In the latter case, the user must provide functions
of specific signatures, which are called at predictable moments during
the parsing: to handle character data, element data, or processing
instructions (PI). The functions are always given the SEED, among other
parameters, and must return the new SEED.

   From a functional point of view, XML parsing is a combined
pre-post-order traversal of a “tree” that is the XML document itself.
This down-and-up traversal tells the user about an element when its
start tag is encountered.  The user is notified about the element once
more, after all element’s children have been handled.  The process of
XML parsing therefore is a fold over the raw XML document.  Unlike a
fold over trees defined in [1], the parser is necessarily
single-threaded – obviously as elements in a text XML document are laid
down sequentially.  The parser therefore is a tree fold that has been
transformed to accept an accumulating parameter [1,2].

   Formally, the denotational semantics of the parser can be expressed
as

      parser:: (Start-tag -> Seed -> Seed) ->
     	   (Start-tag -> Seed -> Seed -> Seed) ->
     	   (Char-Data -> Seed -> Seed) ->
     	   XML-text-fragment -> Seed -> Seed
      parser fdown fup fchar "<elem attrs> content </elem>" seed
       = fup "<elem attrs>" seed
     	(parser fdown fup fchar "content" (fdown "<elem attrs>" seed))

      parser fdown fup fchar "char-data content" seed
       = parser fdown fup fchar "content" (fchar "char-data" seed)

      parser fdown fup fchar "elem-content content" seed
       = parser fdown fup fchar "content" (
     	parser fdown fup fchar "elem-content" seed)

   Compare the last two equations with the left fold

      fold-left kons elem:list seed = fold-left kons list (kons elem seed)

   The real parser created by ‘SSAX:make-parser’ is slightly more
complicated, to account for processing instructions, entity references,
namespaces, processing of document type declaration, etc.

   The XML standard document referred to in this module is
<http://www.w3.org/TR/1998/REC-xml-19980210.html>

   The present file also defines a procedure that parses the text of an
XML document or of a separate element into SXML, an S-expression-based
model of an XML Information Set.  SXML is also an Abstract Syntax Tree
of an XML document.  SXML is similar but not identical to DOM; SXML is
particularly suitable for Scheme-based XML/HTML authoring, SXPath
queries, and tree transformations.  See SXML.html for more details.
SXML is a term implementation of evaluation of the XML document [3].
The other implementation is context-passing.

   The present frameworks fully supports the XML Namespaces
Recommendation: <http://www.w3.org/TR/REC-xml-names/>.

   Other links:

[1]
     Jeremy Gibbons, Geraint Jones, "The Under-appreciated Unfold,"
     Proc.  ICFP’98, 1998, pp.  273-279.

[2]
     Richard S. Bird, The promotion and accumulation strategies in
     transformational programming, ACM Trans.  Progr.  Lang.  Systems,
     6(4):487-504, October 1984.

[3]
     Ralf Hinze, "Deriving Backtracking Monad Transformers," Functional
     Pearl.  Proc ICFP’00, pp.  186-197.

7.21.3.3 Usage
..............

 -- Scheme Procedure: current-ssax-error-port

 -- Scheme Procedure: with-ssax-error-to-port port thunk

 -- Scheme Procedure: xml-token? _
      -- Scheme Procedure: pair? x
          Return `#t' if X is a pair; otherwise return `#f'.
     
      

 -- Scheme Syntax: xml-token-kind token

 -- Scheme Syntax: xml-token-head token

 -- Scheme Procedure: make-empty-attlist

 -- Scheme Procedure: attlist-add attlist name-value

 -- Scheme Procedure: attlist-null? x
     Return ‘#t’ if X is the empty list, else ‘#f’.

 -- Scheme Procedure: attlist-remove-top attlist

 -- Scheme Procedure: attlist->alist attlist

 -- Scheme Procedure: attlist-fold kons knil lis1

 -- Scheme Procedure: define-parsed-entity! entity str
     Define a new parsed entity.  ENTITY should be a symbol.

     Instances of &ENTITY; in XML text will be replaced with the string
     STR, which will then be parsed.

 -- Scheme Procedure: reset-parsed-entity-definitions!
     Restore the set of parsed entity definitions to its initial state.

 -- Scheme Procedure: ssax:uri-string->symbol uri-str

 -- Scheme Procedure: ssax:skip-internal-dtd port

 -- Scheme Procedure: ssax:read-pi-body-as-string port

 -- Scheme Procedure: ssax:reverse-collect-str-drop-ws fragments

 -- Scheme Procedure: ssax:read-markup-token port

 -- Scheme Procedure: ssax:read-cdata-body port str-handler seed

 -- Scheme Procedure: ssax:read-char-ref port

 -- Scheme Procedure: ssax:read-attributes port entities

 -- Scheme Procedure: ssax:complete-start-tag tag-head port elems
          entities namespaces

 -- Scheme Procedure: ssax:read-external-id port

 -- Scheme Procedure: ssax:read-char-data port expect-eof? str-handler
          seed

 -- Scheme Procedure: ssax:xml->sxml port namespace-prefix-assig

 -- Scheme Syntax: ssax:make-parser . kw-val-pairs

 -- Scheme Syntax: ssax:make-pi-parser orig-handlers

 -- Scheme Syntax: ssax:make-elem-parser my-new-level-seed
          my-finish-element my-char-data-handler my-pi-handlers


File: guile.info,  Node: Transforming SXML,  Next: SXML Tree Fold,  Prev: SSAX,  Up: SXML

7.21.4 Transforming SXML
------------------------

7.21.4.1 Overview
.................

SXML expression tree transformers
=================================

Pre-Post-order traversal of a tree and creation of a new tree
-------------------------------------------------------------

     pre-post-order:: <tree> x <bindings> -> <new-tree>

   where

      <bindings> ::= (<binding> ...)
      <binding> ::= (<trigger-symbol> *preorder* . <handler>) |
                    (<trigger-symbol> *macro* . <handler>) |
     		(<trigger-symbol> <new-bindings> . <handler>) |
     		(<trigger-symbol> . <handler>)
      <trigger-symbol> ::= XMLname | *text* | *default*
      <handler> :: <trigger-symbol> x [<tree>] -> <new-tree>

   The ‘pre-post-order’ function, in the ‘(sxml transform)’ module,
visits the nodes and nodelists pre-post-order (depth-first).  For each
‘<Node>’ of the form ‘(NAME <Node> ...)’, it looks up an association
with the given NAME among its <BINDINGS>.  If failed, ‘pre-post-order’
tries to locate a ‘*default*’ binding.  It’s an error if the latter
attempt fails as well.  Having found a binding, the ‘pre-post-order’
function first checks to see if the binding is of the form

     	(<trigger-symbol> *preorder* . <handler>)

   If it is, the handler is ’applied’ to the current node.  Otherwise,
the pre-post-order function first calls itself recursively for each
child of the current node, with <NEW-BINDINGS> prepended to the
<BINDINGS> in effect.  The result of these calls is passed to the
<HANDLER> (along with the head of the current <NODE>).  To be more
precise, the handler is _applied_ to the head of the current node and
its processed children.  The result of the handler, which should also be
a ‘<tree>’, replaces the current <NODE>.  If the current <NODE> is a
text string or other atom, a special binding with a symbol ‘*text*’ is
looked up.

   A binding can also be of a form

     	(<trigger-symbol> *macro* . <handler>)

   This is equivalent to ‘*preorder*’ described above.  However, the
result is re-processed again, with the current stylesheet.

7.21.4.2 Usage
..............

 -- Scheme Procedure: SRV:send-reply . fragments
     Output the FRAGMENTS to the current output port.

     The fragments are a list of strings, characters, numbers, thunks,
     ‘#f’, ‘#t’ – and other fragments.  The function traverses the tree
     depth-first, writes out strings and characters, executes thunks,
     and ignores ‘#f’ and ‘'()’.  The function returns ‘#t’ if anything
     was written at all; otherwise the result is ‘#f’ If ‘#t’ occurs
     among the fragments, it is not written out but causes the result of
     ‘SRV:send-reply’ to be ‘#t’.

 -- Scheme Procedure: foldts fdown fup fhere seed tree

 -- Scheme Procedure: post-order tree bindings

 -- Scheme Procedure: pre-post-order tree bindings

 -- Scheme Procedure: replace-range beg-pred end-pred forest


File: guile.info,  Node: SXML Tree Fold,  Next: SXPath,  Prev: Transforming SXML,  Up: SXML

7.21.5 SXML Tree Fold
---------------------

7.21.5.1 Overview
.................

‘(sxml fold)’ defines a number of variants of the “fold” algorithm for
use in transforming SXML trees.  Additionally it defines the layout
operator, ‘fold-layout’, which might be described as a context-passing
variant of SSAX’s ‘pre-post-order’.

7.21.5.2 Usage
..............

 -- Scheme Procedure: foldt fup fhere tree
     The standard multithreaded tree fold.

     FUP is of type [a] -> a.  FHERE is of type object -> a.

 -- Scheme Procedure: foldts fdown fup fhere seed tree
     The single-threaded tree fold originally defined in SSAX. *Note
     SSAX::, for more information.

 -- Scheme Procedure: foldts* fdown fup fhere seed tree
     A variant of ‘foldts’ that allows pre-order tree rewrites.
     Originally defined in Andy Wingo’s 2007 paper, _Applications of
     fold to XML transformation_.

 -- Scheme Procedure: fold-values proc list . seeds
     A variant of ‘fold’ that allows multi-valued seeds.  Note that the
     order of the arguments differs from that of ‘fold’.  *Note SRFI-1
     Fold and Map::.

 -- Scheme Procedure: foldts*-values fdown fup fhere tree . seeds
     A variant of ‘foldts*’ that allows multi-valued seeds.  Originally
     defined in Andy Wingo’s 2007 paper, _Applications of fold to XML
     transformation_.

 -- Scheme Procedure: fold-layout tree bindings params layout stylesheet
     A traversal combinator in the spirit of ‘pre-post-order’.  *Note
     Transforming SXML::.

     ‘fold-layout’ was originally presented in Andy Wingo’s 2007 paper,
     _Applications of fold to XML transformation_.

          bindings := (<binding>...)
          binding  := (<tag> <handler-pair>...)
                    | (*default* . <post-handler>)
                    | (*text* . <text-handler>)
          tag      := <symbol>
          handler-pair := (pre-layout . <pre-layout-handler>)
                    | (post . <post-handler>)
                    | (bindings . <bindings>)
                    | (pre . <pre-handler>)
                    | (macro . <macro-handler>)

     PRE-LAYOUT-HANDLER
          A function of three arguments:

          KIDS
               the kids of the current node, before traversal

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into this node

          PRE-LAYOUT-HANDLER is expected to use this information to
          return a layout to pass to the kids.  The default
          implementation returns the layout given in the arguments.

     POST-HANDLER
          A function of five arguments:

          TAG
               the current tag being processed

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into the current node, before any kids
               were processed

          KLAYOUT
               the layout after processing all of the children

          KIDS
               the already-processed child nodes

          POST-HANDLER should return two values, the layout to pass to
          the next node and the final tree.

     TEXT-HANDLER
          TEXT-HANDLER is a function of three arguments:

          TEXT
               the string

          PARAMS
               the current params

          LAYOUT
               the current layout

          TEXT-HANDLER should return two values, the layout to pass to
          the next node and the value to which the string should
          transform.


File: guile.info,  Node: SXPath,  Next: sxml ssax input-parse,  Prev: SXML Tree Fold,  Up: SXML

7.21.6 SXPath
-------------

7.21.6.1 Overview
.................

SXPath: SXML Query Language
===========================

SXPath is a query language for SXML, an instance of XML Information set
(Infoset) in the form of s-expressions.  See ‘(sxml ssax)’ for the
definition of SXML and more details.  SXPath is also a translation into
Scheme of an XML Path Language, XPath (http://www.w3.org/TR/xpath).
XPath and SXPath describe means of selecting a set of Infoset’s items or
their properties.

   To facilitate queries, XPath maps the XML Infoset into an explicit
tree, and introduces important notions of a location path and a current,
context node.  A location path denotes a selection of a set of nodes
relative to a context node.  Any XPath tree has a distinguished, root
node – which serves as the context node for absolute location paths.
Location path is recursively defined as a location step joined with a
location path.  A location step is a simple query of the database
relative to a context node.  A step may include expressions that further
filter the selected set.  Each node in the resulting set is used as a
context node for the adjoining location path.  The result of the step is
a union of the sets returned by the latter location paths.

   The SXML representation of the XML Infoset (see SSAX.scm) is rather
suitable for querying as it is.  Bowing to the XPath specification, we
will refer to SXML information items as ’Nodes’:

      	<Node> ::= <Element> | <attributes-coll> | <attrib>
      		   | "text string" | <PI>

   This production can also be described as

     	<Node> ::= (name . <Nodeset>) | "text string"

   An (ordered) set of nodes is just a list of the constituent nodes:

      	<Nodeset> ::= (<Node> ...)

   Nodesets, and Nodes other than text strings are both lists.  A
<Nodeset> however is either an empty list, or a list whose head is not a
symbol.  A symbol at the head of a node is either an XML name (in which
case it’s a tag of an XML element), or an administrative name such as
’@’.  This uniform list representation makes processing rather simple
and elegant, while avoiding confusion.  The multi-branch tree structure
formed by the mutually-recursive datatypes <Node> and <Nodeset> lends
itself well to processing by functional languages.

   A location path is in fact a composite query over an XPath tree or
its branch.  A single step is a combination of a projection, selection
or a transitive closure.  Multiple steps are combined via join and union
operations.  This insight allows us to _elegantly_ implement XPath as a
sequence of projection and filtering primitives – converters – joined by
“combinators”.  Each converter takes a node and returns a nodeset which
is the result of the corresponding query relative to that node.  A
converter can also be called on a set of nodes.  In that case it returns
a union of the corresponding queries over each node in the set.  The
union is easily implemented as a list append operation as all nodes in a
SXML tree are considered distinct, by XPath conventions.  We also
preserve the order of the members in the union.  Query combinators are
high-order functions: they take converter(s) (which is a Node|Nodeset ->
Nodeset function) and compose or otherwise combine them.  We will be
concerned with only relative location paths [XPath]: an absolute
location path is a relative path applied to the root node.

   Similarly to XPath, SXPath defines full and abbreviated notations for
location paths.  In both cases, the abbreviated notation can be
mechanically expanded into the full form by simple rewriting rules.  In
the case of SXPath the corresponding rules are given in the
documentation of the ‘sxpath’ procedure.  *Note SXPath procedure
documentation: sxpath-procedure-docs.

   The regression test suite at the end of the file ‘SXPATH-old.scm’
shows a representative sample of SXPaths in both notations, juxtaposed
with the corresponding XPath expressions.  Most of the samples are
borrowed literally from the XPath specification.

   Much of the following material is taken from the SXPath sources by
Oleg Kiselyov et al.

7.21.6.2 Basic Converters and Applicators
.........................................

A converter is a function mapping a nodeset (or a single node) to
another nodeset.  Its type can be represented like this:

     type Converter = Node|Nodeset -> Nodeset

   A converter can also play the role of a predicate: in that case, if a
converter, applied to a node or a nodeset, yields a non-empty nodeset,
the converter-predicate is deemed satisfied.  Likewise, an empty nodeset
is equivalent to ‘#f’ in denoting failure.

 -- Scheme Procedure: nodeset? x
     Return ‘#t’ if X is a nodeset.

 -- Scheme Procedure: node-typeof? crit
     This function implements a ’Node test’ as defined in Sec.  2.3 of
     the XPath document.  A node test is one of the components of a
     location step.  It is also a converter-predicate in SXPath.

     The function ‘node-typeof?’ takes a type criterion and returns a
     function, which, when applied to a node, will tell if the node
     satisfies the test.

     The criterion CRIT is a symbol, one of the following:

     ‘id’
          tests if the node has the right name (id)

     ‘@’
          tests if the node is an <attributes-coll>

     ‘*’
          tests if the node is an <Element>

     ‘*text*’
          tests if the node is a text node

     ‘*PI*’
          tests if the node is a PI (processing instruction) node

     ‘*any*’
          ‘#t’ for any type of node

 -- Scheme Procedure: node-eq? other
     A curried equivalence converter predicate that takes a node OTHER
     and returns a function that takes another node.  The two nodes are
     compared using ‘eq?’.

 -- Scheme Procedure: node-equal? other
     A curried equivalence converter predicate that takes a node OTHER
     and returns a function that takes another node.  The two nodes are
     compared using ‘equal?’.

 -- Scheme Procedure: node-pos n
     Select the N’th element of a nodeset and return as a singular
     nodeset.  If the N’th element does not exist, return an empty
     nodeset.  If N is a negative number the node is picked from the
     tail of the list.

          ((node-pos 1) nodeset)  ; return the the head of the nodeset (if exists)
          ((node-pos 2) nodeset)  ; return the node after that (if exists)
          ((node-pos -1) nodeset) ; selects the last node of a non-empty nodeset
          ((node-pos -2) nodeset) ; selects the last but one node, if exists.

 -- Scheme Procedure: filter pred?
     A filter applicator, which introduces a filtering context.  The
     argument converter PRED? is considered a predicate, with either
     ‘#f’ or ‘nil’ meaning failure.

 -- Scheme Procedure: take-until pred?
          take-until:: Converter -> Converter, or
          take-until:: Pred -> Node|Nodeset -> Nodeset

     Given a converter-predicate PRED? and a nodeset, apply the
     predicate to each element of the nodeset, until the predicate
     yields anything but ‘#f’ or ‘nil’.  Return the elements of the
     input nodeset that have been processed until that moment (that is,
     which fail the predicate).

     ‘take-until’ is a variation of the ‘filter’ above: ‘take-until’
     passes elements of an ordered input set up to (but not including)
     the first element that satisfies the predicate.  The nodeset
     returned by ‘((take-until (not pred)) nset)’ is a subset – to be
     more precise, a prefix – of the nodeset returned by ‘((filter pred)
     nset)’.

 -- Scheme Procedure: take-after pred?
          take-after:: Converter -> Converter, or
          take-after:: Pred -> Node|Nodeset -> Nodeset

     Given a converter-predicate PRED? and a nodeset, apply the
     predicate to each element of the nodeset, until the predicate
     yields anything but ‘#f’ or ‘nil’.  Return the elements of the
     input nodeset that have not been processed: that is, return the
     elements of the input nodeset that follow the first element that
     satisfied the predicate.

     ‘take-after’ along with ‘take-until’ partition an input nodeset
     into three parts: the first element that satisfies a predicate, all
     preceding elements and all following elements.

 -- Scheme Procedure: map-union proc lst
     Apply PROC to each element of LST and return the list of results.
     If PROC returns a nodeset, splice it into the result

     From another point of view, ‘map-union’ is a function
     ‘Converter->Converter’, which places an argument-converter in a
     joining context.

 -- Scheme Procedure: node-reverse node-or-nodeset
          node-reverse :: Converter, or
          node-reverse:: Node|Nodeset -> Nodeset

     Reverses the order of nodes in the nodeset.  This basic converter
     is needed to implement a reverse document order (see the XPath
     Recommendation).

 -- Scheme Procedure: node-trace title
          node-trace:: String -> Converter

     ‘(node-trace title)’ is an identity converter.  In addition it
     prints out the node or nodeset it is applied to, prefixed with the
     TITLE.  This converter is very useful for debugging.

7.21.6.3 Converter Combinators
..............................

Combinators are higher-order functions that transmogrify a converter or
glue a sequence of converters into a single, non-trivial converter.  The
goal is to arrive at converters that correspond to XPath location paths.

   From a different point of view, a combinator is a fixed, named
“pattern” of applying converters.  Given below is a complete set of such
patterns that together implement XPath location path specification.  As
it turns out, all these combinators can be built from a small number of
basic blocks: regular functional composition, ‘map-union’ and ‘filter’
applicators, and the nodeset union.

 -- Scheme Procedure: select-kids test-pred?
     ‘select-kids’ takes a converter (or a predicate) as an argument and
     returns another converter.  The resulting converter applied to a
     nodeset returns an ordered subset of its children that satisfy the
     predicate TEST-PRED?.

 -- Scheme Procedure: node-self pred?
     Similar to ‘select-kids’ except that the predicate PRED? is applied
     to the node itself rather than to its children.  The resulting
     nodeset will contain either one component, or will be empty if the
     node failed the predicate.

 -- Scheme Procedure: node-join . selectors
          node-join:: [LocPath] -> Node|Nodeset -> Nodeset, or
          node-join:: [Converter] -> Converter

     Join the sequence of location steps or paths as described above.

 -- Scheme Procedure: node-reduce . converters
          node-reduce:: [LocPath] -> Node|Nodeset -> Nodeset, or
          node-reduce:: [Converter] -> Converter

     A regular functional composition of converters.  From a different
     point of view, ‘((apply node-reduce converters) nodeset)’ is
     equivalent to ‘(foldl apply nodeset converters)’, i.e., folding, or
     reducing, a list of converters with the nodeset as a seed.

 -- Scheme Procedure: node-or . converters
          node-or:: [Converter] -> Converter

     This combinator applies all converters to a given node and produces
     the union of their results.  This combinator corresponds to a union
     (‘|’ operation) for XPath location paths.

 -- Scheme Procedure: node-closure test-pred?
          node-closure:: Converter -> Converter

     Select all _descendants_ of a node that satisfy a
     converter-predicate TEST-PRED?.  This combinator is similar to
     ‘select-kids’ but applies to grand...  children as well.  This
     combinator implements the ‘descendant::’ XPath axis.  Conceptually,
     this combinator can be expressed as

          (define (node-closure f)
            (node-or
              (select-kids f)
              (node-reduce (select-kids (node-typeof? '*)) (node-closure f))))

     This definition, as written, looks somewhat like a fixpoint, and it
     will run forever.  It is obvious however that sooner or later
     ‘(select-kids (node-typeof? '*))’ will return an empty nodeset.  At
     this point further iterations will no longer affect the result and
     can be stopped.

 -- Scheme Procedure: node-parent rootnode
          node-parent:: RootNode -> Converter

     ‘(node-parent rootnode)’ yields a converter that returns a parent
     of a node it is applied to.  If applied to a nodeset, it returns
     the list of parents of nodes in the nodeset.  The ROOTNODE does not
     have to be the root node of the whole SXML tree – it may be a root
     node of a branch of interest.

     Given the notation of Philip Wadler’s paper on semantics of XSLT,

       parent(x) = { y | y=subnode*(root), x=subnode(y) }

     Therefore, ‘node-parent’ is not the fundamental converter: it can
     be expressed through the existing ones.  Yet ‘node-parent’ is a
     rather convenient converter.  It corresponds to a ‘parent::’ axis
     of SXPath.  Note that the ‘parent::’ axis can be used with an
     attribute node as well.

 -- Scheme Procedure: sxpath path
     Evaluate an abbreviated SXPath.

          sxpath:: AbbrPath -> Converter, or
          sxpath:: AbbrPath -> Node|Nodeset -> Nodeset

     PATH is a list.  It is translated to the full SXPath according to
     the following rewriting rules:

          (sxpath '())
          ⇒ (node-join)

          (sxpath '(path-component ...))
          ⇒ (node-join (sxpath1 path-component) (sxpath '(...)))

          (sxpath1 '//)
          ⇒ (node-or
             (node-self (node-typeof? '*any*))
             (node-closure (node-typeof? '*any*)))

          (sxpath1 '(equal? x))
          ⇒ (select-kids (node-equal? x))

          (sxpath1 '(eq? x))
          ⇒ (select-kids (node-eq? x))

          (sxpath1 ?symbol)
          ⇒ (select-kids (node-typeof? ?symbol)

          (sxpath1 procedure)
          ⇒ procedure

          (sxpath1 '(?symbol ...))
          ⇒ (sxpath1 '((?symbol) ...))

          (sxpath1 '(path reducer ...))
          ⇒ (node-reduce (sxpath path) (sxpathr reducer) ...)

          (sxpathr number)
          ⇒ (node-pos number)

          (sxpathr path-filter)
          ⇒ (filter (sxpath path-filter))


File: guile.info,  Node: sxml ssax input-parse,  Next: sxml apply-templates,  Prev: SXPath,  Up: SXML

7.21.7 (sxml ssax input-parse)
------------------------------

7.21.7.1 Overview
.................

A simple lexer.

   The procedures in this module surprisingly often suffice to parse an
input stream.  They either skip, or build and return tokens, according
to inclusion or delimiting semantics.  The list of characters to expect,
include, or to break at may vary from one invocation of a function to
another.  This allows the functions to easily parse even
context-sensitive languages.

   EOF is generally frowned on, and thrown up upon if encountered.
Exceptions are mentioned specifically.  The list of expected characters
(characters to skip until, or break-characters) may include an EOF
"character", which is to be coded as the symbol, ‘*eof*’.

   The input stream to parse is specified as a “port”, which is usually
the last (and optional) argument.  It defaults to the current input port
if omitted.

   If the parser encounters an error, it will throw an exception to the
key ‘parser-error’.  The arguments will be of the form ‘(PORT MESSAGE
SPECIALISING-MSG*)’.

   The first argument is a port, which typically points to the offending
character or its neighborhood.  You can then use ‘port-column’ and
‘port-line’ to query the current position.  MESSAGE is the description
of the error.  Other arguments supply more details about the problem.

7.21.7.2 Usage
..............

 -- Scheme Procedure: peek-next-char [port]

 -- Scheme Procedure: assert-curr-char expected-chars comment [port]

 -- Scheme Procedure: skip-until arg [port]

 -- Scheme Procedure: skip-while skip-chars [port]

 -- Scheme Procedure: next-token prefix-skipped-chars break-chars
          [comment] [port]

 -- Scheme Procedure: next-token-of incl-list/pred [port]

 -- Scheme Procedure: read-text-line [port]

 -- Scheme Procedure: read-string n [port]

 -- Scheme Procedure: find-string-from-port? _ _ . _
     Looks for STR in <INPUT-PORT>, optionally within the first
     MAX-NO-CHAR characters.


File: guile.info,  Node: sxml apply-templates,  Prev: sxml ssax input-parse,  Up: SXML

7.21.8 (sxml apply-templates)
-----------------------------

7.21.8.1 Overview
.................

Pre-order traversal of a tree and creation of a new tree:

     	apply-templates:: tree x <templates> -> <new-tree>

   where

      <templates> ::= (<template> ...)
      <template>  ::= (<node-test> <node-test> ... <node-test> . <handler>)
      <node-test> ::= an argument to node-typeof? above
      <handler>   ::= <tree> -> <new-tree>

   This procedure does a _normal_, pre-order traversal of an SXML tree.
It walks the tree, checking at each node against the list of matching
templates.

   If the match is found (which must be unique, i.e., unambiguous), the
corresponding handler is invoked and given the current node as an
argument.  The result from the handler, which must be a ‘<tree>’, takes
place of the current node in the resulting tree.  The name of the
function is not accidental: it resembles rather closely an
‘apply-templates’ function of XSLT.

7.21.8.2 Usage
..............

 -- Scheme Procedure: apply-templates tree templates


File: guile.info,  Node: Texinfo Processing,  Prev: SXML,  Up: Guile Modules

7.22 Texinfo Processing
=======================

* Menu:

* texinfo::              Parse texinfo files or fragments into ‘stexi’, a scheme representation
* texinfo docbook::      Transform a subset of docbook into ‘stexi’
* texinfo html::         Transform ‘stexi’ into HTML
* texinfo indexing::     Extract an index from a piece of ‘stexi’
* texinfo string-utils::  String utility functions used by the texinfo processor
* texinfo plain-text::   Render ‘stexi’ as plain text
* texinfo serialize::    Render ‘stexi’ as texinfo
* texinfo reflection::   Enable texinfo across Guile’s help system


File: guile.info,  Node: texinfo,  Next: texinfo docbook,  Up: Texinfo Processing

7.22.1 (texinfo)
----------------

7.22.1.1 Overview
.................

Texinfo processing in scheme
----------------------------

This module parses texinfo into SXML. TeX will always be the processor
of choice for print output, of course.  However, although ‘makeinfo’
works well for info, its output in other formats is not very
customizable, and the program is not extensible as a whole.  This module
aims to provide an extensible framework for texinfo processing that
integrates texinfo into the constellation of SXML processing tools.

Notes on the SXML vocabulary
----------------------------

Consider the following texinfo fragment:

      @deffn Primitive set-car! pair value
      This function...
      @end deffn

   Logically, the category (Primitive), name (set-car!), and arguments
(pair value) are “attributes” of the deffn, with the description as the
content.  However, texinfo allows for @-commands within the arguments to
an environment, like ‘@deffn’, which means that texinfo “attributes” are
PCDATA. XML attributes, on the other hand, are CDATA. For this reason,
“attributes” of texinfo @-commands are called “arguments”, and are
grouped under the special element, ‘%’.

   Because ‘%’ is not a valid NCName, stexinfo is a superset of SXML. In
the interests of interoperability, this module provides a conversion
function to replace the ‘%’ with ‘texinfo-arguments’.

7.22.1.2 Usage
..............

 -- Function: call-with-file-and-dir filename proc
     Call the one-argument procedure PROC with an input port that reads
     from FILENAME.  During the dynamic extent of PROC’s execution, the
     current directory will be ‘(dirname FILENAME)’.  This is useful for
     parsing documents that can include files by relative path name.

 -- Variable: texi-command-specs

 -- Function: texi-command-depth command max-depth
     Given the texinfo command COMMAND, return its nesting level, or
     ‘#f’ if it nests too deep for MAX-DEPTH.

     Examples:

           (texi-command-depth 'chapter 4)        ⇒ 1
           (texi-command-depth 'top 4)            ⇒ 0
           (texi-command-depth 'subsection 4)     ⇒ 3
           (texi-command-depth 'appendixsubsec 4) ⇒ 3
           (texi-command-depth 'subsection 2)     ⇒ #f

 -- Function: texi-fragment->stexi string-or-port
     Parse the texinfo commands in STRING-OR-PORT, and return the
     resultant stexi tree.  The head of the tree will be the special
     command, ‘*fragment*’.

 -- Function: texi->stexi port
     Read a full texinfo document from PORT and return the parsed stexi
     tree.  The parsing will start at the ‘@settitle’ and end at ‘@bye’
     or EOF.

 -- Function: stexi->sxml tree
     Transform the stexi tree TREE into sxml.  This involves replacing
     the ‘%’ element that keeps the texinfo arguments with an element
     for each argument.

     FIXME: right now it just changes % to ‘texinfo-arguments’ – that
     doesn’t hang with the idea of making a dtd at some point


File: guile.info,  Node: texinfo docbook,  Next: texinfo html,  Prev: texinfo,  Up: Texinfo Processing

7.22.2 (texinfo docbook)
------------------------

7.22.2.1 Overview
.................

This module exports procedures for transforming a limited subset of the
SXML representation of docbook into stexi.  It is not complete by any
means.  The intention is to gather a number of routines and stylesheets
so that external modules can parse specific subsets of docbook, for
example that set generated by certain tools.

7.22.2.2 Usage
..............

 -- Variable: *sdocbook->stexi-rules*

 -- Variable: *sdocbook-block-commands*

 -- Function: sdocbook-flatten sdocbook
     "Flatten" a fragment of sdocbook so that block elements do not nest
     inside each other.

     Docbook is a nested format, where e.g.  a ‘refsect2’ normally
     appears inside a ‘refsect1’.  Logical divisions in the document are
     represented via the tree topology; a ‘refsect2’ element _contains_
     all of the elements in its section.

     On the contrary, texinfo is a flat format, in which sections are
     marked off by standalone section headers like ‘@subsection’, and
     block elements do not nest inside each other.

     This function takes a nested sdocbook fragment SDOCBOOK and
     flattens all of the sections, such that e.g.

           (refsect1 (refsect2 (para "Hello")))

     becomes

           ((refsect1) (refsect2) (para "Hello"))

     Oftentimes (always?)  sectioning elements have ‘<title>’ as their
     first element child; users interested in processing the ‘refsect*’
     elements into proper sectioning elements like ‘chapter’ might be
     interested in ‘replace-titles’ and ‘filter-empty-elements’.  *Note
     replace-titles: texinfo docbook replace-titles, and *note
     filter-empty-elements: texinfo docbook filter-empty-elements.

     Returns a nodeset; that is to say, an untagged list of stexi
     elements.  *Note SXPath::, for the definition of a nodeset.

 -- Function: filter-empty-elements sdocbook
     Filters out empty elements in an sdocbook nodeset.  Mostly useful
     after running ‘sdocbook-flatten’.

 -- Function: replace-titles sdocbook-fragment
     Iterate over the sdocbook nodeset SDOCBOOK-FRAGMENT, transforming
     contiguous ‘refsect’ and ‘title’ elements into the appropriate
     texinfo sectioning command.  Most useful after having run
     ‘sdocbook-flatten’.

     For example:

           (replace-titles '((refsect1) (title "Foo") (para "Bar.")))
              ⇒ '((chapter "Foo") (para "Bar."))


File: guile.info,  Node: texinfo html,  Next: texinfo indexing,  Prev: texinfo docbook,  Up: Texinfo Processing

7.22.3 (texinfo html)
---------------------

7.22.3.1 Overview
.................

This module implements transformation from ‘stexi’ to HTML. Note that
the output of ‘stexi->shtml’ is actually SXML with the HTML vocabulary.
This means that the output can be further processed, and that it must
eventually be serialized by ‘sxml->xml’.  *Note Reading and Writing
XML::.

   References (i.e., the ‘@ref’ family of commands) are resolved by a
“ref-resolver”.  *Note add-ref-resolver!: texinfo html
add-ref-resolver!.

7.22.3.2 Usage
..............

 -- Function: add-ref-resolver! proc
     Add PROC to the head of the list of ref-resolvers.  PROC will be
     expected to take the name of a node and the name of a manual and
     return the URL of the referent, or ‘#f’ to pass control to the next
     ref-resolver in the list.

     The default ref-resolver will return the concatenation of the
     manual name, ‘#’, and the node name.

 -- Function: stexi->shtml tree
     Transform the stexi TREE into shtml, resolving references via
     ref-resolvers.  See the module commentary for more details.

 -- Function: urlify str


File: guile.info,  Node: texinfo indexing,  Next: texinfo string-utils,  Prev: texinfo html,  Up: Texinfo Processing

7.22.4 (texinfo indexing)
-------------------------

7.22.4.1 Overview
.................

Given a piece of stexi, return an index of a specified variety.

   Note that currently, ‘stexi-extract-index’ doesn’t differentiate
between different kinds of index entries.  That’s a bug ;)

7.22.4.2 Usage
..............

 -- Function: stexi-extract-index tree manual-name kind
     Given an stexi tree TREE, index all of the entries of type KIND.
     KIND can be one of the predefined texinfo indices (‘concept’,
     ‘variable’, ‘function’, ‘key’, ‘program’, ‘type’) or one of the
     special symbols ‘auto’ or ‘all’.  ‘auto’ will scan the stext for a
     ‘(printindex)’ statement, and ‘all’ will generate an index from all
     entries, regardless of type.

     The returned index is a list of pairs, the CAR of which is the
     entry (a string) and the CDR of which is a node name (a string).


File: guile.info,  Node: texinfo string-utils,  Next: texinfo plain-text,  Prev: texinfo indexing,  Up: Texinfo Processing

7.22.5 (texinfo string-utils)
-----------------------------

7.22.5.1 Overview
.................

Module ‘(texinfo string-utils)’ provides various string-related
functions useful to Guile’s texinfo support.

7.22.5.2 Usage
..............

 -- Function: escape-special-chars str special-chars escape-char
     Returns a copy of STR with all given special characters preceded by
     the given ESCAPE-CHAR.

     SPECIAL-CHARS can either be a single character, or a string
     consisting of all the special characters.

          ;; make a string regexp-safe...
           (escape-special-chars "***(Example String)***"
                                "[]()/*."
                                #\\)
          => "\\*\\*\\*\\(Example String\\)\\*\\*\\*"

          ;; also can escape a single char...
           (escape-special-chars "richardt@vzavenue.net"
                                #\@
                                #\@)
          => "richardt@@vzavenue.net"

 -- Function: transform-string str match? replace [start] [end]
     Uses MATCH? against each character in STR, and performs a
     replacement on each character for which matches are found.

     MATCH? may either be a function, a character, a string, or ‘#t’.
     If MATCH? is a function, then it takes a single character as input,
     and should return ‘#t’ for matches.  MATCH? is a character, it is
     compared to each string character using ‘char=?’.  If MATCH? is a
     string, then any character in that string will be considered a
     match.  ‘#t’ will cause every character to be a match.

     If REPLACE is a function, it is called with the matched character
     as an argument, and the returned value is sent to the output string
     via ‘display’.  If REPLACE is anything else, it is sent through the
     output string via ‘display’.

     Note that the replacement for the matched characters does not need
     to be a single character.  That is what differentiates this
     function from ‘string-map’, and what makes it useful for
     applications such as converting ‘#\&’ to ‘"&amp;"’ in web page
     text.  Some other functions in this module are just wrappers around
     common uses of ‘transform-string’.  Transformations not possible
     with this function should probably be done with regular
     expressions.

     If START and END are given, they control which portion of the
     string undergoes transformation.  The entire input string is still
     output, though.  So, if START is ‘5’, then the first five
     characters of STR will still appear in the returned string.

          ; these two are equivalent...
           (transform-string str #\space #\-) ; change all spaces to -'s
           (transform-string str (lambda (c) (char=? #\space c)) #\-)

 -- Function: expand-tabs str [tab-size]
     Returns a copy of STR with all tabs expanded to spaces.  TAB-SIZE
     defaults to 8.

     Assuming tab size of 8, this is equivalent to:

           (transform-string str #\tab "        ")

 -- Function: center-string str [width] [chr] [rchr]
     Returns a copy of STR centered in a field of WIDTH characters.  Any
     needed padding is done by character CHR, which defaults to
     ‘#\space’.  If RCHR is provided, then the padding to the right will
     use it instead.  See the examples below.  left and RCHR on the
     right.  The default WIDTH is 80.  The default CHR and RCHR is
     ‘#\space’.  The string is never truncated.

           (center-string "Richard Todd" 24)
          => "      Richard Todd      "

           (center-string " Richard Todd " 24 #\=)
          => "===== Richard Todd ====="

           (center-string " Richard Todd " 24 #\< #\>)
          => "<<<<< Richard Todd >>>>>"

 -- Function: left-justify-string str [width] [chr]
     ‘left-justify-string str [width chr]’.  Returns a copy of STR
     padded with CHR such that it is left justified in a field of WIDTH
     characters.  The default WIDTH is 80.  Unlike ‘string-pad’ from
     srfi-13, the string is never truncated.

 -- Function: right-justify-string str [width] [chr]
     Returns a copy of STR padded with CHR such that it is right
     justified in a field of WIDTH characters.  The default WIDTH is 80.
     The default CHR is ‘#\space’.  Unlike ‘string-pad’ from srfi-13,
     the string is never truncated.

 -- Function: collapse-repeated-chars str [chr] [num]
     Returns a copy of STR with all repeated instances of CHR collapsed
     down to at most NUM instances.  The default value for CHR is
     ‘#\space’, and the default value for NUM is 1.

           (collapse-repeated-chars "H  e  l  l  o")
          => "H e l l o"
           (collapse-repeated-chars "H--e--l--l--o" #\-)
          => "H-e-l-l-o"
           (collapse-repeated-chars "H-e--l---l----o" #\- 2)
          => "H-e--l--l--o"

 -- Function: make-text-wrapper [#:line-width] [#:expand-tabs?]
          [#:tab-width] [#:collapse-whitespace?] [#:subsequent-indent]
          [#:initial-indent] [#:break-long-words?]
     Returns a procedure that will split a string into lines according
     to the given parameters.

     ‘#:line-width’
          This is the target length used when deciding where to wrap
          lines.  Default is 80.

     ‘#:expand-tabs?’
          Boolean describing whether tabs in the input should be
          expanded.  Default is #t.

     ‘#:tab-width’
          If tabs are expanded, this will be the number of spaces to
          which they expand.  Default is 8.

     ‘#:collapse-whitespace?’
          Boolean describing whether the whitespace inside the existing
          text should be removed or not.  Default is #t.

          If text is already well-formatted, and is just being wrapped
          to fit in a different width, then set this to ‘#f’.  This way,
          many common text conventions (such as two spaces between
          sentences) can be preserved if in the original text.  If the
          input text spacing cannot be trusted, then leave this setting
          at the default, and all repeated whitespace will be collapsed
          down to a single space.

     ‘#:initial-indent’
          Defines a string that will be put in front of the first line
          of wrapped text.  Default is the empty string, “”.

     ‘#:subsequent-indent’
          Defines a string that will be put in front of all lines of
          wrapped text, except the first one.  Default is the empty
          string, “”.

     ‘#:break-long-words?’
          If a single word is too big to fit on a line, this setting
          tells the wrapper what to do.  Defaults to #t, which will
          break up long words.  When set to #f, the line will be
          allowed, even though it is longer than the defined
          ‘#:line-width’.

     The return value is a procedure of one argument, the input string,
     which returns a list of strings, where each element of the list is
     one line.

 -- Function: fill-string str . kwargs
     Wraps the text given in string STR according to the parameters
     provided in KWARGS, or the default setting if they are not given.
     Returns a single string with the wrapped text.  Valid keyword
     arguments are discussed in ‘make-text-wrapper’.

 -- Function: string->wrapped-lines str . kwargs
     ‘string->wrapped-lines str keywds ...’.  Wraps the text given in
     string STR according to the parameters provided in KEYWDS, or the
     default setting if they are not given.  Returns a list of strings
     representing the formatted lines.  Valid keyword arguments are
     discussed in ‘make-text-wrapper’.


File: guile.info,  Node: texinfo plain-text,  Next: texinfo serialize,  Prev: texinfo string-utils,  Up: Texinfo Processing

7.22.6 (texinfo plain-text)
---------------------------

7.22.6.1 Overview
.................

Transformation from stexi to plain-text.  Strives to re-create the
output from ‘info’; comes pretty damn close.

7.22.6.2 Usage
..............

 -- Function: stexi->plain-text tree
     Transform TREE into plain text.  Returns a string.

 -- Scheme Variable: *line-width*
     This fluid (*note Fluids and Dynamic States::) specifies the length
     of line for the purposes of line wrapping in the
     ‘stexi->plain-text’ conversion.


File: guile.info,  Node: texinfo serialize,  Next: texinfo reflection,  Prev: texinfo plain-text,  Up: Texinfo Processing

7.22.7 (texinfo serialize)
--------------------------

7.22.7.1 Overview
.................

Serialization of ‘stexi’ to plain texinfo.

7.22.7.2 Usage
..............

 -- Function: stexi->texi tree
     Serialize the stexi TREE into plain texinfo.


File: guile.info,  Node: texinfo reflection,  Prev: texinfo serialize,  Up: Texinfo Processing

7.22.8 (texinfo reflection)
---------------------------

7.22.8.1 Overview
.................

Routines to generare ‘stexi’ documentation for objects and modules.

   Note that in this context, an “object” is just a value associated
with a location.  It has nothing to do with GOOPS.

7.22.8.2 Usage
..............

 -- Function: module-stexi-documentation sym-name [%docs-resolver]
          [#:docs-resolver]
     Return documentation for the module named SYM-NAME.  The
     documentation will be formatted as ‘stexi’ (*note texinfo:
     texinfo.).

 -- Function: script-stexi-documentation scriptpath
     Return documentation for given script.  The documentation will be
     taken from the script’s commentary, and will be returned in the
     ‘stexi’ format (*note texinfo: texinfo.).

 -- Function: object-stexi-documentation _ [_] [#:force]

 -- Function: package-stexi-standard-copying name version updated years
          copyright-holder permissions
     Create a standard texinfo ‘copying’ section.

     YEARS is a list of years (as integers) in which the modules being
     documented were released.  All other arguments are strings.

 -- Function: package-stexi-standard-titlepage name version updated
          authors
     Create a standard GNU title page.

     AUTHORS is a list of ‘(NAME . EMAIL)’ pairs.  All other arguments
     are strings.

     Here is an example of the usage of this procedure:

           (package-stexi-standard-titlepage
            "Foolib"
            "3.2"
            "26 September 2006"
            '(("Alyssa P Hacker" . "alyssa@example.com"))
            '(2004 2005 2006)
            "Free Software Foundation, Inc."
            "Standard GPL permissions blurb goes here")

 -- Function: package-stexi-generic-menu name entries
     Create a menu from a generic alist of entries, the car of which
     should be the node name, and the cdr the description.  As an
     exception, an entry of ‘#f’ will produce a separator.

 -- Function: package-stexi-standard-menu name modules
          module-descriptions extra-entries
     Create a standard top node and menu, suitable for processing by
     makeinfo.

 -- Function: package-stexi-extended-menu name module-pairs script-pairs
          extra-entries
     Create an "extended" menu, like the standard menu but with a
     section for scripts.

 -- Function: package-stexi-standard-prologue name filename category
          description copying titlepage menu
     Create a standard prologue, suitable for later serialization to
     texinfo and .info creation with makeinfo.

     Returns a list of stexinfo forms suitable for passing to
     ‘package-stexi-documentation’ as the prologue.  *Note texinfo
     reflection package-stexi-documentation::, *note
     package-stexi-standard-titlepage: texinfo reflection
     package-stexi-standard-titlepage, *note
     package-stexi-standard-copying: texinfo reflection
     package-stexi-standard-copying, and *note
     package-stexi-standard-menu: texinfo reflection
     package-stexi-standard-menu.

 -- Function: package-stexi-documentation modules name filename prologue
          epilogue [#:module-stexi-documentation-args] [#:scripts]
     Create stexi documentation for a “package”, where a package is a
     set of modules that is released together.

     MODULES is expected to be a list of module names, where a module
     name is a list of symbols.  The stexi that is returned will be
     titled NAME and a texinfo filename of FILENAME.

     PROLOGUE and EPILOGUE are lists of stexi forms that will be spliced
     into the output document before and after the generated modules
     documentation, respectively.  *Note texinfo reflection
     package-stexi-standard-prologue::, to create a conventional GNU
     texinfo prologue.

     MODULE-STEXI-DOCUMENTATION-ARGS is an optional argument that, if
     given, will be added to the argument list when
     ‘module-texi-documentation’ is called.  For example, it might be
     useful to define a ‘#:docs-resolver’ argument.

 -- Function: package-stexi-documentation-for-include modules
          module-descriptions [#:module-stexi-documentation-args]
     Create stexi documentation for a “package”, where a package is a
     set of modules that is released together.

     MODULES is expected to be a list of module names, where a module
     name is a list of symbols.  Returns an stexinfo fragment.

     Unlike ‘package-stexi-documentation’, this function simply produces
     a menu and the module documentations instead of producing a full
     texinfo document.  This can be useful if you write part of your
     manual by hand, and just use ‘@include’ to pull in the
     automatically generated parts.

     MODULE-STEXI-DOCUMENTATION-ARGS is an optional argument that, if
     given, will be added to the argument list when
     ‘module-texi-documentation’ is called.  For example, it might be
     useful to define a ‘#:docs-resolver’ argument.


File: guile.info,  Node: GOOPS,  Next: Guile Implementation,  Prev: Guile Modules,  Up: Top

8 GOOPS
*******

GOOPS is the “Guile Object Oriented Programming System”.  Its
implementation is derived from STk-3.99.3 by Erick Gallesio and version
1.3 of Gregor Kiczales’ ‘Tiny-Clos’.  It is very close in spirit to
CLOS, the Common Lisp Object System, but is adapted for the Scheme
language.

   GOOPS is a full object oriented system, with classes, objects,
multiple inheritance, and generic functions with multi-method dispatch.
Furthermore its implementation relies on a meta object protocol — which
means that GOOPS’s core operations are themselves defined as methods on
relevant classes, and can be customised by overriding or redefining
those methods.

   To start using GOOPS you first need to import the ‘(oop goops)’
module.  You can do this at the Guile REPL by evaluating:

     (use-modules (oop goops))

* Menu:

* Copyright Notice::
* Class Definition::
* Instance Creation::
* Slot Options::
* Slot Description Example::
* Methods and Generic Functions::
* Inheritance::
* Introspection::
* GOOPS Error Handling::
* GOOPS Object Miscellany::
* The Metaobject Protocol::
* Redefining a Class::
* Changing the Class of an Instance::


File: guile.info,  Node: Copyright Notice,  Next: Class Definition,  Up: GOOPS

8.1 Copyright Notice
====================

The material in this chapter is partly derived from the STk Reference
Manual written by Erick Gallesio, whose copyright notice is as follows.

   Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
Permission to use, copy, modify, distribute,and license this software
and its documentation for any purpose is hereby granted, provided that
existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions.  No written agreement,
license, or royalty fee is required for any of the authorized uses.
This software is provided “AS IS” without express or implied warranty.

   The material has been adapted for use in Guile, with the author’s
permission.


File: guile.info,  Node: Class Definition,  Next: Instance Creation,  Prev: Copyright Notice,  Up: GOOPS

8.2 Class Definition
====================

A new class is defined with the ‘define-class’ syntax:

     (define-class CLASS (SUPERCLASS ...)
        SLOT-DESCRIPTION ...
        CLASS-OPTION ...)

   CLASS is the class being defined.  The list of SUPERCLASSes specifies
which existing classes, if any, to inherit slots and properties from.
“Slots” hold per-instance(1) data, for instances of that class — like
“fields” or “member variables” in other object oriented systems.  Each
SLOT-DESCRIPTION gives the name of a slot and optionally some
“properties” of this slot; for example its initial value, the name of a
function which will access its value, and so on.  Class options, slot
descriptions and inheritance are discussed more below.

 -- syntax: define-class name (super ...) slot-definition ...
          class-option ...
     Define a class called NAME that inherits from SUPERs, with direct
     slots defined by SLOT-DEFINITIONs and CLASS-OPTIONs.  The newly
     created class is bound to the variable name NAME in the current
     environment.

     Each SLOT-DEFINITION is either a symbol that names the slot or a
     list,

          (SLOT-NAME-SYMBOL . SLOT-OPTIONS)

     where SLOT-NAME-SYMBOL is a symbol and SLOT-OPTIONS is a list with
     an even number of elements.  The even-numbered elements of
     SLOT-OPTIONS (counting from zero) are slot option keywords; the
     odd-numbered elements are the corresponding values for those
     keywords.

     Each CLASS-OPTION is an option keyword and corresponding value.

   As an example, let us define a type for representing a complex number
in terms of two real numbers.(2)  This can be done with the following
class definition:

     (define-class <my-complex> (<number>)
        r i)

   This binds the variable ‘<my-complex>’ to a new class whose instances
will contain two slots.  These slots are called ‘r’ and ‘i’ and will
hold the real and imaginary parts of a complex number.  Note that this
class inherits from ‘<number>’, which is a predefined class.(3)

   Slot options are described in the next section.  The possible class
options are as follows.

 -- class option: #:metaclass metaclass
     The ‘#:metaclass’ class option specifies the metaclass of the class
     being defined.  METACLASS must be a class that inherits from
     ‘<class>’.  For the use of metaclasses, see *note Metaobjects and
     the Metaobject Protocol:: and *note Metaclasses::.

     If the ‘#:metaclass’ option is absent, GOOPS reuses or constructs a
     metaclass for the new class by calling ‘ensure-metaclass’ (*note
     ensure-metaclass: Class Definition Protocol.).

 -- class option: #:name name
     The ‘#:name’ class option specifies the new class’s name.  This
     name is used to identify the class whenever related objects - the
     class itself, its instances and its subclasses - are printed.

     If the ‘#:name’ option is absent, GOOPS uses the first argument to
     ‘define-class’ as the class name.

   ---------- Footnotes ----------

   (1) Usually — but see also the ‘#:allocation’ slot option.

   (2) Of course Guile already provides complex numbers, and ‘<complex>’
is in fact a predefined class in GOOPS; but the definition here is still
useful as an example.

   (3) ‘<number>’ is the direct superclass of the predefined class
‘<complex>’; ‘<complex>’ is the superclass of ‘<real>’, and ‘<real>’ is
the superclass of ‘<integer>’.


File: guile.info,  Node: Instance Creation,  Next: Slot Options,  Prev: Class Definition,  Up: GOOPS

8.3 Instance Creation and Slot Access
=====================================

An instance (or object) of a defined class can be created with ‘make’.
‘make’ takes one mandatory parameter, which is the class of the instance
to create, and a list of optional arguments that will be used to
initialize the slots of the new instance.  For instance the following
form

     (define c (make <my-complex>))

creates a new ‘<my-complex>’ object and binds it to the Scheme variable
‘c’.

 -- generic: make
 -- method: make (class <class>) initarg ...
     Create and return a new instance of class CLASS, initialized using
     INITARG ....

     In theory, INITARG ... can have any structure that is understood by
     whatever methods get applied when the ‘initialize’ generic function
     is applied to the newly allocated instance.

     In practice, specialized ‘initialize’ methods would normally call
     ‘(next-method)’ (*note Next-method::), and so eventually the
     standard GOOPS ‘initialize’ methods are applied.  These methods
     expect INITARGS to be a list with an even number of elements, where
     even-numbered elements (counting from zero) are keywords and
     odd-numbered elements are the corresponding values.

     GOOPS processes initialization argument keywords automatically for
     slots whose definition includes the ‘#:init-keyword’ option (*note
     init-keyword: Slot Options.).  Other keyword value pairs can only
     be processed by an ‘initialize’ method that is specialized for the
     new instance’s class.  Any unprocessed keyword value pairs are
     ignored.

 -- generic: make-instance
 -- method: make-instance (class <class>) initarg ...
     ‘make-instance’ is an alias for ‘make’.

   The slots of the new complex number can be accessed using ‘slot-ref’
and ‘slot-set!’.  ‘slot-set!’ sets the value of an object slot and
‘slot-ref’ retrieves it.

     (slot-set! c 'r 10)
     (slot-set! c 'i 3)
     (slot-ref c 'r) ⇒ 10
     (slot-ref c 'i) ⇒ 3

   The ‘(oop goops describe)’ module provides a ‘describe’ function that
is useful for seeing all the slots of an object; it prints the slots and
their values to standard output.

     (describe c)
     ⊣
     #<<my-complex> 401d8638> is an instance of class <my-complex>
     Slots are:
          r = 10
          i = 3


File: guile.info,  Node: Slot Options,  Next: Slot Description Example,  Prev: Instance Creation,  Up: GOOPS

8.4 Slot Options
================

When specifying a slot (in a ‘(define-class ...)’ form), various options
can be specified in addition to the slot’s name.  Each option is
specified by a keyword.  The list of possible keywords is as follows.

 -- slot option: #:init-value init-value
 -- slot option: #:init-form init-form
 -- slot option: #:init-thunk init-thunk
 -- slot option: #:init-keyword init-keyword
     These options provide various ways to specify how to initialize the
     slot’s value at instance creation time.

     INIT-VALUE specifies a fixed initial slot value (shared across all
     new instances of the class).

     INIT-THUNK specifies a thunk that will provide a default value for
     the slot.  The thunk is called when a new instance is created and
     should return the desired initial slot value.

     INIT-FORM specifies a form that, when evaluated, will return an
     initial value for the slot.  The form is evaluated each time that
     an instance of the class is created, in the lexical environment of
     the containing ‘define-class’ expression.

     INIT-KEYWORD specifies a keyword that can be used to pass an
     initial slot value to ‘make’ when creating a new instance.

     Note that, since an ‘init-value’ value is shared across all
     instances of a class, you should only use it when the initial value
     is an immutable value, like a constant.  If you want to initialize
     a slot with a fresh, independently mutable value, you should use
     ‘init-thunk’ or ‘init-form’ instead.  Consider the following
     example.

          (define-class <chbouib> ()
            (hashtab #:init-value (make-hash-table)))

     Here only one hash table is created and all instances of
     ‘<chbouib>’ have their ‘hashtab’ slot refer to it.  In order to
     have each instance of ‘<chbouib>’ refer to a new hash table, you
     should instead write:

          (define-class <chbouib> ()
            (hashtab #:init-thunk make-hash-table))

     or:

          (define-class <chbouib> ()
            (hashtab #:init-form (make-hash-table)))

     If more than one of these options is specified for the same slot,
     the order of precedence, highest first is

        • ‘#:init-keyword’, if INIT-KEYWORD is present in the options
          passed to ‘make’

        • ‘#:init-thunk’, ‘#:init-form’ or ‘#:init-value’.

     If the slot definition contains more than one initialization option
     of the same precedence, the later ones are ignored.  If a slot is
     not initialized at all, its value is unbound.

     In general, slots that are shared between more than one instance
     are only initialized at new instance creation time if the slot
     value is unbound at that time.  However, if the new instance
     creation specifies a valid init keyword and value for a shared
     slot, the slot is re-initialized regardless of its previous value.

     Note, however, that the power of GOOPS’ metaobject protocol means
     that everything written here may be customized or overridden for
     particular classes!  The slot initializations described here are
     performed by the least specialized method of the generic function
     ‘initialize’, whose signature is

          (define-method (initialize (object <object>) initargs) ...)

     The initialization of instances of any given class can be
     customized by defining a ‘initialize’ method that is specialized
     for that class, and the author of the specialized method may decide
     to call ‘next-method’ - which will result in a call to the next
     less specialized ‘initialize’ method - at any point within the
     specialized code, or maybe not at all.  In general, therefore, the
     initialization mechanisms described here may be modified or
     overridden by more specialized code, or may not be supported at all
     for particular classes.

 -- slot option: #:getter getter
 -- slot option: #:setter setter
 -- slot option: #:accessor accessor
     Given an object OBJ with slots named ‘foo’ and ‘bar’, it is always
     possible to read and write those slots by calling ‘slot-ref’ and
     ‘slot-set!’ with the relevant slot name; for example:

          (slot-ref OBJ 'foo)
          (slot-set! OBJ 'bar 25)

     The ‘#:getter’, ‘#:setter’ and ‘#:accessor’ options, if present,
     tell GOOPS to create generic function and method definitions that
     can be used to get and set the slot value more conveniently.
     GETTER specifies a generic function to which GOOPS will add a
     method for getting the slot value.  SETTER specifies a generic
     function to which GOOPS will add a method for setting the slot
     value.  ACCESSOR specifies an accessor to which GOOPS will add
     methods for both getting and setting the slot value.

     So if a class includes a slot definition like this:

          (c #:getter get-count #:setter set-count #:accessor count)

     GOOPS defines generic function methods such that the slot value can
     be referenced using either the getter or the accessor -

          (let ((current-count (get-count obj))) ...)
          (let ((current-count (count obj))) ...)

     - and set using either the setter or the accessor -

          (set-count obj (+ 1 current-count))
          (set! (count obj) (+ 1 current-count))

     Note that

        • with an accessor, the slot value is set using the generalized
          ‘set!’ syntax

        • in practice, it is unusual for a slot to use all three of
          these options: read-only, write-only and read-write slots
          would typically use only ‘#:getter’, ‘#:setter’ and
          ‘#:accessor’ options respectively.

     The binding of the specified names is done in the environment of
     the ‘define-class’ expression.  If the names are already bound (in
     that environment) to values that cannot be upgraded to generic
     functions, those values are overwritten when the ‘define-class’
     expression is evaluated.  For more detail, see *note
     ensure-generic: Generic Function Internals.

 -- slot option: #:allocation allocation
     The ‘#:allocation’ option tells GOOPS how to allocate storage for
     the slot.  Possible values for ALLOCATION are

        • ‘#:instance’

          Indicates that GOOPS should create separate storage for this
          slot in each new instance of the containing class (and its
          subclasses).  This is the default.

        • ‘#:class’

          Indicates that GOOPS should create storage for this slot that
          is shared by all instances of the containing class (and its
          subclasses).  In other words, a slot in class C with
          allocation ‘#:class’ is shared by all INSTANCEs for which
          ‘(is-a? INSTANCE C)’.  This permits defining a kind of global
          variable which can be accessed only by (in)direct instances of
          the class which defines the slot.

        • ‘#:each-subclass’

          Indicates that GOOPS should create storage for this slot that
          is shared by all _direct_ instances of the containing class,
          and that whenever a subclass of the containing class is
          defined, GOOPS should create a new storage for the slot that
          is shared by all _direct_ instances of the subclass.  In other
          words, a slot with allocation ‘#:each-subclass’ is shared by
          all instances with the same ‘class-of’.

        • ‘#:virtual’

          Indicates that GOOPS should not allocate storage for this
          slot.  The slot definition must also include the ‘#:slot-ref’
          and ‘#:slot-set!’ options to specify how to reference and set
          the value for this slot.  See the example below.

     Slot allocation options are processed when defining a new class by
     the generic function ‘compute-get-n-set’, which is specialized by
     the class’s metaclass.  Hence new types of slot allocation can be
     implemented by defining a new metaclass and a method for
     ‘compute-get-n-set’ that is specialized for the new metaclass.  For
     an example of how to do this, see *note Customizing Class
     Definition::.

 -- slot option: #:slot-ref getter
 -- slot option: #:slot-set! setter
     The ‘#:slot-ref’ and ‘#:slot-set!’ options must be specified if the
     slot allocation is ‘#:virtual’, and are ignored otherwise.

     GETTER should be a closure taking a single INSTANCE parameter that
     returns the current slot value.  SETTER should be a closure taking
     two parameters - INSTANCE and NEW-VAL - that sets the slot value to
     NEW-VAL.


File: guile.info,  Node: Slot Description Example,  Next: Methods and Generic Functions,  Prev: Slot Options,  Up: GOOPS

8.5 Illustrating Slot Description
=================================

To illustrate slot description, we can redefine the ‘<my-complex>’ class
seen before.  A definition could be:

     (define-class <my-complex> (<number>)
        (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r)
        (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i))

With this definition, the ‘r’ and ‘i’ slots are set to 0 by default, and
can be initialised to other values by calling ‘make’ with the ‘#:r’ and
‘#:i’ keywords.  Also the generic functions ‘get-r’, ‘set-r!’, ‘get-i’
and ‘set-i!’ are automatically defined to read and write the slots.

     (define c1 (make <my-complex> #:r 1 #:i 2))
     (get-r c1) ⇒ 1
     (set-r! c1 12)
     (get-r c1) ⇒ 12
     (define c2 (make <my-complex> #:r 2))
     (get-r c2) ⇒ 2
     (get-i c2) ⇒ 0

   Accessors can both read and write a slot.  So, another definition of
the ‘<my-complex>’ class, using the ‘#:accessor’ option, could be:

     (define-class <my-complex> (<number>)
        (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
        (i #:init-value 0 #:accessor imag-part #:init-keyword #:i))

With this definition, the ‘r’ slot can be read with:
     (real-part c)
and set with:
     (set! (real-part c) new-value)

   Suppose now that we want to manipulate complex numbers with both
rectangular and polar coordinates.  One solution could be to have a
definition of complex numbers which uses one particular representation
and some conversion functions to pass from one representation to the
other.  A better solution is to use virtual slots, like this:

     (define-class <my-complex> (<number>)
        ;; True slots use rectangular coordinates
        (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
        (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)
        ;; Virtual slots access do the conversion
        (m #:accessor magnitude #:init-keyword #:magn
           #:allocation #:virtual
           #:slot-ref (lambda (o)
                       (let ((r (slot-ref o 'r)) (i (slot-ref o 'i)))
                         (sqrt (+ (* r r) (* i i)))))
           #:slot-set! (lambda (o m)
                         (let ((a (slot-ref o 'a)))
                           (slot-set! o 'r (* m (cos a)))
                           (slot-set! o 'i (* m (sin a))))))
        (a #:accessor angle #:init-keyword #:angle
           #:allocation #:virtual
           #:slot-ref (lambda (o)
                       (atan (slot-ref o 'i) (slot-ref o 'r)))
           #:slot-set! (lambda(o a)
                        (let ((m (slot-ref o 'm)))
                           (slot-set! o 'r (* m (cos a)))
                           (slot-set! o 'i (* m (sin a)))))))


   In this class definition, the magnitude ‘m’ and angle ‘a’ slots are
virtual, and are calculated, when referenced, from the normal (i.e.
‘#:allocation #:instance’) slots ‘r’ and ‘i’, by calling the function
defined in the relevant ‘#:slot-ref’ option.  Correspondingly, writing
‘m’ or ‘a’ leads to calling the function defined in the ‘#:slot-set!’
option.  Thus the following expression

     (slot-set! c 'a 3)

permits to set the angle of the ‘c’ complex number.

     (define c (make <my-complex> #:r 12 #:i 20))
     (real-part c) ⇒ 12
     (angle c) ⇒ 1.03037682652431
     (slot-set! c 'i 10)
     (set! (real-part c) 1)
     (describe c)
     ⊣
     #<<my-complex> 401e9b58> is an instance of class <my-complex>
     Slots are:
          r = 1
          i = 10
          m = 10.0498756211209
          a = 1.47112767430373

   Since initialization keywords have been defined for the four slots,
we can now define the standard Scheme primitives ‘make-rectangular’ and
‘make-polar’.

     (define make-rectangular
        (lambda (x y) (make <my-complex> #:r x #:i y)))

     (define make-polar
        (lambda (x y) (make <my-complex> #:magn x #:angle y)))


File: guile.info,  Node: Methods and Generic Functions,  Next: Inheritance,  Prev: Slot Description Example,  Up: GOOPS

8.6 Methods and Generic Functions
=================================

A GOOPS method is like a Scheme procedure except that it is specialized
for a particular set of argument classes, and will only be used when the
actual arguments in a call match the classes in the method definition.

     (define-method (+ (x <string>) (y <string>))
       (string-append x y))

     (+ "abc" "de") ⇒ "abcde"

   A method is not formally associated with any single class (as it is
in many other object oriented languages), because a method can be
specialized for a combination of several classes.  If you’ve studied
object orientation in non-Lispy languages, you may remember discussions
such as whether a method to stretch a graphical image around a surface
should be a method of the image class, with a surface as a parameter, or
a method of the surface class, with an image as a parameter.  In GOOPS
you’d just write

     (define-method (stretch (im <image>) (sf <surface>))
       ...)

and the question of which class the method is more associated with does
not need answering.

   There can simultaneously be several methods with the same name but
different sets of specializing argument classes; for example:

     (define-method (+ (x <string>) (y <string)) ...)
     (define-method (+ (x <matrix>) (y <matrix>)) ...)
     (define-method (+ (f <fish>) (b <bicycle>)) ...)
     (define-method (+ (a <foo>) (b <bar>) (c <baz>)) ...)

A generic function is a container for the set of such methods that a
program intends to use.

   If you look at a program’s source code, and see ‘(+ x y)’ somewhere
in it, conceptually what is happening is that the program at that point
calls a generic function (in this case, the generic function bound to
the identifier ‘+’).  When that happens, Guile works out which of the
generic function’s methods is the most appropriate for the arguments
that the function is being called with; then it evaluates the method’s
code with the arguments as formal parameters.  This happens every time
that a generic function call is evaluated — it isn’t assumed that a
given source code call will end up invoking the same method every time.

   Defining an identifier as a generic function is done with the
‘define-generic’ macro.  Definition of a new method is done with the
‘define-method’ macro.  Note that ‘define-method’ automatically does a
‘define-generic’ if the identifier concerned is not already a generic
function, so often an explicit ‘define-generic’ call is not needed.

 -- syntax: define-generic symbol
     Create a generic function with name SYMBOL and bind it to the
     variable SYMBOL.  If SYMBOL was previously bound to a Scheme
     procedure (or procedure-with-setter), the old procedure (and
     setter) is incorporated into the new generic function as its
     default procedure (and setter).  Any other previous value,
     including an existing generic function, is discarded and replaced
     by a new, empty generic function.

 -- syntax: define-method (generic parameter ...) body ...
     Define a method for the generic function or accessor GENERIC with
     parameters PARAMETERs and body BODY ....

     GENERIC is a generic function.  If GENERIC is a variable which is
     not yet bound to a generic function object, the expansion of
     ‘define-method’ will include a call to ‘define-generic’.  If
     GENERIC is ‘(setter GENERIC-WITH-SETTER)’, where
     GENERIC-WITH-SETTER is a variable which is not yet bound to a
     generic-with-setter object, the expansion will include a call to
     ‘define-accessor’.

     Each PARAMETER must be either a symbol or a two-element list
     ‘(SYMBOL CLASS)’.  The symbols refer to variables in the body forms
     that will be bound to the parameters supplied by the caller when
     calling this method.  The CLASSes, if present, specify the possible
     combinations of parameters to which this method can be applied.

     BODY ... are the bodies of the method definition.

   ‘define-method’ expressions look a little like Scheme procedure
definitions of the form

     (define (name formals ...) . body)

   The important difference is that each formal parameter, apart from
the possible “rest” argument, can be qualified by a class name: ‘FORMAL’
becomes ‘(FORMAL CLASS)’.  The meaning of this qualification is that the
method being defined will only be applicable in a particular generic
function invocation if the corresponding argument is an instance of
‘CLASS’ (or one of its subclasses).  If more than one of the formal
parameters is qualified in this way, then the method will only be
applicable if each of the corresponding arguments is an instance of its
respective qualifying class.

   Note that unqualified formal parameters act as though they are
qualified by the class ‘<top>’, which GOOPS uses to mean the superclass
of all valid Scheme types, including both primitive types and GOOPS
classes.

   For example, if a generic function method is defined with PARAMETERs
‘(s1 <square>)’ and ‘(n <number>)’, that method is only applicable to
invocations of its generic function that have two parameters where the
first parameter is an instance of the ‘<square>’ class and the second
parameter is a number.

* Menu:

* Accessors::
* Extending Primitives::
* Merging Generics::
* Next-method::
* method* and define-method*::           Advanced argument handling
* Generic Function and Method Examples::
* Handling Invocation Errors::


File: guile.info,  Node: Accessors,  Next: Extending Primitives,  Up: Methods and Generic Functions

8.6.1 Accessors
---------------

An accessor is a generic function that can also be used with the
generalized ‘set!’ syntax (*note Procedures with Setters::).  Guile will
handle a call like

     (set! (accessor args...) value)

by calling the most specialized method of ‘accessor’ that matches the
classes of ‘args’ and ‘value’.  ‘define-accessor’ is used to bind an
identifier to an accessor.

 -- syntax: define-accessor symbol
     Create an accessor with name SYMBOL and bind it to the variable
     SYMBOL.  If SYMBOL was previously bound to a Scheme procedure (or
     procedure-with-setter), the old procedure (and setter) is
     incorporated into the new accessor as its default procedure (and
     setter).  Any other previous value, including an existing generic
     function or accessor, is discarded and replaced by a new, empty
     accessor.


File: guile.info,  Node: Extending Primitives,  Next: Merging Generics,  Prev: Accessors,  Up: Methods and Generic Functions

8.6.2 Extending Primitives
--------------------------

Many of Guile’s primitive procedures can be extended by giving them a
generic function definition that operates in conjunction with their
normal C-coded implementation.  When a primitive is extended in this
way, it behaves like a generic function with the C-coded implementation
as its default method.

   This extension happens automatically if a method is defined (by a
‘define-method’ call) for a variable whose current value is a primitive.
But it can also be forced by calling ‘enable-primitive-generic!’.

 -- primitive procedure: enable-primitive-generic! primitive
     Force the creation of a generic function definition for PRIMITIVE.

   Once the generic function definition for a primitive has been
created, it can be retrieved using ‘primitive-generic-generic’.

 -- primitive procedure: primitive-generic-generic primitive
     Return the generic function definition of PRIMITIVE.

     ‘primitive-generic-generic’ raises an error if PRIMITIVE is not a
     primitive with generic capability.


File: guile.info,  Node: Merging Generics,  Next: Next-method,  Prev: Extending Primitives,  Up: Methods and Generic Functions

8.6.3 Merging Generics
----------------------

GOOPS generic functions and accessors often have short, generic names.
For example, if a vector package provides an accessor for the X
coordinate of a vector, that accessor may just be called ‘x’.  It
doesn’t need to be called, for example, ‘vector:x’, because GOOPS will
work out, when it sees code like ‘(x OBJ)’, that the vector-specific
method of ‘x’ should be called if OBJ is a vector.

   That raises the question, though, of what happens when different
packages define a generic function with the same name.  Suppose we work
with a graphical package which needs to use two independent vector
packages for 2D and 3D vectors respectively.  If both packages export
‘x’, what does the code using those packages end up with?

   *note duplicate binding handlers: Creating Guile Modules. explains
how this is resolved for conflicting bindings in general.  For generics,
there is a special duplicates handler, ‘merge-generics’, which tells the
module system to merge generic functions with the same name.  Here is an
example:

     (define-module (math 2D-vectors)
       #:use-module (oop goops)
       #:export (x y ...))

     (define-module (math 3D-vectors)
       #:use-module (oop goops)
       #:export (x y z ...))

     (define-module (my-module)
       #:use-module (oop goops)
       #:use-module (math 2D-vectors)
       #:use-module (math 3D-vectors)
       #:duplicates (merge-generics))

   The generic function ‘x’ in ‘(my-module)’ will now incorporate all of
the methods of ‘x’ from both imported modules.

   To be precise, there will now be three distinct generic functions
named ‘x’: ‘x’ in ‘(math 2D-vectors)’, ‘x’ in ‘(math 3D-vectors)’, and
‘x’ in ‘(my-module)’; and these functions share their methods in an
interesting and dynamic way.

   To explain, let’s call the imported generic functions (in ‘(math
2D-vectors)’ and ‘(math 3D-vectors)’) the “ancestors”, and the merged
generic function (in ‘(my-module)’), the “descendant”.  The general rule
is that for any generic function G, the applicable methods are selected
from the union of the methods of G’s descendant functions, the methods
of G itself and the methods of G’s ancestor functions.

   Thus ancestor functions effectively share methods with their
descendants, and vice versa.  In the example above, ‘x’ in ‘(math
2D-vectors)’ will share the methods of ‘x’ in ‘(my-module)’ and vice
versa.(1)  Sharing is dynamic, so adding another new method to a
descendant implies adding it to that descendant’s ancestors too.

   ---------- Footnotes ----------

   (1) But note that ‘x’ in ‘(math 2D-vectors)’ doesn’t share methods
with ‘x’ in ‘(math 3D-vectors)’, so modularity is still preserved.


File: guile.info,  Node: Next-method,  Next: method* and define-method*,  Prev: Merging Generics,  Up: Methods and Generic Functions

8.6.4 Next-method
-----------------

When you call a generic function, with a particular set of arguments,
GOOPS builds a list of all the methods that are applicable to those
arguments and orders them by how closely the method definitions match
the actual argument types.  It then calls the method at the top of this
list.  If the selected method’s code wants to call on to the next method
in this list, it can do so by using ‘next-method’.

     (define-method (test (a <integer>)) (cons 'integer (next-method)))
     (define-method (test (a <number>))  (cons 'number  (next-method)))
     (define-method (test a)             (list 'top))

   With these definitions,

     (test 1)   ⇒ (integer number top)
     (test 1.0) ⇒ (number top)
     (test #t)  ⇒ (top)

   ‘next-method’ can be called as just ‘(next-method)’.  The arguments
for the next method call are then implicit, and the same as for the
original method call.

   If you want to call on to a method with the same name but with a
different set of arguments (as you might with overloaded methods in C++,
for example), you can pass custom arguments to ‘next-method’:

     (define-method (test (a <number>) min max)
       (if (and (>= a min) (<= a max))
           (display "Number is in range\n"))
       (next-method a))

     (test 2 1 10)
     ⊣
     Number is in range
     ⇒
     (integer number top)


File: guile.info,  Node: method* and define-method*,  Next: Generic Function and Method Examples,  Prev: Next-method,  Up: Methods and Generic Functions

8.6.5 method* and define-method*
--------------------------------

‘method*’ and ‘define-method*’ are the GOOPS versions of ‘lambda*’ and
‘define*’.

 -- syntax: method* ([param...]
          [#:optional vardef...]
          [#:key vardef... [#:allow-other-keys]]
          [#:rest var | . var])
          body1 body2 ...

     Create a method which takes optional and/or keyword arguments
     specified with ‘#:optional’ and ‘#:key’.  *Note lambda* and
     define*::.  PARAM... are ordinary method parameters as for ‘method’
     and ‘define-method’, i.e. either VAR or (VAR TYPESPEC).

     ‘define-method*’ is syntactic sugar for defining methods using
     ‘method*’.  For example,

          (define-method* (foo (a <integer>) b #:optional c
                               #:key (d 2) e
                               #:rest f)
            (list a b c d e f))

     is a method with fixed arguments A of type ‘<integer>’ and B of
     type ‘<top>’, optional argument C, keyword arguments D, with
     default value 2, and E, and rest argument F.  A call

          (foo 1 'x #:d 3 'y)

     will return

          (1 x #f 3 #f (#:d 3 y))

     The values for C and E are ‘#f’ since they have not been given in
     the call.  The given keyword argument(s) are included in the rest
     argument, as for ‘define*’.

* Menu:

* Advanced argument handling in method and define-method::
* Type dispatch and redefinition for advanced argument handling::
* next-method call in method*::
* Advanced argument handling design choices::


File: guile.info,  Node: Advanced argument handling in method and define-method,  Next: Type dispatch and redefinition for advanced argument handling,  Up: method* and define-method*

8.6.5.1 Advanced argument handling in method and define-method
..............................................................

Some users may find it more natural not to have to choose between
‘define-method’ and ‘define-method*’ in their code.

   It turns out that ‘method*’ and ‘define-method*’ can do just fine
also for ordinary methods without keyword formals.  They take marginally
longer to compile but result in the same code as ‘method’ and
‘define-method’ if keyword formals are absent.

   For this reason, we provide a module (oop goops keyword-formals)
which replaces the standard ‘method’ and ‘define-method’ bindings with
their keyword formal counterparts.  It can be used like this:

     (use-modules (oop goops) (oop goops keyword-formals))

   or

     (define-module (foo)
       #:use-module (oop goops)
       #:use-module (oop goops keyword-formals))


File: guile.info,  Node: Type dispatch and redefinition for advanced argument handling,  Next: next-method call in method*,  Prev: Advanced argument handling in method and define-method,  Up: method* and define-method*

8.6.5.2 Type dispatch and redefinition for advanced argument handling
.....................................................................

As in CLOS, GOOPS only does type dispatch on required arguments, also
for method*.  For a ‘method*’ with keyword formals, the list of
specializers becomes the same as for a corresponding ‘method’ with the
same number of required arguments and a tail/rest argument.  For
example, the list of specializers for

     (define-method* (foo (a <integer>) b #:optional c #:key d)
       ...)

   becomes

     (<integer> <top> . <top>)

   This means that ‘(method (a <integer>) b) ...)’ is more specialized
than ‘(method (a <integer>) b #:optional c #:key d) ...)’ and will come
before the latter in the list of applicable methods.

   Two methods of the same generic function can’t have the same
specializers list.  This means that if we do

     (define-method* (foo (a <integer>) b #:optional c)
      ...)
     (define-method* (foo (a <integer>) b . rest)
      ...)

   the second ‘define-method*’ will cause a redefinition such that the
second method will replace the first.


File: guile.info,  Node: next-method call in method*,  Next: Advanced argument handling design choices,  Prev: Type dispatch and redefinition for advanced argument handling,  Up: method* and define-method*

8.6.5.3 next-method call in method*
...................................

A ‘(next-method)’ call in a ‘method*’ will pass on all required,
optional and rest arguments in the list of formals to the next less
specialized method in the list of applicable methods, as well as any
actual keyword arguments passed in the call to the ‘method*’.

   This has the following consequences for default values:

  1. A an optional argument will shadow default values for optional
     arguments in the same position in less specialized methods.  For
     example if <B> is a subclass of <A> and B an instance of <B>,

          (define-method* (foo (obj <A>) #:optional (c 1)) c)
          (define-method* (foo (obj <B>) #:optional c)) (next-method))
          (foo b) ⇒ #f

     The reason for this is that C will obtain the value ‘#f’ already in
     the call to the second (most specialized, called first) method, and
     this value will be passed on by the ‘(next-method)’ call.

  2. A keyword argument will not shadow a default value for the same
     keyword argument in less specialized methods.  Example:

          (define-method* (foo (obj <A>) #:key (c 1)) c)
          (define-method* (foo (obj <B>) #:key c)) (next-method))
          (foo b) ⇒ 1

     The reason for this is that the first (less specialized, called
     last) method will not be passed any keyword arguments from the
     call.  In particular, it won’t be passed ‘#:c VAL’, and it will
     therefore use its default value.

   The user can pass arguments to ‘next-method’ to customize the
behavior.  In particular, if the current method uses advanced argument
handling in such a way that it has keywords in its list of formals and
the next, less specialized, method is an ordinary ‘method’, it will be
necessary to pass arguments explicitly to ‘next-method’ to “filter out”
any keywords.


File: guile.info,  Node: Advanced argument handling design choices,  Prev: next-method call in method*,  Up: method* and define-method*

8.6.5.4 Advanced argument handling design choices
.................................................

There are two design choices with regard to advanced argument handling
in GOOPS methods which are worth explaining.

   First, there was the choice whether to add this functionality to
‘method’ and ‘define-method’ proper or to introduce new syntax ‘method*’
and ‘define-method*’.

   There are several reasons why it could be better not to introduce new
syntax.  It would give a simpler API, with less cognitive load for the
user, and a slightly simpler implementation (compared to providing the
new syntax as well).  It would align with the CLOS design choice where
‘defmethod’ does support advanced argument handling.

   Eventually, we decided to introduce new syntax instead of extending
the old for the following reasons:

  1. It aligns with ‘lambda*’ and ‘define*’.
  2. It is somewhat better at protecting backward compatibility.
  3. It preserves the conceptual simplicity of ‘method’ and
     ‘define-method’.
  4. It makes it easier for other implementations (like guile-hoot) to
     choose to only provide the simpler functionality (through ‘method’
     and ‘define-method’).

   However, note that users who prefer to only use ‘define-method’ can
do so.  *Note Advanced argument handling in method and define-method::.

   Second, we have chosen not to do type dispatch on optional or keyword
arguments.  Reasons include:

  1. It strikes a reasonable balance with regards to the complexity of
     implementation (and cognitive load for the user).
  2. It aligns with the CLOS implementation which also likely had good
     reasons for this choice.
  3. Currently, we don’t have clear ideas about a conceptual framework
     of rules governing type dispatch for advanced argument handling or
     how this would be implemented.


File: guile.info,  Node: Generic Function and Method Examples,  Next: Handling Invocation Errors,  Prev: method* and define-method*,  Up: Methods and Generic Functions

8.6.6 Generic Function and Method Examples
------------------------------------------

Consider the following definitions:

     (define-generic G)
     (define-method (G (a <integer>) b) 'integer)
     (define-method (G (a <real>) b) 'real)
     (define-method (G a b) 'top)

   The ‘define-generic’ call defines G as a generic function.  The three
next lines define methods for G.  Each method uses a sequence of
“parameter specializers” that specify when the given method is
applicable.  A specializer permits to indicate the class a parameter
must belong to (directly or indirectly) to be applicable.  If no
specializer is given, the system defaults it to ‘<top>’.  Thus, the
first method definition is equivalent to

     (define-method (G (a <integer>) (b <top>)) 'integer)

   Now, let’s look at some possible calls to the generic function G:

     (G 2 3)    ⇒ integer
     (G 2 #t)   ⇒ integer
     (G 1.2 'a) ⇒ real
     (G #t #f)  ⇒ top
     (G 1 2 3)  ⇒ error (since no method exists for 3 parameters)

   The methods above use only one specializer per parameter list.  But
in general, any or all of a method’s parameters may be specialized.
Suppose we define now:

     (define-method (G (a <integer>) (b <number>))  'integer-number)
     (define-method (G (a <integer>) (b <real>))    'integer-real)
     (define-method (G (a <integer>) (b <integer>)) 'integer-integer)
     (define-method (G a (b <number>))              'top-number)

With these definitions:

     (G 1 2)   ⇒ integer-integer
     (G 1 1.0) ⇒ integer-real
     (G 1 #t)  ⇒ integer
     (G 'a 1)  ⇒ top-number

   As a further example we shall continue to define operations on the
‘<my-complex>’ class.  Suppose that we want to use it to implement
complex numbers completely.  For instance a definition for the addition
of two complex numbers could be

     (define-method (new-+ (a <my-complex>) (b <my-complex>))
       (make-rectangular (+ (real-part a) (real-part b))
                         (+ (imag-part a) (imag-part b))))

   To be sure that the ‘+’ used in the method ‘new-+’ is the standard
addition we can do:

     (define-generic new-+)

     (let ((+ +))
       (define-method (new-+ (a <my-complex>) (b <my-complex>))
         (make-rectangular (+ (real-part a) (real-part b))
                           (+ (imag-part a) (imag-part b)))))

   The ‘define-generic’ ensures here that ‘new-+’ will be defined in the
global environment.  Once this is done, we can add methods to the
generic function ‘new-+’ which make a closure on the ‘+’ symbol.  A
complete writing of the ‘new-+’ methods is shown in *note Figure 8.1:
fig:newplus.

     (define-generic new-+)

     (let ((+ +))

       (define-method (new-+ (a <real>) (b <real>)) (+ a b))

       (define-method (new-+ (a <real>) (b <my-complex>))
         (make-rectangular (+ a (real-part b)) (imag-part b)))

       (define-method (new-+ (a <my-complex>) (b <real>))
         (make-rectangular (+ (real-part a) b) (imag-part a)))

       (define-method (new-+ (a <my-complex>) (b <my-complex>))
         (make-rectangular (+ (real-part a) (real-part b))
                           (+ (imag-part a) (imag-part b))))

       (define-method (new-+ (a <number>))  a)

       (define-method (new-+) 0)

       (define-method (new-+ . args)
         (new-+ (car args)
           (apply new-+ (cdr args)))))

     (set! + new-+)


Figure 8.1: Extending ‘+’ to handle complex numbers

   We take advantage here of the fact that generic function are not
obliged to have a fixed number of parameters.  The four first methods
implement dyadic addition.  The fifth method says that the addition of a
single element is this element itself.  The sixth method says that using
the addition with no parameter always return 0 (as is also true for the
primitive ‘+’).  The last method takes an arbitrary number of
parameters(1).  This method acts as a kind of ‘reduce’: it calls the
dyadic addition on the _car_ of the list and on the result of applying
it on its rest.  To finish, the ‘set!’ permits to redefine the ‘+’
symbol to our extended addition.

   To conclude our implementation (integration?)  of complex numbers, we
could redefine standard Scheme predicates in the following manner:

     (define-method (complex? c <my-complex>) #t)
     (define-method (complex? c)           #f)

     (define-method (number? n <number>) #t)
     (define-method (number? n)          #f)
     ...

   Standard primitives in which complex numbers are involved could also
be redefined in the same manner.

   ---------- Footnotes ----------

   (1) The parameter list for a ‘define-method’ follows the conventions
used for Scheme procedures.  In particular it can use the dot notation
or a symbol to denote an arbitrary number of parameters


File: guile.info,  Node: Handling Invocation Errors,  Prev: Generic Function and Method Examples,  Up: Methods and Generic Functions

8.6.7 Handling Invocation Errors
--------------------------------

If a generic function is invoked with a combination of parameters for
which there is no applicable method, GOOPS raises an error.

 -- generic: no-method
 -- method: no-method (gf <generic>) args
     When an application invokes a generic function, and no methods at
     all have been defined for that generic function, GOOPS calls the
     ‘no-method’ generic function.  The default method calls
     ‘goops-error’ with an appropriate message.

 -- generic: no-applicable-method
 -- method: no-applicable-method (gf <generic>) args
     When an application applies a generic function to a set of
     arguments, and no methods have been defined for those argument
     types, GOOPS calls the ‘no-applicable-method’ generic function.
     The default method calls ‘goops-error’ with an appropriate message.

 -- generic: no-next-method
 -- method: no-next-method (gf <generic>) args
     When a generic function method calls ‘(next-method)’ to invoke the
     next less specialized method for that generic function, and no less
     specialized methods have been defined for the current generic
     function arguments, GOOPS calls the ‘no-next-method’ generic
     function.  The default method calls ‘goops-error’ with an
     appropriate message.


File: guile.info,  Node: Inheritance,  Next: Introspection,  Prev: Methods and Generic Functions,  Up: GOOPS

8.7 Inheritance
===============

Here are some class definitions to help illustrate inheritance:

     (define-class A () a)
     (define-class B () b)
     (define-class C () c)
     (define-class D (A B) d a)
     (define-class E (A C) e c)
     (define-class F (D E) f)

   ‘A’, ‘B’, ‘C’ have a null list of superclasses.  In this case, the
system will replace the null list by a list which only contains
‘<object>’, the root of all the classes defined by ‘define-class’.  ‘D’,
‘E’, ‘F’ use multiple inheritance: each class inherits from two
previously defined classes.  Those class definitions define a hierarchy
which is shown in *note Figure 8.2: fig:hier.  In this figure, the class
‘<top>’ is also shown; this class is the superclass of all Scheme
objects.  In particular, ‘<top>’ is the superclass of all standard
Scheme types.

          <top>
          / \\\_____________________
         /   \\___________          \
        /     \           \          \
    <object>  <pair>  <procedure>  <number>
    /  |  \                           |
   /   |   \                          |
  A    B    C                      <complex>
  |\__/__   |                         |
   \ /   \ /                          |
    D     E                         <real>
     \   /                            |
       F                              |
                                   <integer>


Figure 8.2: A class hierarchy.

   When a class has superclasses, its set of slots is calculated by
taking the union of its own slots and those of all its superclasses.
Thus each instance of D will have three slots, ‘a’, ‘b’ and ‘d’).  The
slots of a class can be discovered using the ‘class-slots’ primitive.
For instance,

     (class-slots A) ⇒ ((a))
     (class-slots E) ⇒ ((a) (e) (c))
     (class-slots F) ⇒ ((e) (c) (b) (d) (a) (f))

The ordering of the returned slots is not significant.

* Menu:

* Class Precedence List::
* Sorting Methods::
* Inheritance and accessors::


File: guile.info,  Node: Class Precedence List,  Next: Sorting Methods,  Up: Inheritance

8.7.1 Class Precedence List
---------------------------

What happens when a class inherits from two or more superclasses that
have a slot with the same name but incompatible definitions — for
example, different init values or slot allocations?  We need a rule for
deciding which slot definition the derived class ends up with, and this
rule is provided by the class’s “Class Precedence List”.(1)

   Another problem arises when invoking a generic function, and there is
more than one method that could apply to the call arguments.  Here we
need a way of ordering the applicable methods, so that Guile knows which
method to use first, which to use next if that method calls
‘next-method’, and so on.  One of the ingredients for this ordering is
determining, for each given call argument, which of the specializing
classes, from each applicable method’s definition, is the most specific
for that argument; and here again the class precedence list helps.

   If inheritance was restricted such that each class could only have
one superclass — which is known as “single” inheritance — class ordering
would be easy.  The rule would be simply that a subclass is considered
more specific than its superclass.

   With multiple inheritance, ordering is less obvious, and we have to
impose an arbitrary rule to determine precedence.  Suppose we have

     (define-class X ()
        (x #:init-value 1))

     (define-class Y ()
        (x #:init-value 2))

     (define-class Z (X Y)
        (...))

Clearly the ‘Z’ class is more specific than ‘X’ or ‘Y’, for instances of
‘Z’.  But which is more specific out of ‘X’ and ‘Y’ — and hence, for the
definitions above, which ‘#:init-value’ will take effect when creating
an instance of ‘Z’?  The rule in GOOPS is that the superclasses listed
earlier are more specific than those listed later.  Hence ‘X’ is more
specific than ‘Y’, and the ‘#:init-value’ for slot ‘x’ in instances of
‘Z’ will be 1.

   Hence there is a linear ordering for a class and all its
superclasses, from most specific to least specific, and this ordering is
called the Class Precedence List of the class.

   In fact the rules above are not quite enough to always determine a
unique order, but they give an idea of how things work.  For example,
for the ‘F’ class shown in *note Figure 8.2: fig:hier, the class
precedence list is

     (f d e a c b <object> <top>)

In cases where there is any ambiguity (like this one), it is a bad idea
for programmers to rely on exactly what the order is.  If the order for
some superclasses is important, it can be expressed directly in the
class definition.

   The precedence list of a class can be obtained by calling
‘class-precedence-list’.  This function returns a ordered list whose
first element is the most specific class.  For instance:

     (class-precedence-list B) ⇒ (#<<class> B 401b97c8>
                                          #<<class> <object> 401e4a10>
                                          #<<class> <top> 4026a9d8>)

Or for a more immediately readable result:

     (map class-name (class-precedence-list B)) ⇒ (B <object> <top>)

   ---------- Footnotes ----------

   (1) This section is an adaptation of material from Jeff Dalton’s
(J.Dalton@ed.ac.uk) ‘Brief introduction to CLOS’


File: guile.info,  Node: Sorting Methods,  Next: Inheritance and accessors,  Prev: Class Precedence List,  Up: Inheritance

8.7.2 Sorting Methods
---------------------

Now, with the idea of the class precedence list, we can state precisely
how the possible methods are sorted when more than one of the methods of
a generic function are applicable to the call arguments.

   The rules are that
   • the applicable methods are sorted in order of specificity, and the
     most specific method is used first, then the next if that method
     calls ‘next-method’, and so on

   • a method M1 is more specific than another method M2 if the first
     specializing class that differs, between the definitions of M1 and
     M2, is more specific, in M1’s definition, for the corresponding
     actual call argument, than the specializing class in M2’s
     definition

   • a class C1 is more specific than another class C2, for an object of
     actual class C, if C1 comes before C2 in C’s class precedence list.


File: guile.info,  Node: Inheritance and accessors,  Prev: Sorting Methods,  Up: Inheritance

8.7.3 Inheritance and accessors
-------------------------------

When a class <A> defines a getter, setter or accessor for one of its
slots X, an _accessor method_ specialized to class <A> is created.
Accessor methods are special in that they always refer to a concrete
class.  When you subclass <A>, a new accessor method for X is created
automatically, specialized to the subclass:

     (define-class <A> () (x #:accessor x))
     (define-class <B> (<A>))
     (generic-function-methods x)
     ⇒
     (#<<accessor-method> (<B>) 7faa66b5b1c0>
      #<<accessor-method> (<A>) 7faa66b5b240>)

   Note, in particular, that the X accessor method specialized to <A> is
_not_ applicable to objects of class B:

     (define o (make <B>))
     (compute-applicable-methods x (list o))
     ⇒
     (#<<accessor-method> (<B>) 7faa66b5b1c0>)

   As a consequence, an accessor doesn’t have a next-method.  The fact
that accessor methods always apply to concrete classes allows for
extensive optimization.


File: guile.info,  Node: Introspection,  Next: GOOPS Error Handling,  Prev: Inheritance,  Up: GOOPS

8.8 Introspection
=================

“Introspection”, or “reflection”, means being able to obtain information
dynamically about GOOPS objects.  It is perhaps best illustrated by
considering an object oriented language that does not provide any
introspection, namely C++.

   Nothing in C++ allows a running program to obtain answers to the
following types of question:

   • What are the data members of this object or class?

   • What classes does this class inherit from?

   • Is this method call virtual or non-virtual?

   • If I invoke ‘Employee::adjustHoliday()’, what class contains the
     ‘adjustHoliday()’ method that will be applied?

   In C++, answers to such questions can only be determined by looking
at the source code, if you have access to it.  GOOPS, on the other hand,
includes procedures that allow answers to these questions — or their
GOOPS equivalents — to be obtained dynamically, at run time.

* Menu:

* Classes::
* Instances::
* Slots::
* Generic Functions::
* Accessing Slots::


File: guile.info,  Node: Classes,  Next: Instances,  Up: Introspection

8.8.1 Classes
-------------

A GOOPS class is itself an instance of the ‘<class>’ class, or of a
subclass of ‘<class>’.  The definition of the ‘<class>’ class has slots
that are used to describe the properties of a class, including the
following.

 -- primitive procedure: class-name class
     Return the name of class CLASS.  This is the value of CLASS’s
     ‘name’ slot.

 -- primitive procedure: class-direct-supers class
     Return a list containing the direct superclasses of CLASS.  This is
     the value of CLASS’s ‘direct-supers’ slot.

 -- primitive procedure: class-direct-slots class
     Return a list containing the slot definitions of the direct slots
     of CLASS.  This is the value of CLASS’s ‘direct-slots’ slot.

 -- primitive procedure: class-direct-subclasses class
     Return a list containing the direct subclasses of CLASS.  This is
     the value of CLASS’s ‘direct-subclasses’ slot.

 -- primitive procedure: class-direct-methods class
     Return a list of all the generic function methods that use CLASS as
     a formal parameter specializer.  This is the value of CLASS’s
     ‘direct-methods’ slot.

 -- primitive procedure: class-precedence-list class
     Return the class precedence list for class CLASS (*note Class
     Precedence List::).  This is the value of CLASS’s ‘cpl’ slot.

 -- primitive procedure: class-slots class
     Return a list containing the slot definitions for all CLASS’s
     slots, including any slots that are inherited from superclasses.
     This is the value of CLASS’s ‘slots’ slot.

 -- procedure: class-subclasses class
     Return a list of all subclasses of CLASS.

 -- procedure: class-methods class
     Return a list of all methods that use CLASS or a subclass of CLASS
     as one of its formal parameter specializers.


File: guile.info,  Node: Instances,  Next: Slots,  Prev: Classes,  Up: Introspection

8.8.2 Instances
---------------

 -- primitive procedure: class-of value
     Return the GOOPS class of any Scheme VALUE.

 -- primitive procedure: instance? object
     Return ‘#t’ if OBJECT is any GOOPS instance, otherwise ‘#f’.

 -- procedure: is-a? object class
     Return ‘#t’ if OBJECT is an instance of CLASS or one of its
     subclasses.

   You can use the ‘is-a?’ predicate to ask whether any given value
belongs to a given class, or ‘class-of’ to discover the class of a given
value.  Note that when GOOPS is loaded (by code using the ‘(oop goops)’
module) built-in classes like ‘<string>’, ‘<list>’ and ‘<number>’ are
automatically set up, corresponding to all Guile Scheme types.

     (is-a? 2.3 <number>) ⇒ #t
     (is-a? 2.3 <real>) ⇒ #t
     (is-a? 2.3 <string>) ⇒ #f
     (is-a? '("a" "b") <string>) ⇒ #f
     (is-a? '("a" "b") <list>) ⇒ #t
     (is-a? (car '("a" "b")) <string>) ⇒ #t
     (is-a? <string> <class>) ⇒ #t
     (is-a? <class> <string>) ⇒ #f

     (class-of 2.3) ⇒ #<<class> <real> 908c708>
     (class-of #(1 2 3)) ⇒ #<<class> <vector> 908cd20>
     (class-of <string>) ⇒ #<<class> <class> 8bd3e10>
     (class-of <class>) ⇒ #<<class> <class> 8bd3e10>


File: guile.info,  Node: Slots,  Next: Generic Functions,  Prev: Instances,  Up: Introspection

8.8.3 Slots
-----------

 -- procedure: class-slot-definition class slot-name
     Return the slot definition for the slot named SLOT-NAME in class
     CLASS.  SLOT-NAME should be a symbol.

 -- procedure: slot-definition-name slot-def
     Extract and return the slot name from SLOT-DEF.

 -- procedure: slot-definition-options slot-def
     Extract and return the slot options from SLOT-DEF.

 -- procedure: slot-definition-allocation slot-def
     Extract and return the slot allocation option from SLOT-DEF.  This
     is the value of the ‘#:allocation’ keyword (*note allocation: Slot
     Options.), or ‘#:instance’ if the ‘#:allocation’ keyword is absent.

 -- procedure: slot-definition-getter slot-def
     Extract and return the slot getter option from SLOT-DEF.  This is
     the value of the ‘#:getter’ keyword (*note getter: Slot Options.),
     or ‘#f’ if the ‘#:getter’ keyword is absent.

 -- procedure: slot-definition-setter slot-def
     Extract and return the slot setter option from SLOT-DEF.  This is
     the value of the ‘#:setter’ keyword (*note setter: Slot Options.),
     or ‘#f’ if the ‘#:setter’ keyword is absent.

 -- procedure: slot-definition-accessor slot-def
     Extract and return the slot accessor option from SLOT-DEF.  This is
     the value of the ‘#:accessor’ keyword (*note accessor: Slot
     Options.), or ‘#f’ if the ‘#:accessor’ keyword is absent.

 -- procedure: slot-definition-init-value slot-def
     Extract and return the slot init-value option from SLOT-DEF.  This
     is the value of the ‘#:init-value’ keyword (*note init-value: Slot
     Options.), or the unbound value if the ‘#:init-value’ keyword is
     absent.

 -- procedure: slot-definition-init-form slot-def
     Extract and return the slot init-form option from SLOT-DEF.  This
     is the value of the ‘#:init-form’ keyword (*note init-form: Slot
     Options.), or the unbound value if the ‘#:init-form’ keyword is
     absent.

 -- procedure: slot-definition-init-thunk slot-def
     Extract and return the slot init-thunk option from SLOT-DEF.  This
     is the value of the ‘#:init-thunk’ keyword (*note init-thunk: Slot
     Options.), or ‘#f’ if the ‘#:init-thunk’ keyword is absent.

 -- procedure: slot-definition-init-keyword slot-def
     Extract and return the slot init-keyword option from SLOT-DEF.
     This is the value of the ‘#:init-keyword’ keyword (*note
     init-keyword: Slot Options.), or ‘#f’ if the ‘#:init-keyword’
     keyword is absent.

 -- procedure: slot-init-function class slot-name
     Return the initialization function for the slot named SLOT-NAME in
     class CLASS.  SLOT-NAME should be a symbol.

     The returned initialization function incorporates the effects of
     the standard ‘#:init-thunk’, ‘#:init-form’ and ‘#:init-value’ slot
     options.  These initializations can be overridden by the
     ‘#:init-keyword’ slot option or by a specialized ‘initialize’
     method, so, in general, the function returned by
     ‘slot-init-function’ may be irrelevant.  For a fuller discussion,
     see *note init-value: Slot Options.


File: guile.info,  Node: Generic Functions,  Next: Accessing Slots,  Prev: Slots,  Up: Introspection

8.8.4 Generic Functions
-----------------------

A generic function is an instance of the ‘<generic>’ class, or of a
subclass of ‘<generic>’.  The definition of the ‘<generic>’ class has
slots that are used to describe the properties of a generic function.

 -- primitive procedure: generic-function-name gf
     Return the name of generic function GF.

 -- primitive procedure: generic-function-methods gf
     Return a list of the methods of generic function GF.  This is the
     value of GF’s ‘methods’ slot.

   Similarly, a method is an instance of the ‘<method>’ class, or of a
subclass of ‘<method>’; and the definition of the ‘<method>’ class has
slots that are used to describe the properties of a method.

 -- primitive procedure: method-generic-function method
     Return the generic function that METHOD belongs to.  This is the
     value of METHOD’s ‘generic-function’ slot.

 -- primitive procedure: method-specializers method
     Return a list of METHOD’s formal parameter specializers .  This is
     the value of METHOD’s ‘specializers’ slot.

 -- primitive procedure: method-procedure method
     Return the procedure that implements METHOD.  This is the value of
     METHOD’s ‘procedure’ slot.

 -- generic: method-source
 -- method: method-source (m <method>)
     Return an expression that prints to show the definition of method
     M.

          (define-generic cube)

          (define-method (cube (n <number>))
            (* n n n))

          (map method-source (generic-function-methods cube))
          ⇒
          ((method ((n <number>)) (* n n n)))


File: guile.info,  Node: Accessing Slots,  Prev: Generic Functions,  Up: Introspection

8.8.5 Accessing Slots
---------------------

Any slot, regardless of its allocation, can be queried, referenced and
set using the following four primitive procedures.

 -- primitive procedure: slot-exists? obj slot-name
     Return ‘#t’ if OBJ has a slot with name SLOT-NAME, otherwise ‘#f’.

 -- primitive procedure: slot-bound? obj slot-name
     Return ‘#t’ if the slot named SLOT-NAME in OBJ has a value,
     otherwise ‘#f’.

     ‘slot-bound?’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

 -- primitive procedure: slot-ref obj slot-name
     Return the value of the slot named SLOT-NAME in OBJ.

     ‘slot-ref’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

     ‘slot-ref’ calls the generic function ‘slot-unbound’ if the named
     slot in OBJ does not have a value (*note slot-unbound: Accessing
     Slots.).

 -- primitive procedure: slot-set! obj slot-name value
     Set the value of the slot named SLOT-NAME in OBJ to VALUE.

     ‘slot-set!’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

   GOOPS stores information about slots in classes.  Internally, all of
these procedures work by looking up the slot definition for the slot
named SLOT-NAME in the class ‘(class-of OBJ)’, and then using the slot
definition’s “getter” and “setter” closures to get and set the slot
value.

   The next four procedures differ from the previous ones in that they
take the class as an explicit argument, rather than assuming ‘(class-of
OBJ)’.  Therefore they allow you to apply the “getter” and “setter”
closures of a slot definition in one class to an instance of a different
class.

 -- primitive procedure: slot-exists-using-class? class obj slot-name
     Return ‘#t’ if CLASS has a slot definition for a slot with name
     SLOT-NAME, otherwise ‘#f’.

 -- primitive procedure: slot-bound-using-class? class obj slot-name
     Return ‘#t’ if applying ‘slot-ref-using-class’ to the same
     arguments would call the generic function ‘slot-unbound’, otherwise
     ‘#f’.

     ‘slot-bound-using-class?’ calls the generic function ‘slot-missing’
     if CLASS does not have a slot definition for a slot called
     SLOT-NAME (*note slot-missing: Accessing Slots.).

 -- primitive procedure: slot-ref-using-class class obj slot-name
     Apply the “getter” closure for the slot named SLOT-NAME in CLASS to
     OBJ, and return its result.

     ‘slot-ref-using-class’ calls the generic function ‘slot-missing’ if
     CLASS does not have a slot definition for a slot called SLOT-NAME
     (*note slot-missing: Accessing Slots.).

     ‘slot-ref-using-class’ calls the generic function ‘slot-unbound’ if
     the application of the “getter” closure to OBJ returns an unbound
     value (*note slot-unbound: Accessing Slots.).

 -- primitive procedure: slot-set-using-class! class obj slot-name value
     Apply the “setter” closure for the slot named SLOT-NAME in CLASS to
     OBJ and VALUE.

     ‘slot-set-using-class!’ calls the generic function ‘slot-missing’
     if CLASS does not have a slot definition for a slot called
     SLOT-NAME (*note slot-missing: Accessing Slots.).

   Slots whose allocation is per-class rather than per-instance can be
referenced and set without needing to specify any particular instance.

 -- procedure: class-slot-ref class slot-name
     Return the value of the slot named SLOT-NAME in class CLASS.  The
     named slot must have ‘#:class’ or ‘#:each-subclass’ allocation
     (*note allocation: Slot Options.).

     If there is no such slot with ‘#:class’ or ‘#:each-subclass’
     allocation, ‘class-slot-ref’ calls the ‘slot-missing’ generic
     function with arguments CLASS and SLOT-NAME.  Otherwise, if the
     slot value is unbound, ‘class-slot-ref’ calls the ‘slot-unbound’
     generic function, with the same arguments.

 -- procedure: class-slot-set! class slot-name value
     Set the value of the slot named SLOT-NAME in class CLASS to VALUE.
     The named slot must have ‘#:class’ or ‘#:each-subclass’ allocation
     (*note allocation: Slot Options.).

     If there is no such slot with ‘#:class’ or ‘#:each-subclass’
     allocation, ‘class-slot-ref’ calls the ‘slot-missing’ generic
     function with arguments CLASS and SLOT-NAME.

   When a ‘slot-ref’ or ‘slot-set!’ call specifies a non-existent slot
name, or tries to reference a slot whose value is unbound, GOOPS calls
one of the following generic functions.

 -- generic: slot-missing
 -- method: slot-missing (class <class>) slot-name
 -- method: slot-missing (class <class>) (object <object>) slot-name
 -- method: slot-missing (class <class>) (object <object>) slot-name
          value
     When an application attempts to reference or set a class or
     instance slot by name, and the slot name is invalid for the
     specified CLASS or OBJECT, GOOPS calls the ‘slot-missing’ generic
     function.

     The default methods all call ‘goops-error’ with an appropriate
     message.

 -- generic: slot-unbound
 -- method: slot-unbound (object <object>)
 -- method: slot-unbound (class <class>) slot-name
 -- method: slot-unbound (class <class>) (object <object>) slot-name
     When an application attempts to reference a class or instance slot,
     and the slot’s value is unbound, GOOPS calls the ‘slot-unbound’
     generic function.

     The default methods all call ‘goops-error’ with an appropriate
     message.


File: guile.info,  Node: GOOPS Error Handling,  Next: GOOPS Object Miscellany,  Prev: Introspection,  Up: GOOPS

8.9 Error Handling
==================

The procedure ‘goops-error’ is called to raise an appropriate error by
the default methods of the following generic functions:

   • ‘slot-missing’ (*note slot-missing: Accessing Slots.)

   • ‘slot-unbound’ (*note slot-unbound: Accessing Slots.)

   • ‘no-method’ (*note no-method: Handling Invocation Errors.)

   • ‘no-applicable-method’ (*note no-applicable-method: Handling
     Invocation Errors.)

   • ‘no-next-method’ (*note no-next-method: Handling Invocation
     Errors.)

   If you customize these functions for particular classes or
metaclasses, you may still want to use ‘goops-error’ to signal any error
conditions that you detect.

 -- procedure: goops-error format-string arg ...
     Raise an error with key ‘goops-error’ and error message constructed
     from FORMAT-STRING and ARG ....  Error message formatting is as
     done by ‘scm-error’.


File: guile.info,  Node: GOOPS Object Miscellany,  Next: The Metaobject Protocol,  Prev: GOOPS Error Handling,  Up: GOOPS

8.10 GOOPS Object Miscellany
============================

Here we cover some points about GOOPS objects that aren’t substantial
enough to merit sections on their own.

Object Equality
---------------

When GOOPS is loaded, ‘eqv?’, ‘equal?’ and ‘=’ become generic functions,
and you can define methods for them, specialized for your own classes,
so as to control what the various kinds of equality mean for your
classes.

   For example, the ‘assoc’ procedure, for looking up an entry in an
alist, is specified as using ‘equal?’ to determine when the car of an
entry in the alist is the same as the key parameter that ‘assoc’ is
called with.  Hence, if you had defined a new class, and wanted to use
instances of that class as the keys in an alist, you could define a
method for ‘equal?’, for your class, to control ‘assoc’’s lookup
precisely.

Cloning Objects
---------------

 -- generic: shallow-clone
 -- method: shallow-clone (self <object>)
     Return a “shallow” clone of SELF.  The default method makes a
     shallow clone by allocating a new instance and copying slot values
     from self to the new instance.  Each slot value is copied either as
     an immediate value or by reference.

 -- generic: deep-clone
 -- method: deep-clone (self <object>)
     Return a “deep” clone of SELF.  The default method makes a deep
     clone by allocating a new instance and copying or cloning slot
     values from self to the new instance.  If a slot value is an
     instance (satisfies ‘instance?’), it is cloned by calling
     ‘deep-clone’ on that value.  Other slot values are copied either as
     immediate values or by reference.

Write and Display
-----------------

 -- primitive generic: write object port
 -- primitive generic: display object port
     When GOOPS is loaded, ‘write’ and ‘display’ become generic
     functions with special methods for printing

        • objects - instances of the class ‘<object>’

        • foreign objects - instances of the class ‘<foreign-object>’

        • classes - instances of the class ‘<class>’

        • generic functions - instances of the class ‘<generic>’

        • methods - instances of the class ‘<method>’.

     ‘write’ and ‘display’ print non-GOOPS values in the same way as the
     Guile primitive ‘write’ and ‘display’ functions.

   In addition to the cases mentioned, you can of course define ‘write’
and ‘display’ methods for your own classes, to customize how instances
of those classes are printed.


File: guile.info,  Node: The Metaobject Protocol,  Next: Redefining a Class,  Prev: GOOPS Object Miscellany,  Up: GOOPS

8.11 The Metaobject Protocol
============================

At this point, we’ve said about as much as can be said about GOOPS
without having to confront the idea of the metaobject protocol.  There
are a couple more topics that could be discussed in isolation first —
class redefinition, and changing the class of existing instances — but
in practice developers using them will be advanced enough to want to
understand the metaobject protocol too, and will probably be using the
protocol to customize exactly what happens during these events.

   So let’s plunge in.  GOOPS is based on a “metaobject protocol” (aka
“MOP”) derived from the ones used in CLOS (the Common Lisp Object
System), tiny-clos (a small Scheme implementation of a subset of CLOS
functionality) and STKlos.

   The MOP underlies many possible GOOPS customizations — such as
defining an ‘initialize’ method to customize the initialization of
instances of an application-defined class — and an understanding of the
MOP makes it much easier to explain such customizations in a precise
way.  And at a deeper level, understanding the MOP is a key part of
understanding GOOPS, and of taking full advantage of GOOPS’ power, by
customizing the behavior of GOOPS itself.

* Menu:

* Metaobjects and the Metaobject Protocol::
* Metaclasses::
* MOP Specification::
* Instance Creation Protocol::
* Class Definition Protocol::
* Customizing Class Definition::
* Method Definition::
* Method Definition Internals::
* Generic Function Internals::
* Generic Function Invocation::


File: guile.info,  Node: Metaobjects and the Metaobject Protocol,  Next: Metaclasses,  Up: The Metaobject Protocol

8.11.1 Metaobjects and the Metaobject Protocol
----------------------------------------------

The building blocks of GOOPS are classes, slot definitions, instances,
generic functions and methods.  A class is a grouping of inheritance
relations and slot definitions.  An instance is an object with slots
that are allocated following the rules implied by its class’s
superclasses and slot definitions.  A generic function is a collection
of methods and rules for determining which of those methods to apply
when the generic function is invoked.  A method is a procedure and a set
of specializers that specify the type of arguments to which the
procedure is applicable.

   Of these entities, GOOPS represents classes, generic functions and
methods as “metaobjects”.  In other words, the values in a GOOPS program
that describe classes, generic functions and methods, are themselves
instances (or “objects”) of special GOOPS classes that encapsulate the
behavior, respectively, of classes, generic functions, and methods.

   (The other two entities are slot definitions and instances.  Slot
definitions are not strictly instances, but every slot definition is
associated with a GOOPS class that specifies the behavior of the slot as
regards accessibility and protection from garbage collection.  Instances
are of course objects in the usual sense, and there is no benefit from
thinking of them as metaobjects.)

   The “metaobject protocol” (or “MOP”) is the specification of the
generic functions which determine the behavior of these metaobjects and
the circumstances in which these generic functions are invoked.

   For a concrete example of what this means, consider how GOOPS
calculates the set of slots for a class that is being defined using
‘define-class’.  The desired set of slots is the union of the new
class’s direct slots and the slots of all its superclasses.  But
‘define-class’ itself does not perform this calculation.  Instead, there
is a method of the ‘initialize’ generic function that is specialized for
instances of type ‘<class>’, and it is this method that performs the
slot calculation.

   ‘initialize’ is a generic function which GOOPS calls whenever a new
instance is created, immediately after allocating memory for a new
instance, in order to initialize the new instance’s slots.  The sequence
of steps is as follows.

   • ‘define-class’ uses ‘make’ to make a new instance of the ‘<class>’
     class, passing as initialization arguments the superclasses, slot
     definitions and class options that were specified in the
     ‘define-class’ form.

   • ‘make’ allocates memory for the new instance, and invokes the
     ‘initialize’ generic function to initialize the new instance’s
     slots.

   • The ‘initialize’ generic function applies the method that is
     specialized for instances of type ‘<class>’, and this method
     performs the slot calculation.

   In other words, rather than being hardcoded in ‘define-class’, the
default behavior of class definition is encapsulated by generic function
methods that are specialized for the class ‘<class>’.

   It is possible to create a new class that inherits from ‘<class>’,
which is called a “metaclass”, and to write a new ‘initialize’ method
that is specialized for instances of the new metaclass.  Then, if the
‘define-class’ form includes a ‘#:metaclass’ class option whose value is
the new metaclass, the class that is defined by the ‘define-class’ form
will be an instance of the new metaclass rather than of the default
‘<class>’, and will be defined in accordance with the new ‘initialize’
method.  Thus the default slot calculation, as well as any other aspect
of the new class’s relationship with its superclasses, can be modified
or overridden.

   In a similar way, the behavior of generic functions can be modified
or overridden by creating a new class that inherits from the standard
generic function class ‘<generic>’, writing appropriate methods that are
specialized to the new class, and creating new generic functions that
are instances of the new class.

   The same is true for method metaobjects.  And the same basic
mechanism allows the application class author to write an ‘initialize’
method that is specialized to their application class, to initialize
instances of that class.

   Such is the power of the MOP. Note that ‘initialize’ is just one of a
large number of generic functions that can be customized to modify the
behavior of application objects and classes and of GOOPS itself.  Each
following section covers a particular area of GOOPS functionality, and
describes the generic functions that are relevant for customization of
that area.


File: guile.info,  Node: Metaclasses,  Next: MOP Specification,  Prev: Metaobjects and the Metaobject Protocol,  Up: The Metaobject Protocol

8.11.2 Metaclasses
------------------

A “metaclass” is the class of an object which represents a GOOPS class.
Put more succinctly, a metaclass is a class’s class.

   Most GOOPS classes have the metaclass ‘<class>’ and, by default, any
new class that is created using ‘define-class’ has the metaclass
‘<class>’.

   But what does this really mean?  To find out, let’s look in more
detail at what happens when a new class is created using ‘define-class’:

     (define-class <my-class> (<object>) . slots)

Guile expands this to something like:

     (define <my-class> (class (<object>) . slots))

which in turn expands to:

     (define <my-class>
       (make <class> #:dsupers (list <object>) #:slots slots))

   As this expansion makes clear, the resulting value of ‘<my-class>’ is
an instance of the class ‘<class>’ with slot values specifying the
superclasses and slot definitions for the class ‘<my-class>’.
(‘#:dsupers’ and ‘#:slots’ are initialization keywords for the ‘dsupers’
and ‘dslots’ slots of the ‘<class>’ class.)

   Now suppose that you want to define a new class with a metaclass
other than the default ‘<class>’.  This is done by writing:

     (define-class <my-class2> (<object>)
        slot ...
        #:metaclass <my-metaclass>)

and Guile expands _this_ to something like:

     (define <my-class2>
       (make <my-metaclass> #:dsupers (list <object>) #:slots slots))

   In this case, the value of ‘<my-class2>’ is an instance of the more
specialized class ‘<my-metaclass>’.  Note that ‘<my-metaclass>’ itself
must previously have been defined as a subclass of ‘<class>’.  For a
full discussion of when and how it is useful to define new metaclasses,
see *note MOP Specification::.

   Now let’s make an instance of ‘<my-class2>’:

     (define my-object (make <my-class2> ...))

   All of the following statements are correct expressions of the
relationships between ‘my-object’, ‘<my-class2>’, ‘<my-metaclass>’ and
‘<class>’.

   • ‘my-object’ is an instance of the class ‘<my-class2>’.

   • ‘<my-class2>’ is an instance of the class ‘<my-metaclass>’.

   • ‘<my-metaclass>’ is an instance of the class ‘<class>’.

   • The class of ‘my-object’ is ‘<my-class2>’.

   • The class of ‘<my-class2>’ is ‘<my-metaclass>’.

   • The class of ‘<my-metaclass>’ is ‘<class>’.


File: guile.info,  Node: MOP Specification,  Next: Instance Creation Protocol,  Prev: Metaclasses,  Up: The Metaobject Protocol

8.11.3 MOP Specification
------------------------

The aim of the MOP specification in this chapter is to specify all the
customizable generic function invocations that can be made by the
standard GOOPS syntax, procedures and methods, and to explain the
protocol for customizing such invocations.

   A generic function invocation is customizable if the types of the
arguments to which it is applied are not completely determined by the
lexical context in which the invocation appears.  For example, the
‘(initialize INSTANCE INITARGS)’ invocation in the default
‘make-instance’ method is customizable, because the type of the
‘INSTANCE’ argument is determined by the class that was passed to
‘make-instance’.

   (Whereas — to give a counter-example — the ‘(make <generic> #:name
',name)’ invocation in ‘define-generic’ is not customizable, because all
of its arguments have lexically determined types.)

   When using this rule to decide whether a given generic function
invocation is customizable, we ignore arguments that are expected to be
handled in method definitions as a single “rest” list argument.

   For each customizable generic function invocation, the “invocation
protocol” is explained by specifying

   • what, conceptually, the applied method is intended to do

   • what assumptions, if any, the caller makes about the applied
     method’s side effects

   • what the caller expects to get as the applied method’s return
     value.


File: guile.info,  Node: Instance Creation Protocol,  Next: Class Definition Protocol,  Prev: MOP Specification,  Up: The Metaobject Protocol

8.11.4 Instance Creation Protocol
---------------------------------

‘make <class> . INITARGS’ (method)

   • ‘allocate-instance CLASS INITARGS’ (generic)

     The applied ‘allocate-instance’ method should allocate storage for
     a new instance of class CLASS and return the uninitialized
     instance.

   • ‘initialize INSTANCE INITARGS’ (generic)

     INSTANCE is the uninitialized instance returned by
     ‘allocate-instance’.  The applied method should initialize the new
     instance in whatever sense is appropriate for its class.  The
     method’s return value is ignored.

   ‘make’ itself is a generic function.  Hence the ‘make’ invocation
itself can be customized in the case where the new instance’s metaclass
is more specialized than the default ‘<class>’, by defining a ‘make’
method that is specialized to that metaclass.

   Normally, however, the method for classes with metaclass ‘<class>’
will be applied.  This method calls two generic functions:

   • (allocate-instance CLASS .  INITARGS)

   • (initialize INSTANCE .  INITARGS)

   ‘allocate-instance’ allocates storage for and returns the new
instance, uninitialized.  You might customize ‘allocate-instance’, for
example, if you wanted to provide a GOOPS wrapper around some other
object programming system.

   To do this, you would create a specialized metaclass, which would act
as the metaclass for all classes and instances from the other system.
Then define an ‘allocate-instance’ method, specialized to that
metaclass, which calls a Guile primitive C function (or FFI code), which
in turn allocates the new instance using the interface of the other
object system.

   In this case, for a complete system, you would also need to customize
a number of other generic functions like ‘make’ and ‘initialize’, so
that GOOPS knows how to make classes from the other system, access
instance slots, and so on.

   ‘initialize’ initializes the instance that is returned by
‘allocate-instance’.  The standard GOOPS methods perform initializations
appropriate to the instance class.

   • At the least specialized level, the method for instances of type
     ‘<object>’ performs internal GOOPS instance initialization, and
     initializes the instance’s slots according to the slot definitions
     and any slot initialization keywords that appear in INITARGS.

   • The method for instances of type ‘<class>’ calls ‘(next-method)’,
     then performs the class initializations described in *note Class
     Definition Protocol::.

   • and so on for generic functions, methods, operator classes ...

   Similarly, you can customize the initialization of instances of any
application-defined class by defining an ‘initialize’ method specialized
to that class.

   Imagine a class whose instances’ slots need to be initialized at
instance creation time by querying a database.  Although it might be
possible to achieve this a combination of ‘#:init-thunk’ keywords and
closures in the slot definitions, it may be neater to write an
‘initialize’ method for the class that queries the database once and
initializes all the dependent slot values according to the results.


File: guile.info,  Node: Class Definition Protocol,  Next: Customizing Class Definition,  Prev: Instance Creation Protocol,  Up: The Metaobject Protocol

8.11.5 Class Definition Protocol
--------------------------------

Here is a summary diagram of the syntax, procedures and generic
functions that may be involved in class definition.

‘define-class’ (syntax)

   • ‘class’ (syntax)

        • ‘make-class’ (procedure)

             • ‘ensure-metaclass’ (procedure)

             • ‘make METACLASS ...’ (generic)

                  • ‘allocate-instance’ (generic)

                  • ‘initialize’ (generic)

                       • ‘compute-cpl’ (generic)

                            • ‘compute-std-cpl’ (procedure)

                       • ‘compute-slots’ (generic)

                       • ‘compute-get-n-set’ (generic)

                       • ‘compute-getter-method’ (generic)

                       • ‘compute-setter-method’ (generic)

   • ‘class-redefinition’ (generic)

        • ‘remove-class-accessors’ (generic)

        • ‘update-direct-method!’ (generic)

        • ‘update-direct-subclass!’ (generic)

   Wherever a step above is marked as “generic”, it can be customized,
and the detail shown below it is only “correct” insofar as it describes
what the default method of that generic function does.  For example, if
you write an ‘initialize’ method, for some metaclass, that does not call
‘next-method’ and does not call ‘compute-cpl’, then ‘compute-cpl’ will
not be called when a class is defined with that metaclass.

   A ‘(define-class ...)’ form (*note Class Definition::) expands to an
expression which

   • checks that it is being evaluated only at top level

   • defines any accessors that are implied by the SLOT-DEFINITIONs

   • uses ‘class’ to create the new class

   • checks for a previous class definition for NAME and, if found,
     handles the redefinition by invoking ‘class-redefinition’ (*note
     Redefining a Class::).

 -- syntax: class name (super ...) slot-definition ... class-option ...
     Return a newly created class that inherits from SUPERs, with direct
     slots defined by SLOT-DEFINITIONs and CLASS-OPTIONs.  For the
     format of SLOT-DEFINITIONs and CLASS-OPTIONs, see *note
     define-class: Class Definition.

‘class’ expands to an expression which

   • processes the class and slot definition options to check that they
     are well-formed, to convert the ‘#:init-form’ option to an
     ‘#:init-thunk’ option, to supply a default environment parameter
     (the current top-level environment) and to evaluate all the bits
     that need to be evaluated

   • calls ‘make-class’ to create the class with the processed and
     evaluated parameters.

 -- procedure: make-class supers slots class-option ...
     Return a newly created class that inherits from SUPERS, with direct
     slots defined by SLOTS and CLASS-OPTIONs.  For the format of SLOTS
     and CLASS-OPTIONs, see *note define-class: Class Definition, except
     note that for ‘make-class’, SLOTS is a separate list of slot
     definitions.

‘make-class’

   • adds ‘<object>’ to the SUPERS list if SUPERS is empty or if none of
     the classes in SUPERS have ‘<object>’ in their class precedence
     list

   • defaults the ‘#:environment’, ‘#:name’ and ‘#:metaclass’ options,
     if they are not specified by OPTIONS, to the current top-level
     environment, the unbound value, and ‘(ensure-metaclass SUPERS)’
     respectively

   • checks for duplicate classes in SUPERS and duplicate slot names in
     SLOTS, and signals an error if there are any duplicates

   • calls ‘make’, passing the metaclass as the first parameter and all
     other parameters as option keywords with values.

 -- procedure: ensure-metaclass supers env
     Return a metaclass suitable for a class that inherits from the list
     of classes in SUPERS.  The returned metaclass is the union by
     inheritance of the metaclasses of the classes in SUPERS.

     In the simplest case, where all the SUPERS are straightforward
     classes with metaclass ‘<class>’, the returned metaclass is just
     ‘<class>’.

     For a more complex example, suppose that SUPERS contained one class
     with metaclass ‘<operator-class>’ and one with metaclass
     ‘<foreign-object-class>’.  Then the returned metaclass would be a
     class that inherits from both ‘<operator-class>’ and
     ‘<foreign-object-class>’.

     If SUPERS is the empty list, ‘ensure-metaclass’ returns the default
     GOOPS metaclass ‘<class>’.

     GOOPS keeps a list of the metaclasses created by
     ‘ensure-metaclass’, so that each required type of metaclass only
     has to be created once.

     The ‘env’ parameter is ignored.

 -- generic: make metaclass initarg ...
     METACLASS is the metaclass of the class being defined, either taken
     from the ‘#:metaclass’ class option or computed by
     ‘ensure-metaclass’.  The applied method must create and return the
     fully initialized class metaobject for the new class definition.

   The ‘(make METACLASS INITARG ...)’ invocation is a particular case of
the instance creation protocol covered in the previous section.  It will
create an class metaobject with metaclass METACLASS.  By default, this
metaobject will be initialized by the ‘initialize’ method that is
specialized for instances of type ‘<class>’.

   The ‘initialize’ method for classes (signature ‘(initialize <class>
initargs)’) calls the following generic functions.

   • ‘compute-cpl CLASS’ (generic)

     The applied method should compute and return the class precedence
     list for CLASS as a list of class metaobjects.  When ‘compute-cpl’
     is called, the following CLASS metaobject slots have all been
     initialized: ‘name’, ‘direct-supers’, ‘direct-slots’,
     ‘direct-subclasses’ (empty), ‘direct-methods’.  The value returned
     by ‘compute-cpl’ will be stored in the ‘cpl’ slot.

   • ‘compute-slots CLASS’ (generic)

     The applied method should compute and return the slots (union of
     direct and inherited) for CLASS as a list of slot definitions.
     When ‘compute-slots’ is called, all the CLASS metaobject slots
     mentioned for ‘compute-cpl’ have been initialized, plus the
     following: ‘cpl’, ‘redefined’ (‘#f’), ‘environment’.  The value
     returned by ‘compute-slots’ will be stored in the ‘slots’ slot.

   • ‘compute-get-n-set CLASS SLOT-DEF’ (generic)

     ‘initialize’ calls ‘compute-get-n-set’ for each slot computed by
     ‘compute-slots’.  The applied method should compute and return a
     pair of closures that, respectively, get and set the value of the
     specified slot.  The get closure should have arity 1 and expect a
     single argument that is the instance whose slot value is to be
     retrieved.  The set closure should have arity 2 and expect two
     arguments, where the first argument is the instance whose slot
     value is to be set and the second argument is the new value for
     that slot.  The closures should be returned in a two element list:
     ‘(list GET SET)’.

     The closures returned by ‘compute-get-n-set’ are stored as part of
     the value of the CLASS metaobject’s ‘getters-n-setters’ slot.
     Specifically, the value of this slot is a list with the same number
     of elements as there are slots in the class, and each element looks
     either like

          (SLOT-NAME-SYMBOL INIT-FUNCTION . INDEX)

     or like

          (SLOT-NAME-SYMBOL INIT-FUNCTION GET SET)

     Where the get and set closures are replaced by INDEX, the slot is
     an instance slot and INDEX is the slot’s index in the underlying
     structure: GOOPS knows how to get and set the value of such slots
     and so does not need specially constructed get and set closures.
     Otherwise, GET and SET are the closures returned by
     ‘compute-get-n-set’.

     The structure of the ‘getters-n-setters’ slot value is important
     when understanding the next customizable generic functions that
     ‘initialize’ calls...

   • ‘compute-getter-method CLASS GNS’ (generic)

     ‘initialize’ calls ‘compute-getter-method’ for each of the class’s
     slots (as determined by ‘compute-slots’) that includes a ‘#:getter’
     or ‘#:accessor’ slot option.  GNS is the element of the CLASS
     metaobject’s ‘getters-n-setters’ slot that specifies how the slot
     in question is referenced and set, as described above under
     ‘compute-get-n-set’.  The applied method should create and return a
     method that is specialized for instances of type CLASS and uses the
     get closure to retrieve the slot’s value.  ‘initialize’ uses
     ‘add-method!’ to add the returned method to the generic function
     named by the slot definition’s ‘#:getter’ or ‘#:accessor’ option.

   • ‘compute-setter-method CLASS GNS’ (generic)

     ‘compute-setter-method’ is invoked with the same arguments as
     ‘compute-getter-method’, for each of the class’s slots that
     includes a ‘#:setter’ or ‘#:accessor’ slot option.  The applied
     method should create and return a method that is specialized for
     instances of type CLASS and uses the set closure to set the slot’s
     value.  ‘initialize’ then uses ‘add-method!’ to add the returned
     method to the generic function named by the slot definition’s
     ‘#:setter’ or ‘#:accessor’ option.


File: guile.info,  Node: Customizing Class Definition,  Next: Method Definition,  Prev: Class Definition Protocol,  Up: The Metaobject Protocol

8.11.6 Customizing Class Definition
-----------------------------------

If the metaclass of the new class is something more specialized than the
default ‘<class>’, then the type of CLASS in the calls above is more
specialized than ‘<class>’, and hence it becomes possible to define
generic function methods, specialized for the new class’s metaclass,
that can modify or override the default behavior of ‘initialize’,
‘compute-cpl’ or ‘compute-get-n-set’.

   ‘compute-cpl’ computes the class precedence list (“CPL”) for the new
class (*note Class Precedence List::), and returns it as a list of class
objects.  The CPL is important because it defines a superclass ordering
that is used, when a generic function is invoked upon an instance of the
class, to decide which of the available generic function methods is the
most specific.  Hence ‘compute-cpl’ could be customized in order to
modify the CPL ordering algorithm for all classes with a special
metaclass.

   The default CPL algorithm is encapsulated by the ‘compute-std-cpl’
procedure, which is called by the default ‘compute-cpl’ method.

 -- procedure: compute-std-cpl class
     Compute and return the class precedence list for CLASS according to
     the algorithm described in *note Class Precedence List::.

   ‘compute-slots’ computes and returns a list of all slot definitions
for the new class.  By default, this list includes the direct slot
definitions from the ‘define-class’ form, plus the slot definitions that
are inherited from the new class’s superclasses.  The default
‘compute-slots’ method uses the CPL computed by ‘compute-cpl’ to
calculate this union of slot definitions, with the rule that slots
inherited from superclasses are shadowed by direct slots with the same
name.  One possible reason for customizing ‘compute-slots’ would be to
implement an alternative resolution strategy for slot name conflicts.

   ‘compute-get-n-set’ computes the low-level closures that will be used
to get and set the value of a particular slot, and returns them in a
list with two elements.

   The closures returned depend on how storage for that slot is
allocated.  The standard ‘compute-get-n-set’ method, specialized for
classes of type ‘<class>’, handles the standard GOOPS values for the
‘#:allocation’ slot option (*note allocation: Slot Options.).  By
defining a new ‘compute-get-n-set’ method for a more specialized
metaclass, it is possible to support new types of slot allocation.

   Suppose you wanted to create a large number of instances of some
class with a slot that should be shared between some but not all
instances of that class - say every 10 instances should share the same
slot storage.  The following example shows how to implement and use a
new type of slot allocation to do this.

     (define-class <batched-allocation-metaclass> (<class>))

     (let ((batch-allocation-count 0)
           (batch-get-n-set #f))
       (define-method (compute-get-n-set
                          (class <batched-allocation-metaclass>) s)
         (case (slot-definition-allocation s)
           ((#:batched)
            ;; If we've already used the same slot storage for 10 instances,
            ;; reset variables.
            (if (= batch-allocation-count 10)
                (begin
                  (set! batch-allocation-count 0)
                  (set! batch-get-n-set #f)))
            ;; If we don't have a current pair of get and set closures,
            ;; create one.  make-closure-variable returns a pair of closures
            ;; around a single Scheme variable - see goops.scm for details.
            (or batch-get-n-set
                (set! batch-get-n-set (make-closure-variable)))
            ;; Increment the batch allocation count.
            (set! batch-allocation-count (+ batch-allocation-count 1))
            batch-get-n-set)

           ;; Call next-method to handle standard allocation types.
           (else (next-method)))))

     (define-class <class-using-batched-slot> ()
       ...
       (c #:allocation #:batched)
       ...
       #:metaclass <batched-allocation-metaclass>)

   The usage of ‘compute-getter-method’ and ‘compute-setter-method’ is
described in *note Class Definition Protocol::.

   ‘compute-cpl’ and ‘compute-get-n-set’ are called by the standard
‘initialize’ method for classes whose metaclass is ‘<class>’.  But
‘initialize’ itself can also be modified, by defining an ‘initialize’
method specialized to the new class’s metaclass.  Such a method could
complete override the standard behavior, by not calling ‘(next-method)’
at all, but more typically it would perform additional class
initialization steps before and/or after calling ‘(next-method)’ for the
standard behavior.


File: guile.info,  Node: Method Definition,  Next: Method Definition Internals,  Prev: Customizing Class Definition,  Up: The Metaobject Protocol

8.11.7 Method Definition
------------------------

‘define-method’ (syntax)

   • ‘add-method! TARGET METHOD’ (generic)

‘define-method’ invokes the ‘add-method!’ generic function to handle
adding the new method to a variety of possible targets.  GOOPS includes
methods to handle TARGET as

   • a generic function (the most common case)

   • a procedure

   • a primitive generic (*note Extending Primitives::)

   By defining further methods for ‘add-method!’, you can theoretically
handle adding methods to further types of target.


File: guile.info,  Node: Method Definition Internals,  Next: Generic Function Internals,  Prev: Method Definition,  Up: The Metaobject Protocol

8.11.8 Method Definition Internals
----------------------------------

‘define-method’:

   • checks the form of the first parameter, and applies the following
     steps to the accessor’s setter if it has the ‘(setter ...)’ form

   • interpolates a call to ‘define-generic’ or ‘define-accessor’ if a
     generic function is not already defined with the supplied name

   • calls ‘method’ with the PARAMETERs and BODY, to make a new method
     instance

   • calls ‘add-method!’ to add this method to the relevant generic
     function.

 -- syntax: method (parameter ...) body ...
     Make a method whose specializers are defined by the classes in
     PARAMETERs and whose procedure definition is constructed from the
     PARAMETER symbols and BODY forms.

     The PARAMETER and BODY parameters should be as for ‘define-method’
     (*note define-method: Methods and Generic Functions.).

‘method’:

   • extracts formals and specializing classes from the PARAMETERs,
     defaulting the class for unspecialized parameters to ‘<top>’

   • creates a closure using the formals and the BODY forms

   • calls ‘make’ with metaclass ‘<method>’ and the specializers and
     closure using the ‘#:specializers’ and ‘#:procedure’ keywords.

 -- procedure: make-method specializers procedure
     Make a method using SPECIALIZERS and PROCEDURE.

     SPECIALIZERS should be a list of classes that specifies the
     parameter combinations to which this method will be applicable.

     PROCEDURE should be the closure that will applied to the generic
     function parameters when this method is invoked.

‘make-method’ is a simple wrapper around ‘make’ with metaclass
‘<method>’.

 -- generic: add-method! target method
     Generic function for adding method METHOD to TARGET.

 -- method: add-method! (generic <generic>) (method <method>)
     Add method METHOD to the generic function GENERIC.

 -- method: add-method! (proc <procedure>) (method <method>)
     If PROC is a procedure with generic capability (*note
     generic-capability?: Extending Primitives.), upgrade it to a
     primitive generic and add METHOD to its generic function
     definition.

 -- method: add-method! (pg <primitive-generic>) (method <method>)
     Add method METHOD to the generic function definition of PG.

     Implementation: ‘(add-method! (primitive-generic-generic pg)
     method)’.

 -- method: add-method! (whatever <top>) (method <method>)
     Raise an error indicating that WHATEVER is not a valid generic
     function.


File: guile.info,  Node: Generic Function Internals,  Next: Generic Function Invocation,  Prev: Method Definition Internals,  Up: The Metaobject Protocol

8.11.9 Generic Function Internals
---------------------------------

‘define-generic’ calls ‘ensure-generic’ to upgrade a pre-existing
procedure value, or ‘make’ with metaclass ‘<generic>’ to create a new
generic function.

   ‘define-accessor’ calls ‘ensure-accessor’ to upgrade a pre-existing
procedure value, or ‘make-accessor’ to create a new accessor.

 -- procedure: ensure-generic old-definition [name]
     Return a generic function with name NAME, if possible by using or
     upgrading OLD-DEFINITION.  If unspecified, NAME defaults to ‘#f’.

     If OLD-DEFINITION is already a generic function, it is returned
     unchanged.

     If OLD-DEFINITION is a Scheme procedure or procedure-with-setter,
     ‘ensure-generic’ returns a new generic function that uses
     OLD-DEFINITION for its default procedure and setter.

     Otherwise ‘ensure-generic’ returns a new generic function with no
     defaults and no methods.

 -- procedure: make-generic [name]
     Return a new generic function with name ‘(car NAME)’.  If
     unspecified, NAME defaults to ‘#f’.

   ‘ensure-generic’ calls ‘make’ with metaclasses ‘<generic>’ and
‘<generic-with-setter>’, depending on the previous value of the variable
that it is trying to upgrade.

   ‘make-generic’ is a simple wrapper for ‘make’ with metaclass
‘<generic>’.

 -- procedure: ensure-accessor proc [name]
     Return an accessor with name NAME, if possible by using or
     upgrading PROC.  If unspecified, NAME defaults to ‘#f’.

     If PROC is already an accessor, it is returned unchanged.

     If PROC is a Scheme procedure, procedure-with-setter or generic
     function, ‘ensure-accessor’ returns an accessor that reuses the
     reusable elements of PROC.

     Otherwise ‘ensure-accessor’ returns a new accessor with no defaults
     and no methods.

 -- procedure: make-accessor [name]
     Return a new accessor with name ‘(car NAME)’.  If unspecified, NAME
     defaults to ‘#f’.

   ‘ensure-accessor’ calls ‘make’ with metaclass
‘<generic-with-setter>’, as well as calls to ‘ensure-generic’,
‘make-accessor’ and (tail recursively) ‘ensure-accessor’.

   ‘make-accessor’ calls ‘make’ twice, first with metaclass ‘<generic>’
to create a generic function for the setter, then with metaclass
‘<generic-with-setter>’ to create the accessor, passing the setter
generic function as the value of the ‘#:setter’ keyword.


File: guile.info,  Node: Generic Function Invocation,  Prev: Generic Function Internals,  Up: The Metaobject Protocol

8.11.10 Generic Function Invocation
-----------------------------------

There is a detailed and customizable protocol involved in the process of
invoking a generic function — i.e., in the process of deciding which of
the generic function’s methods are applicable to the current arguments,
and which one of those to apply.  Here is a summary diagram of the
generic functions involved.

‘apply-generic’ (generic)

   • ‘no-method’ (generic)

   • ‘compute-applicable-methods’ (generic)

   • ‘sort-applicable-methods’ (generic)

        • ‘method-more-specific?’ (generic)

   • ‘apply-methods’ (generic)

        • ‘apply-method’ (generic)

        • ‘no-next-method’ (generic)

   • ‘no-applicable-method’

   We do not yet have full documentation for these.  Please refer to the
code (‘oop/goops.scm’) for details.


File: guile.info,  Node: Redefining a Class,  Next: Changing the Class of an Instance,  Prev: The Metaobject Protocol,  Up: GOOPS

8.12 Redefining a Class
=======================

Suppose that a class ‘<my-class>’ is defined using ‘define-class’ (*note
define-class: Class Definition.), with slots that have accessor
functions, and that an application has created several instances of
‘<my-class>’ using ‘make’ (*note make: Instance Creation.).  What then
happens if ‘<my-class>’ is redefined by calling ‘define-class’ again?

* Menu:

* Redefinable Classes::
* Default Class Redefinition Behavior::
* Customizing Class Redefinition::


File: guile.info,  Node: Redefinable Classes,  Next: Default Class Redefinition Behavior,  Up: Redefining a Class

8.12.1 Redefinable Classes
--------------------------

The ability for a class to be redefined is a choice for a class author
to make.  By default, classes in GOOPS are _not_ redefinable.  A
redefinable class is an instance of ‘<redefinable-class>’; that is to
say, a class with ‘<redefinable-class>’ as its metaclass.  Accordingly,
to define a redefinable class, add ‘#:metaclass <redefinable-class>’ to
its class definition:

     (define-class <foo> ()
       #:metaclass <redefinable-class>)

   Note that any subclass of ‘<foo>’ is also redefinable, without the
need to explicitly pass the ‘#:metaclass’ argument, so you only need to
specify ‘#:metaclass’ for the roots of your application’s class
hierarchy.

     (define-class <bar> (<foo>))
     (class-of <bar>) ⇒ <redefinable-class>

   Note that prior to Guile 3.0, all GOOPS classes were redefinable in
theory.  In practice, attempting to, for example, redefine ‘<class>’
itself would almost certainly not do what you want.  Still, redefinition
is an interesting capability when building long-lived resilient systems,
so GOOPS does offer this facility.


File: guile.info,  Node: Default Class Redefinition Behavior,  Next: Customizing Class Redefinition,  Prev: Redefinable Classes,  Up: Redefining a Class

8.12.2 Default Class Redefinition Behavior
------------------------------------------

When a class is defined using ‘define-class’ and the class name was
previously defined, by default the new binding just replaces the old
binding.  This is the normal behavior for ‘define’.  However if both the
old and new bindings are redefinable classes (instances of
‘<redefinable-class>’), then the class will be updated in place, and its
instances lazily migrated over.

   The way that the class is updated and the way that the instances
migrate over are of course part of the meta-object protocol.  However
the default behavior usually suffices, and it goes as follows.

   • All existing direct instances of ‘<my-class>’ are converted to be
     instances of the new class.  This is achieved by preserving the
     values of slots that exist in both the old and new definitions, and
     initializing the values of new slots in the usual way (*note make:
     Instance Creation.).

   • All existing subclasses of ‘<my-class>’ are redefined, as though
     the ‘define-class’ expressions that defined them were re-evaluated
     following the redefinition of ‘<my-class>’, and the class
     redefinition process described here is applied recursively to the
     redefined subclasses.

   • Once all of its instances and subclasses have been updated, the
     class metaobject previously bound to the variable ‘<my-class>’ is
     no longer needed and so can be allowed to be garbage collected.

   To keep things tidy, GOOPS also needs to do a little housekeeping on
methods that are associated with the redefined class.

   • Slot accessor methods for slots in the old definition should be
     removed from their generic functions.  They will be replaced by
     accessor methods for the slots of the new class definition.

   • Any generic function method that uses the old ‘<my-class>’
     metaobject as one of its formal parameter specializers must be
     updated to refer to the new ‘<my-class>’ metaobject.  (Whenever a
     new generic function method is defined, ‘define-method’ adds the
     method to a list stored in the class metaobject for each class used
     as a formal parameter specializer, so it is easy to identify all
     the methods that must be updated when a class is redefined.)

   If this class redefinition strategy strikes you as rather
counter-intuitive, bear in mind that it is derived from similar behavior
in other object systems such as CLOS, and that experience in those
systems has shown it to be very useful in practice.

   Also bear in mind that, like most of GOOPS’ default behavior, it can
be customized...


File: guile.info,  Node: Customizing Class Redefinition,  Prev: Default Class Redefinition Behavior,  Up: Redefining a Class

8.12.3 Customizing Class Redefinition
-------------------------------------

When ‘define-class’ notices that a class is being redefined, it
constructs the new class metaobject as usual, then invokes the
‘class-redefinition’ generic function with the old and new classes as
arguments.  Therefore, if the old or new classes have metaclasses other
than the default ‘<redefinable-class>’, class redefinition behavior can
be customized by defining a ‘class-redefinition’ method that is
specialized for the relevant metaclasses.

 -- generic: class-redefinition
     Handle the class redefinition from OLD to NEW, and return the new
     class metaobject that should be bound to the variable specified by
     ‘define-class’’s first argument.

 -- method: class-redefinition (old <top>) (new <class>)
     Not all classes are redefinable, and not all previous bindings are
     classes.  *Note Redefinable Classes::.  This default method just
     returns NEW.

 -- method: class-redefinition (old <redefinable-class>) (new
          <redefinable-class>)
     This method implements GOOPS’ default class redefinition behavior,
     as described in *note Default Class Redefinition Behavior::.
     Returns the metaobject for the new class definition.

   The ‘class-redefinition’ method for classes with metaclass
‘<redefinable-class>’ calls the following generic functions, which could
of course be individually customized.

 -- generic: remove-class-accessors! old
     The default ‘remove-class-accessors!’ method removes the accessor
     methods of the old class from all classes which they specialize.

 -- generic: update-direct-method! method old new
     The default ‘update-direct-method!’ method substitutes the new
     class for the old in all methods specialized to the old class.

 -- generic: update-direct-subclass! subclass old new
     The default ‘update-direct-subclass!’ method invokes
     ‘class-redefinition’ recursively to handle the redefinition of
     subclasses.

   An alternative class redefinition strategy could be to leave all
existing instances as instances of the old class, but accepting that the
old class is now “nameless”, since its name has been taken over by the
new definition.  In this strategy, any existing subclasses could also be
left as they are, on the understanding that they inherit from a nameless
superclass.

   This strategy is easily implemented in GOOPS, by defining a new
metaclass, that will be used as the metaclass for all classes to which
the strategy should apply, and then defining a ‘class-redefinition’
method that is specialized for this metaclass:

     (define-class <can-be-nameless> (<redefinable-class>))

     (define-method (class-redefinition (old <can-be-nameless>)
                                        (new <class>))
       new)

   When customization can be as easy as this, aren’t you glad that GOOPS
implements the far more difficult strategy as its default!


File: guile.info,  Node: Changing the Class of an Instance,  Prev: Redefining a Class,  Up: GOOPS

8.13 Changing the Class of an Instance
======================================

When a redefinable class is redefined, any existing instance of the
redefined class will be modified for the new class definition before the
next time that any of the instance’s slots is referenced or set.  GOOPS
modifies each instance by calling the generic function ‘change-class’.

   More generally, you can change the class of an existing instance at
any time by invoking the generic function ‘change-class’ with two
arguments: the instance and the new class.

   The default method for ‘change-class’ decides how to implement the
change of class by looking at the slot definitions for the instance’s
existing class and for the new class.  If the new class has slots with
the same name as slots in the existing class, the values for those slots
are preserved.  Slots that are present only in the existing class are
discarded.  Slots that are present only in the new class are initialized
using the corresponding slot definition’s init function (*note
slot-init-function: Classes.).

 -- generic: change-class instance new-class

 -- method: change-class (obj <object>) (new <redefinable-class>)
     Modify instance OBJ to make it an instance of class NEW.  OBJ
     itself must already be an instance of a redefinable class.

     The value of each of OBJ’s slots is preserved only if a similarly
     named slot exists in NEW; any other slot values are discarded.

     The slots in NEW that do not correspond to any of OBJ’s
     pre-existing slots are initialized according to NEW’s slot
     definitions’ init functions.

   The default ‘change-class’ method also invokes another generic
function, ‘update-instance-for-different-class’, as the last thing that
it does before returning.  The applied
‘update-instance-for-different-class’ method can make any further
adjustments to NEW-INSTANCE that are required to complete or modify the
change of class.  The return value from the applied method is ignored.

 -- generic: update-instance-for-different-class old-instance
          new-instance
     A generic function that can be customized to put finishing touches
     to an instance whose class has just been changed.  The default
     ‘update-instance-for-different-class’ method does nothing.

   Customized change of class behavior can be implemented by defining
‘change-class’ methods that are specialized either by the class of the
instances to be modified or by the metaclass of the new class.


File: guile.info,  Node: Guile Implementation,  Next: GNU Free Documentation License,  Prev: GOOPS,  Up: Top

9 Guile Implementation
**********************

At some point, after one has been programming in Scheme for some time,
another level of Scheme comes into view: its implementation.  Knowledge
of how Scheme can be implemented turns out to be necessary to become an
expert hacker.  As Peter Norvig notes in his retrospective on PAIP(1),
“The expert Lisp programmer eventually develops a good ‘efficiency
model’.”

   By this Norvig means that over time, the Lisp hacker eventually
develops an understanding of how much her code “costs” in terms of space
and time.

   This chapter describes Guile as an implementation of Scheme: its
history, how it represents and evaluates its data, and its compiler.
This knowledge can help you to make that step from being one who is
merely familiar with Scheme to being a real hacker.

* Menu:

* History::                          A brief history of Guile.
* Data Representation::              How Guile represents Scheme data.
* A Virtual Machine for Guile::      How compiled procedures work.
* Compiling to the Virtual Machine:: Not as hard as you might think.

   ---------- Footnotes ----------

   (1) PAIP is the common abbreviation for ‘Paradigms of Artificial
Intelligence Programming’, an old but still useful text on Lisp.
Norvig’s retrospective sums up the lessons of PAIP, and can be found at
<http://norvig.com/Lisp-retro.html>.


File: guile.info,  Node: History,  Next: Data Representation,  Up: Guile Implementation

9.1 A Brief History of Guile
============================

Guile is an artifact of historical processes, both as code and as a
community of hackers.  It is sometimes useful to know this history when
hacking the source code, to know about past decisions and future
directions.

   Of course, the real history of Guile is written by the hackers
hacking and not the writers writing, so we round up the section with a
note on current status and future directions.

* Menu:

* The Emacs Thesis::
* Early Days::
* A Scheme of Many Maintainers::
* A Timeline of Selected Guile Releases::
* Status::


File: guile.info,  Node: The Emacs Thesis,  Next: Early Days,  Up: History

9.1.1 The Emacs Thesis
----------------------

The story of Guile is the story of bringing the development experience
of Emacs to the mass of programs on a GNU system.

   Emacs, when it was first created in its GNU form in 1984, was a new
take on the problem of “how to make a program”.  The Emacs thesis is
that it is delightful to create composite programs based on an
orthogonal kernel written in a low-level language together with a
powerful, high-level extension language.

   Extension languages foster extensible programs, programs which adapt
readily to different users and to changing times.  Proof of this can be
seen in Emacs’ current and continued existence, spanning more than a
quarter-century.

   Besides providing for modification of a program by others, extension
languages are good for _intension_ as well.  Programs built in “the
Emacs way” are pleasurable and easy for their authors to flesh out with
the features that they need.

   After the Emacs experience was appreciated more widely, a number of
hackers started to consider how to spread this experience to the rest of
the GNU system.  It was clear that the easiest way to Emacsify a program
would be to embed a shared language implementation into it.


File: guile.info,  Node: Early Days,  Next: A Scheme of Many Maintainers,  Prev: The Emacs Thesis,  Up: History

9.1.2 Early Days
----------------

Tom Lord was the first to fully concentrate his efforts on an embeddable
language runtime, which he named “GEL”, the GNU Extension Language.

   GEL was the product of converting SCM, Aubrey Jaffer’s implementation
of Scheme, into something more appropriate to embedding as a library.
(SCM was itself based on an implementation by George Carrette, SIOD.)

   Lord managed to convince Richard Stallman to dub GEL the official
extension language for the GNU project.  It was a natural fit, given
that Scheme was a cleaner, more modern Lisp than Emacs Lisp.  Part of
the argument was that eventually when GEL became more capable, it could
gain the ability to execute other languages, especially Emacs Lisp.

   Due to a naming conflict with another programming language, Lee
Thomas suggested a new name for GEL: “Guile”.  Besides being a recursive
acronym, “Guile” craftily follows the naming of its ancestors,
“Planner”, “Conniver”, and “Schemer”.  (The latter was truncated to
“Scheme” due to a 6-character file name limit on an old operating
system.)  Finally, “Guile” suggests “guy-ell”, or “Guy L. Steele”, who,
together with Gerald Sussman, originally discovered Scheme.

   Around the same time that Guile (then GEL) was readying itself for
public release, another extension language was gaining in popularity,
Tcl.  Many developers found advantages in Tcl because of its shell-like
syntax and its well-developed graphical widgets library, Tk.  Also, at
the time there was a large marketing push promoting Tcl as a “universal
extension language”.

   Richard Stallman, as the primary author of GNU Emacs, had a
particular vision of what extension languages should be, and Tcl did not
seem to him to be as capable as Emacs Lisp.  He posted a criticism to
the comp.lang.tcl newsgroup, sparking one of the internet’s legendary
flamewars.  As part of these discussions, retrospectively dubbed the
“Tcl Wars”, he announced the Free Software Foundation’s intent to
promote Guile as the extension language for the GNU project.

   It is a common misconception that Guile was created as a reaction to
Tcl.  While it is true that the public announcement of Guile happened at
the same time as the “Tcl wars”, Guile was created out of a condition
that existed outside the polemic.  Indeed, the need for a powerful
language to bridge the gap between extension of existing applications
and a more fully dynamic programming environment is still with us today.


File: guile.info,  Node: A Scheme of Many Maintainers,  Next: A Timeline of Selected Guile Releases,  Prev: Early Days,  Up: History

9.1.3 A Scheme of Many Maintainers
----------------------------------

Surveying the field, it seems that Scheme implementations correspond
with their maintainers on an N-to-1 relationship.  That is to say, that
those people that implement Schemes might do so on a number of
occasions, but that the lifetime of a given Scheme is tied to the
maintainership of one individual.

   Guile is atypical in this regard.

   Tom Lord maintained Guile for its first year and a half or so,
corresponding to the end of 1994 through the middle of 1996.  The
releases made in this time constitute an arc from SCM as a standalone
program to Guile as a reusable, embeddable library, but passing through
a explosion of features: embedded Tcl and Tk, a toolchain for compiling
and disassembling Java, addition of a C-like syntax, creation of a
module system, and a start at a rich POSIX interface.

   Only some of those features remain in Guile.  There were ongoing
tensions between providing a small, embeddable language, and one which
had all of the features (e.g. a graphical toolkit) that a modern Emacs
might need.  In the end, as Guile gained in uptake, the development team
decided to focus on depth, documentation and orthogonality rather than
on breadth.  This has been the focus of Guile ever since, although there
is a wide range of third-party libraries for Guile.

   Jim Blandy presided over that period of stabilization, in the three
years until the end of 1999, when he too moved on to other projects.
Since then, Guile has had a group maintainership.  The first group was
Maciej Stachowiak, Mikael Djurfeldt, and Marius Vollmer, with Vollmer
staying on the longest.  By late 2007, Marius had mostly moved on to
other things, so Neil Jerram and Ludovic Courtès stepped up to take on
the primary maintenance responsibility.  Neil and Ludovic were joined by
Andy Wingo in late 2009, allowing Neil to step away, and Mark Weaver
joined shortly thereafter.  After spending more than 5 years in the
role, Mark stepped down as well, leaving Ludovic and Andy as the current
co-maintainers of Guile as of January 2020.

   Of course, a large part of the actual work on Guile has come from
other contributors too numerous to mention, but without whom the world
would be a poorer place.


File: guile.info,  Node: A Timeline of Selected Guile Releases,  Next: Status,  Prev: A Scheme of Many Maintainers,  Up: History

9.1.4 A Timeline of Selected Guile Releases
-------------------------------------------

guile-i — 4 February 1995
     SCM, turned into a library.

guile-ii — 6 April 1995
     A low-level module system was added.  Tcl/Tk support was added,
     allowing extension of Scheme by Tcl or vice versa.  POSIX support
     was improved, and there was an experimental stab at Java
     integration.

guile-iii — 18 August 1995
     The C-like syntax, ctax, was improved, but mostly this release
     featured a start at the task of breaking Guile into pieces.

1.0 — 5 January 1997
     ‘#f’ was distinguished from ‘'()’.  User-level, cooperative
     multi-threading was added.  Source-level debugging became more
     useful, and programmer’s and user’s manuals were begun.  The module
     system gained a high-level interface, which is still used today in
     more or less the same form.

1.1 — 16 May 1997
1.2 — 24 June 1997
     Support for Tcl/Tk and ctax were split off as separate packages,
     and have remained there since.  Guile became more compatible with
     SCSH, and more useful as a UNIX scripting language.  Libguile could
     now be built as a shared library, and third-party extensions
     written in C became loadable via dynamic linking.

1.3.0 — 19 October 1998
     Command-line editing became much more pleasant through the use of
     the readline library.  The initial support for internationalization
     via multi-byte strings was removed; 10 years were to pass before
     proper internationalization would land again.  Initial Emacs Lisp
     support landed, ports gained better support for file descriptors,
     and fluids were added.

1.3.2 — 20 August 1999
1.3.4 — 25 September 1999
1.4 — 21 June 2000
     A long list of lispy features were added: hooks, Common Lisp’s
     ‘format’, optional and keyword procedure arguments, ‘getopt-long’,
     sorting, random numbers, and many other fixes and enhancements.
     Guile also gained an interactive debugger, interactive help, and
     better backtraces.

1.6 — 6 September 2002
     Guile gained support for the R5RS standard, and added a number of
     SRFI modules.  The module system was expanded with programmatic
     support for identifier selection and renaming.  The GOOPS object
     system was merged into Guile core.

1.8 — 20 February 2006
     Guile’s arbitrary-precision arithmetic switched to use the GMP
     library, and added support for exact rationals.  Guile’s embedded
     user-space threading was removed in favor of POSIX pre-emptive
     threads, providing true multiprocessing.  Gettext support was
     added, and Guile’s C API was cleaned up and orthogonalized in a
     massive way.

2.0 — 16 February 2010
     A virtual machine was added to Guile, along with the associated
     compiler and toolchain.  Support for internationalization was
     finally reimplemented, in terms of unicode, locales, and
     libunistring.  Running Guile instances became controllable and
     debuggable from within Emacs, via Geiser.  Guile caught up to
     features found in a number of other Schemes: SRFI-18 threads,
     module-hygienic macros, a profiler, tracer, and debugger, SSAX XML
     integration, bytevectors, a dynamic FFI, delimited continuations,
     module versions, and partial support for R6RS.

2.2 — 15 March 2017
     The virtual machine and introduced in 2.0 was completely rewritten,
     along with much of the compiler and toolchain.  This speeds up many
     Guile programs as well as reducing startup time and memory usage.
     Guile’s POSIX multithreading was improved, stacks became
     dynamically expandable, the ports facility gained support for
     non-blocking I/O.

3.0 – January 2020
     Guile gained support for native code generation via a simple
     just-in-time (JIT) compiler, further improving the speed of its
     virtual machine.  The compiler itself gained a number of new
     optimizations: inlining of top-level bindings, better closure
     optimization, and better unboxing of integer and floating-point
     values.  R7RS support was added, and R6RS support improved.  The
     exception facility (throw and catch) was rewritten in terms of
     SRFI-34 exception handlers.


File: guile.info,  Node: Status,  Prev: A Timeline of Selected Guile Releases,  Up: History

9.1.5 Status, or: Your Help Needed
----------------------------------

Guile has achieved much of what it set out to achieve, but there is much
remaining to do.

   There is still the old problem of bringing existing applications into
a more Emacs-like experience.  Guile has had some successes in this
respect, but still most applications in the GNU system are without Guile
integration.

   Getting Guile to those applications takes an investment, the
“hacktivation energy” needed to wire Guile into a program that only pays
off once it is good enough to enable new kinds of behavior.  This would
be a great way for new hackers to contribute: take an application that
you use and that you know well, think of something that it can’t yet do,
and figure out a way to integrate Guile and implement that task in
Guile.

   With time, perhaps this exposure can reverse itself, whereby programs
can run under Guile instead of vice versa, eventually resulting in the
Emacsification of the entire GNU system.  Indeed, this is the reason for
the naming of the many Guile modules that live in the ‘ice-9’ namespace,
a nod to the fictional substance in Kurt Vonnegut’s novel, Cat’s Cradle,
capable of acting as a seed crystal to crystallize the mass of software.

   Implicit to this whole discussion is the idea that dynamic languages
are somehow better than languages like C. While languages like C have
their place, Guile’s take on this question is that yes, Scheme is more
expressive than C, and more fun to write.  This realization carries an
imperative with it to write as much code in Scheme as possible rather
than in other languages.

   These days it is possible to write extensible applications almost
entirely from high-level languages, through byte-code and native
compilation, speed gains in the underlying hardware, and foreign call
interfaces in the high-level language.  Smalltalk systems are like this,
as are Common Lisp-based systems.  While there already are a number of
pure-Guile applications out there, in the past users have still needed
to drop down to C for some tasks: interfacing to system libraries that
don’t have prebuilt Guile interfaces, and for some tasks requiring high
performance.  With the arrival of native code generation via a JIT
compiler in Guile 3.0, most of these older applications can now be
updated to move more C code to Scheme.

   Still, even with an all-Guile application, sometimes you want to
provide an opportunity for users to extend your program from a language
with a syntax that is closer to C, or to Python.  Another interesting
idea to consider is compiling e.g. Python to Guile.  It’s not that
far-fetched of an idea: see for example IronPython or JRuby.

   Also, there’s Emacs itself.  Guile’s Emacs Lisp support has reached
an excellent level of correctness, robustness, and speed.  However there
is still work to do to finish its integration into Emacs itself.  This
will give lots of exciting things to Emacs: native threads, a real
object system, more sophisticated types, cleaner syntax, and access to
all of the Guile extensions.

   Finally, so much of the world’s computation is performed in web
browsers that it makes sense to ask ourselves what the
Guile-on-the-web-client story is.  With the advent of WebAssembly, there
may finally be a reasonable compilation target that’s present on almost
all user-exposed devices.  Especially with the upcoming proposals to
allow for tail calls, delimited continuations, and GC-managed objects,
Scheme might once again have a place in the web browser.  Get to it!


File: guile.info,  Node: Data Representation,  Next: A Virtual Machine for Guile,  Prev: History,  Up: Guile Implementation

9.2 Data Representation
=======================

Scheme is a latently-typed language; this means that the system cannot,
in general, determine the type of a given expression at compile time.
Types only become apparent at run time.  Variables do not have fixed
types; a variable may hold a pair at one point, an integer at the next,
and a thousand-element vector later.  Instead, values, not variables,
have fixed types.

   In order to implement standard Scheme functions like ‘pair?’ and
‘string?’ and provide garbage collection, the representation of every
value must contain enough information to accurately determine its type
at run time.  Often, Scheme systems also use this information to
determine whether a program has attempted to apply an operation to an
inappropriately typed value (such as taking the ‘car’ of a string).

   Because variables, pairs, and vectors may hold values of any type,
Scheme implementations use a uniform representation for values — a
single type large enough to hold either a complete value or a pointer to
a complete value, along with the necessary typing information.

   The following sections will present a simple typing system, and then
make some refinements to correct its major weaknesses.  We then conclude
with a discussion of specific choices that Guile has made regarding
garbage collection and data representation.

* Menu:

* A Simple Representation::
* Faster Integers::
* Cheaper Pairs::
* Conservative GC::
* The SCM Type in Guile::


File: guile.info,  Node: A Simple Representation,  Next: Faster Integers,  Up: Data Representation

9.2.1 A Simple Representation
-----------------------------

The simplest way to represent Scheme values in C would be to represent
each value as a pointer to a structure containing a type indicator,
followed by a union carrying the real value.  Assuming that ‘SCM’ is the
name of our universal type, we can write:

     enum type { integer, pair, string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         int integer;
         struct { SCM car, cdr; } pair;
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };
   with the ellipses replaced with code for the remaining Scheme types.

   This representation is sufficient to implement all of Scheme’s
semantics.  If X is an ‘SCM’ value:
   • To test if X is an integer, we can write ‘X->type == integer’.
   • To find its value, we can write ‘X->value.integer’.
   • To test if X is a vector, we can write ‘X->type == vector’.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element.
   • If we know X is a pair, we can write ‘X->value.pair.car’ to extract
     its car.


File: guile.info,  Node: Faster Integers,  Next: Cheaper Pairs,  Prev: A Simple Representation,  Up: Data Representation

9.2.2 Faster Integers
---------------------

Unfortunately, the above representation has a serious disadvantage.  In
order to return an integer, an expression must allocate a ‘struct
value’, initialize it to represent that integer, and return a pointer to
it.  Furthermore, fetching an integer’s value requires a memory
reference, which is much slower than a register reference on most
processors.  Since integers are extremely common, this representation is
too costly, in both time and space.  Integers should be very cheap to
create and manipulate.

   One possible solution comes from the observation that, on many
architectures, heap-allocated data (i.e., what you get when you call
‘malloc’) must be aligned on an eight-byte boundary.  (Whether or not
the machine actually requires it, we can write our own allocator for
‘struct value’ objects that assures this is true.)  In this case, the
lower three bits of the structure’s address are known to be zero.

   This gives us the room we need to provide an improved representation
for integers.  We make the following rules:
   • If the lower three bits of an ‘SCM’ value are zero, then the SCM
     value is a pointer to a ‘struct value’, and everything proceeds as
     before.
   • Otherwise, the ‘SCM’ value represents an integer, whose value
     appears in its upper bits.

   Here is C code implementing this convention:
     enum type { pair, string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         struct { SCM car, cdr; } pair;
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };

     #define POINTER_P(x) (((int) (x) & 7) == 0)
     #define INTEGER_P(x) (! POINTER_P (x))

     #define GET_INTEGER(x)  ((int) (x) >> 3)
     #define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1))

   Notice that ‘integer’ no longer appears as an element of ‘enum type’,
and the union has lost its ‘integer’ member.  Instead, we use the
‘POINTER_P’ and ‘INTEGER_P’ macros to make a coarse classification of
values into integers and non-integers, and do further type testing as
before.

   Here’s how we would answer the questions posed above (again, assume X
is an ‘SCM’ value):
   • To test if X is an integer, we can write ‘INTEGER_P (X)’.
   • To find its value, we can write ‘GET_INTEGER (X)’.
   • To test if X is a vector, we can write:
            POINTER_P (X) && X->type == vector
     Given the new representation, we must make sure X is truly a
     pointer before we dereference it to determine its complete type.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element, as before.
   • If we know X is a pair, we can write ‘X->value.pair.car’ to extract
     its car, just as before.

   This representation allows us to operate more efficiently on integers
than the first.  For example, if X and Y are known to be integers, we
can compute their sum as follows:
     MAKE_INTEGER (GET_INTEGER (X) + GET_INTEGER (Y))
   Now, integer math requires no allocation or memory references.  Most
real Scheme systems actually implement addition and other operations
using an even more efficient algorithm, but this essay isn’t about
bit-twiddling.  (Hint: how do you decide when to overflow to a bignum?
How would you do it in assembly?)


File: guile.info,  Node: Cheaper Pairs,  Next: Conservative GC,  Prev: Faster Integers,  Up: Data Representation

9.2.3 Cheaper Pairs
-------------------

However, there is yet another issue to confront.  Most Scheme heaps
contain more pairs than any other type of object; Jonathan Rees said at
one point that pairs occupy 45% of the heap in his Scheme
implementation, Scheme 48.  However, our representation above spends
three ‘SCM’-sized words per pair — one for the type, and two for the CAR
and CDR.  Is there any way to represent pairs using only two words?

   Let us refine the convention we established earlier.  Let us assert
that:
   • If the bottom three bits of an ‘SCM’ value are ‘#b000’, then it is
     a pointer, as before.
   • If the bottom three bits are ‘#b001’, then the upper bits are an
     integer.  This is a bit more restrictive than before.
   • If the bottom two bits are ‘#b010’, then the value, with the bottom
     three bits masked out, is the address of a pair.

   Here is the new C code:
     enum type { string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };

     struct pair {
       SCM car, cdr;
     };

     #define POINTER_P(x) (((int) (x) & 7) == 0)

     #define INTEGER_P(x)  (((int) (x) & 7) == 1)
     #define GET_INTEGER(x)  ((int) (x) >> 3)
     #define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1))

     #define PAIR_P(x) (((int) (x) & 7) == 2)
     #define GET_PAIR(x) ((struct pair *) ((int) (x) & ~7))

   Notice that ‘enum type’ and ‘struct value’ now only contain
provisions for vectors and strings; both integers and pairs have become
special cases.  The code above also assumes that an ‘int’ is large
enough to hold a pointer, which isn’t generally true.

   Our list of examples is now as follows:
   • To test if X is an integer, we can write ‘INTEGER_P (X)’; this is
     as before.
   • To find its value, we can write ‘GET_INTEGER (X)’, as before.
   • To test if X is a vector, we can write:
            POINTER_P (X) && X->type == vector
     We must still make sure that X is a pointer to a ‘struct value’
     before dereferencing it to find its type.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element, as before.
   • We can write ‘PAIR_P (X)’ to determine if X is a pair, and then
     write ‘GET_PAIR (X)->car’ to refer to its car.

   This change in representation reduces our heap size by 15%.  It also
makes it cheaper to decide if a value is a pair, because no memory
references are necessary; it suffices to check the bottom two bits of
the ‘SCM’ value.  This may be significant when traversing lists, a
common activity in a Scheme system.

   Again, most real Scheme systems use a slightly different
implementation; for example, if GET_PAIR subtracts off the low bits of
‘x’, instead of masking them off, the optimizer will often be able to
combine that subtraction with the addition of the offset of the
structure member we are referencing, making a modified pointer as fast
to use as an unmodified pointer.


File: guile.info,  Node: Conservative GC,  Next: The SCM Type in Guile,  Prev: Cheaper Pairs,  Up: Data Representation

9.2.4 Conservative Garbage Collection
-------------------------------------

Aside from the latent typing, the major source of constraints on a
Scheme implementation’s data representation is the garbage collector.
The collector must be able to traverse every live object in the heap, to
determine which objects are not live, and thus collectable.

   There are many ways to implement this.  Guile’s garbage collection is
built on a library, the Boehm-Demers-Weiser conservative garbage
collector (BDW-GC). The BDW-GC “just works”, for the most part.  But
since it is interesting to know how these things work, we include here a
high-level description of what the BDW-GC does.

   Garbage collection has two logical phases: a “mark” phase, in which
the set of live objects is enumerated, and a “sweep” phase, in which
objects not traversed in the mark phase are collected.  Correct
functioning of the collector depends on being able to traverse the
entire set of live objects.

   In the mark phase, the collector scans the system’s global variables
and the local variables on the stack to determine which objects are
immediately accessible by the C code.  It then scans those objects to
find the objects they point to, and so on.  The collector logically sets
a “mark bit” on each object it finds, so each object is traversed only
once.

   When the collector can find no unmarked objects pointed to by marked
objects, it assumes that any objects that are still unmarked will never
be used by the program (since there is no path of dereferences from any
global or local variable that reaches them) and deallocates them.

   In the above paragraphs, we did not specify how the garbage collector
finds the global and local variables; as usual, there are many different
approaches.  Frequently, the programmer must maintain a list of pointers
to all global variables that refer to the heap, and another list
(adjusted upon entry to and exit from each function) of local variables,
for the collector’s benefit.

   The list of global variables is usually not too difficult to
maintain, since global variables are relatively rare.  However, an
explicitly maintained list of local variables (in the author’s personal
experience) is a nightmare to maintain.  Thus, the BDW-GC uses a
technique called “conservative garbage collection”, to make the local
variable list unnecessary.

   The trick to conservative collection is to treat the C stack as an
ordinary range of memory, and assume that _every_ word on the C stack is
a pointer into the heap.  Thus, the collector marks all objects whose
addresses appear anywhere in the C stack, without knowing for sure how
that word is meant to be interpreted.

   In addition to the stack, the BDW-GC will also scan static data
sections.  This means that global variables are also scanned when
looking for live Scheme objects.

   Obviously, such a system will occasionally retain objects that are
actually garbage, and should be freed.  In practice, this is not a
problem, as the set of conservatively-scanned locations is fixed; the
Scheme stack is maintained apart from the C stack, and is scanned
precisely (as opposed to conservatively).  The GC-managed heap is also
partitioned into parts that can contain pointers (such as vectors) and
parts that can’t (such as bytevectors), limiting the potential for
confusing a raw integer with a pointer to a live object.

   Interested readers should see the BDW-GC web page at
<http://www.hboehm.info/gc/>, for more information on conservative GC in
general and the BDW-GC implementation in particular.


File: guile.info,  Node: The SCM Type in Guile,  Prev: Conservative GC,  Up: Data Representation

9.2.5 The SCM Type in Guile
---------------------------

Guile classifies Scheme objects into two kinds: those that fit entirely
within an ‘SCM’, and those that require heap storage.

   The former class are called “immediates”.  The class of immediates
includes small integers, characters, boolean values, the empty list, the
mysterious end-of-file object, and some others.

   The remaining types are called, not surprisingly, “non-immediates”.
They include pairs, procedures, strings, vectors, and all other data
types in Guile.  For non-immediates, the ‘SCM’ word contains a pointer
to data on the heap, with further information about the object in
question is stored in that data.

   This section describes how the ‘SCM’ type is actually represented and
used at the C level.  Interested readers should see ‘libguile/scm.h’ for
an exposition of how Guile stores type information.

   In fact, there are two basic C data types to represent objects in
Guile: ‘SCM’ and ‘scm_t_bits’.

* Menu:

* Relationship Between SCM and scm_t_bits::
* Immediate Objects::
* Non-Immediate Objects::
* Allocating Heap Objects::
* Heap Object Type Information::
* Accessing Heap Object Fields::


File: guile.info,  Node: Relationship Between SCM and scm_t_bits,  Next: Immediate Objects,  Up: The SCM Type in Guile

9.2.5.1 Relationship Between ‘SCM’ and ‘scm_t_bits’
...................................................

A variable of type ‘SCM’ is guaranteed to hold a valid Scheme object.  A
variable of type ‘scm_t_bits’, on the other hand, may hold a
representation of a ‘SCM’ value as a C integral type, but may also hold
any C value, even if it does not correspond to a valid Scheme object.

   For a variable X of type ‘SCM’, the Scheme object’s type information
is stored in a form that is not directly usable.  To be able to work on
the type encoding of the scheme value, the ‘SCM’ variable has to be
transformed into the corresponding representation as a ‘scm_t_bits’
variable Y by using the ‘SCM_UNPACK’ macro.  Once this has been done,
the type of the scheme object X can be derived from the content of the
bits of the ‘scm_t_bits’ value Y, in the way illustrated by the example
earlier in this chapter (*note Cheaper Pairs::).  Conversely, a valid
bit encoding of a Scheme value as a ‘scm_t_bits’ variable can be
transformed into the corresponding ‘SCM’ value using the ‘SCM_PACK’
macro.


File: guile.info,  Node: Immediate Objects,  Next: Non-Immediate Objects,  Prev: Relationship Between SCM and scm_t_bits,  Up: The SCM Type in Guile

9.2.5.2 Immediate Objects
.........................

A Scheme object may either be an immediate, i.e. carrying all necessary
information by itself, or it may contain a reference to a “heap object”
which is, as the name implies, data on the heap.  Although in general it
should be irrelevant for user code whether an object is an immediate or
not, within Guile’s own code the distinction is sometimes of importance.
Thus, the following low level macro is provided:

 -- Macro: int SCM_IMP (SCM X)
     A Scheme object is an immediate if it fulfills the ‘SCM_IMP’
     predicate, otherwise it holds an encoded reference to a heap
     object.  The result of the predicate is delivered as a C style
     boolean value.  User code and code that extends Guile should
     normally not be required to use this macro.

Summary:
   • Given a Scheme object X of unknown type, check first with ‘SCM_IMP
     (X)’ if it is an immediate object.
   • If so, all of the type and value information can be determined from
     the ‘scm_t_bits’ value that is delivered by ‘SCM_UNPACK (X)’.

   There are a number of special values in Scheme, most of them
documented elsewhere in this manual.  It’s not quite the right place to
put them, but for now, here’s a list of the C names given to some of
these values:

 -- Macro: SCM SCM_EOL
     The Scheme empty list object, or “End Of List” object, usually
     written in Scheme as ‘'()’.

 -- Macro: SCM SCM_EOF_VAL
     The Scheme end-of-file value.  It has no standard written
     representation, for obvious reasons.

 -- Macro: SCM SCM_UNSPECIFIED
     The value returned by some (but not all) expressions that the
     Scheme standard says return an “unspecified” value.

     This is sort of a weirdly literal way to take things, but the
     standard read-eval-print loop prints nothing when the expression
     returns this value, so it’s not a bad idea to return this when you
     can’t think of anything else helpful.

 -- Macro: SCM SCM_UNDEFINED
     The “undefined” value.  Its most important property is that is not
     equal to any valid Scheme value.  This is put to various internal
     uses by C code interacting with Guile.

     For example, when you write a C function that is callable from
     Scheme and which takes optional arguments, the interpreter passes
     ‘SCM_UNDEFINED’ for any arguments you did not receive.

     We also use this to mark unbound variables.

 -- Macro: int SCM_UNBNDP (SCM X)
     Return true if X is ‘SCM_UNDEFINED’.  Note that this is not a check
     to see if X is ‘SCM_UNBOUND’.  History will not be kind to us.


File: guile.info,  Node: Non-Immediate Objects,  Next: Allocating Heap Objects,  Prev: Immediate Objects,  Up: The SCM Type in Guile

9.2.5.3 Non-Immediate Objects
.............................

A Scheme object of type ‘SCM’ that does not fulfill the ‘SCM_IMP’
predicate holds an encoded reference to a heap object.  This reference
can be decoded to a C pointer to a heap object using the
‘SCM_UNPACK_POINTER’ macro.  The encoding of a pointer to a heap object
into a ‘SCM’ value is done using the ‘SCM_PACK_POINTER’ macro.

   Before Guile 2.0, Guile had a custom garbage collector that allocated
heap objects in units of 2-word “cells”.  With the move to the BDW-GC
collector in Guile 2.0, Guile can allocate heap objects of any size, and
the concept of a cell is now obsolete.  Still, we mention it here as the
name still appears in various low-level interfaces.

 -- Macro: scm_t_bits * SCM_UNPACK_POINTER (SCM X)
 -- Macro: scm_t_cell * SCM2PTR (SCM X)
     Extract and return the heap object pointer from a non-immediate
     ‘SCM’ object X.  The name ‘SCM2PTR’ is deprecated but still common.

 -- Macro: SCM_PACK_POINTER (scm_t_bits * X)
 -- Macro: SCM PTR2SCM (scm_t_cell * X)
     Return a ‘SCM’ value that encodes a reference to the heap object
     pointer X.  The name ‘PTR2SCM’ is deprecated but still common.

   Note that it is also possible to transform a non-immediate ‘SCM’
value by using ‘SCM_UNPACK’ into a ‘scm_t_bits’ variable.  However, the
result of ‘SCM_UNPACK’ may not be used as a pointer to a heap object:
only ‘SCM_UNPACK_POINTER’ is guaranteed to transform a ‘SCM’ object into
a valid pointer to a heap object.  Also, it is not allowed to apply
‘SCM_PACK_POINTER’ to anything that is not a valid pointer to a heap
object.

Summary:
   • Only use ‘SCM_UNPACK_POINTER’ on ‘SCM’ values for which ‘SCM_IMP’
     is false!
   • Don’t use ‘(scm_t_cell *) SCM_UNPACK (X)’!  Use ‘SCM_UNPACK_POINTER
     (X)’ instead!
   • Don’t use ‘SCM_PACK_POINTER’ for anything but a heap object
     pointer!


File: guile.info,  Node: Allocating Heap Objects,  Next: Heap Object Type Information,  Prev: Non-Immediate Objects,  Up: The SCM Type in Guile

9.2.5.4 Allocating Heap Objects
...............................

Heap objects are heap-allocated data pointed to by non-immediate ‘SCM’
value.  The first word of the heap object should contain a type code.
The object may be any number of words in length, and is generally
scanned by the garbage collector for additional unless the object was
allocated using a “pointerless” allocation function.

   You should generally not need these functions, unless you are
implementing a new data type, and thoroughly understand the code in
‘<libguile/scm.h>’.

   If you just want to allocate pairs, use ‘scm_cons’.

 -- Function: SCM scm_words (scm_t_bits word_0, uint32_t n_words)
     Allocate a new heap object containing N_WORDS, and initialize the
     first slot to WORD_0, and return a non-immediate ‘SCM’ value
     encoding a pointer to the object.  Typically WORD_0 will contain
     the type tag.

   There are also deprecated but common variants of ‘scm_words’ that use
the term “cell” to indicate 2-word objects.

 -- Function: SCM scm_cell (scm_t_bits word_0, scm_t_bits word_1)
     Allocate a new 2-word heap object, initialize the two slots with
     WORD_0 and WORD_1, and return it.  Just like calling ‘scm_words
     (WORD_0, 2)’, then initializing the second slot to WORD_1.

     Note that WORD_0 and WORD_1 are of type ‘scm_t_bits’.  If you want
     to pass a ‘SCM’ object, you need to use ‘SCM_UNPACK’.

 -- Function: SCM scm_double_cell (scm_t_bits word_0, scm_t_bits word_1,
          scm_t_bits word_2, scm_t_bits word_3)
     Like ‘scm_cell’, but allocates a 4-word heap object.


File: guile.info,  Node: Heap Object Type Information,  Next: Accessing Heap Object Fields,  Prev: Allocating Heap Objects,  Up: The SCM Type in Guile

9.2.5.5 Heap Object Type Information
....................................

Heap objects contain a type tag and are followed by a number of
word-sized slots.  The interpretation of the object contents depends on
the type of the object.

 -- Macro: scm_t_bits SCM_CELL_TYPE (SCM X)
     Extract the first word of the heap object pointed to by X.  This
     value holds the information about the cell type.

 -- Macro: void SCM_SET_CELL_TYPE (SCM X, scm_t_bits T)
     For a non-immediate Scheme object X, write the value T into the
     first word of the heap object referenced by X.  The value T must
     hold a valid cell type.


File: guile.info,  Node: Accessing Heap Object Fields,  Prev: Heap Object Type Information,  Up: The SCM Type in Guile

9.2.5.6 Accessing Heap Object Fields
....................................

For a non-immediate Scheme object X, the object type can be determined
by using the ‘SCM_CELL_TYPE’ macro described in the previous section.
For each different type of heap object it is known which fields hold
tagged Scheme objects and which fields hold untagged raw data.  To
access the different fields appropriately, the following macros are
provided.

 -- Macro: scm_t_bits SCM_CELL_WORD (SCM X, unsigned int N)
 -- Macro: scm_t_bits SCM_CELL_WORD_0 (X)
 -- Macro: scm_t_bits SCM_CELL_WORD_1 (X)
 -- Macro: scm_t_bits SCM_CELL_WORD_2 (X)
 -- Macro: scm_t_bits SCM_CELL_WORD_3 (X)
     Deliver the field N of the heap object referenced by the
     non-immediate Scheme object X as raw untagged data.  Only use this
     macro for fields containing untagged data; don’t use it for fields
     containing tagged ‘SCM’ objects.

 -- Macro: SCM SCM_CELL_OBJECT (SCM X, unsigned int N)
 -- Macro: SCM SCM_CELL_OBJECT_0 (SCM X)
 -- Macro: SCM SCM_CELL_OBJECT_1 (SCM X)
 -- Macro: SCM SCM_CELL_OBJECT_2 (SCM X)
 -- Macro: SCM SCM_CELL_OBJECT_3 (SCM X)
     Deliver the field N of the heap object referenced by the
     non-immediate Scheme object X as a Scheme object.  Only use this
     macro for fields containing tagged ‘SCM’ objects; don’t use it for
     fields containing untagged data.

 -- Macro: void SCM_SET_CELL_WORD (SCM X, unsigned int N, scm_t_bits W)
 -- Macro: void SCM_SET_CELL_WORD_0 (X, W)
 -- Macro: void SCM_SET_CELL_WORD_1 (X, W)
 -- Macro: void SCM_SET_CELL_WORD_2 (X, W)
 -- Macro: void SCM_SET_CELL_WORD_3 (X, W)
     Write the raw value W into field number N of the heap object
     referenced by the non-immediate Scheme value X.  Values that are
     written into heap objects as raw values should only be read later
     using the ‘SCM_CELL_WORD’ macros.

 -- Macro: void SCM_SET_CELL_OBJECT (SCM X, unsigned int N, SCM O)
 -- Macro: void SCM_SET_CELL_OBJECT_0 (SCM X, SCM O)
 -- Macro: void SCM_SET_CELL_OBJECT_1 (SCM X, SCM O)
 -- Macro: void SCM_SET_CELL_OBJECT_2 (SCM X, SCM O)
 -- Macro: void SCM_SET_CELL_OBJECT_3 (SCM X, SCM O)
     Write the Scheme object O into field number N of the heap object
     referenced by the non-immediate Scheme value X.  Values that are
     written into heap objects as objects should only be read using the
     ‘SCM_CELL_OBJECT’ macros.

Summary:
   • For a non-immediate Scheme object X of unknown type, get the type
     information by using ‘SCM_CELL_TYPE (X)’.
   • As soon as the type information is available, only use the
     appropriate access methods to read and write data to the different
     heap object fields.
   • Note that field 0 stores the cell type information.  Generally
     speaking, other data associated with a heap object is stored
     starting from field 1.


File: guile.info,  Node: A Virtual Machine for Guile,  Next: Compiling to the Virtual Machine,  Prev: Data Representation,  Up: Guile Implementation

9.3 A Virtual Machine for Guile
===============================

Enough about data—how does Guile run code?

   Code is a grammatical production of a language.  Sometimes these
languages are implemented using interpreters: programs that run
along-side the program being interpreted, dynamically translating the
high-level code to low-level code.  Sometimes these languages are
implemented using compilers: programs that translate high-level programs
to equivalent low-level code, and pass on that low-level code to some
other language implementation.  Each of these languages can be thought
to be virtual machines: they offer programs an abstract machine on which
to run.

   Guile implements a number of interpreters and compilers on different
language levels.  For example, there is an interpreter for the Scheme
language that is itself implemented as a Scheme program compiled to a
bytecode for a low-level virtual machine shipped with Guile.  That
virtual machine is implemented by both an interpreter—a C program that
interprets the bytecodes—and a compiler—a C program that dynamically
translates bytecode programs to native machine code(1).

   This section describes the language implemented by Guile’s bytecode
virtual machine, as well as some examples of translations of Scheme
programs to Guile’s VM.

* Menu:

* Why a VM?::
* VM Concepts::
* Stack Layout::
* Variables and the VM::
* VM Programs::
* Object File Format::
* Instruction Set::
* Just-In-Time Native Code::

   ---------- Footnotes ----------

   (1) Even the lowest-level machine code can be thought to be
interpreted by the CPU, and indeed is often implemented by compiling
machine instructions to “micro-operations”.


File: guile.info,  Node: Why a VM?,  Next: VM Concepts,  Up: A Virtual Machine for Guile

9.3.1 Why a VM?
---------------

For a long time, Guile only had a Scheme interpreter, implemented in C.
Guile’s interpreter operated directly on the S-expression representation
of Scheme source code.

   But while the interpreter was highly optimized and hand-tuned, it
still performed many needless computations during the course of
evaluating a Scheme expression.  For example, application of a function
to arguments needlessly consed up the arguments in a list.  Evaluation
of an expression like ‘(f x y)’ always had to figure out whether F was a
procedure, or a special form like ‘if’, or something else.  The
interpreter represented the lexical environment as a heap data
structure, so every evaluation caused allocation, which was of course
slow.  Et cetera.

   The solution to the slow-interpreter problem was to compile the
higher-level language, Scheme, into a lower-level language for which all
of the checks and dispatching have already been done—the code is instead
stripped to the bare minimum needed to “do the job”.

   The question becomes then, what low-level language to choose?  There
are many options.  We could compile to native code directly, but that
poses portability problems for Guile, as it is a highly cross-platform
project.

   So we want the performance gains that compilation provides, but we
also want to maintain the portability benefits of a single code path.
The obvious solution is to compile to a virtual machine that is present
on all Guile installations.

   The easiest (and most fun) way to depend on a virtual machine is to
implement the virtual machine within Guile itself.  Guile contains a
bytecode interpreter (written in C) and a Scheme to bytecode compiler
(written in Scheme).  This way the virtual machine provides what Scheme
needs (tail calls, multiple values, ‘call/cc’) and can provide optimized
inline instructions for Guile as well (GC-managed allocations, type
checks, etc.).

   Guile also includes a just-in-time (JIT) compiler to translate
bytecode to native code.  Because Guile embeds a portable code
generation library (<https://gitlab.com/wingo/lightening>), we keep the
benefits of portability while also benefitting from fast native code.
To avoid too much time spent in the JIT compiler itself, Guile is tuned
to only emit machine code for bytecode that is called often.

   The rest of this section describes that VM that Guile implements, and
the compiled procedures that run on it.

   Before moving on, though, we should note that though we spoke of the
interpreter in the past tense, Guile still has an interpreter.  The
difference is that before, it was Guile’s main Scheme implementation,
and so was implemented in highly optimized C; now, it is actually
implemented in Scheme, and compiled down to VM bytecode, just like any
other program.  (There is still a C interpreter around, used to
bootstrap the compiler, but it is not normally used at runtime.)

   The upside of implementing the interpreter in Scheme is that we
preserve tail calls and multiple-value handling between interpreted and
compiled code, and with advent of the JIT compiler in Guile 3.0 we reach
the speed of the old hand-tuned C implementation; it’s the best of both
worlds.

   Also note that this decision to implement a bytecode compiler does
not preclude ahead-of-time native compilation.  More possibilities are
discussed in *note Extending the Compiler::.


File: guile.info,  Node: VM Concepts,  Next: Stack Layout,  Prev: Why a VM?,  Up: A Virtual Machine for Guile

9.3.2 VM Concepts
-----------------

The bytecode in a Scheme procedure is interpreted by a virtual machine
(VM). Each thread has its own instantiation of the VM. The virtual
machine executes the sequence of instructions in a procedure.

   Each VM instruction starts by indicating which operation it is, and
then follows by encoding its source and destination operands.  Each
procedure declares that it has some number of local variables, including
the function arguments.  These local variables form the available
operands of the procedure, and are accessed by index.

   The local variables for a procedure are stored on a stack.  Calling a
procedure typically enlarges the stack, and returning from a procedure
shrinks it.  Stack memory is exclusive to the virtual machine that owns
it.

   In addition to their stacks, virtual machines also have access to the
global memory (modules, global bindings, etc) that is shared among other
parts of Guile, including other VMs.

   The registers that a VM has are as follows:

   • ip - Instruction pointer
   • sp - Stack pointer
   • fp - Frame pointer

   In other architectures, the instruction pointer is sometimes called
the “program counter” (pc).  This set of registers is pretty typical for
virtual machines; their exact meanings in the context of Guile’s VM are
described in the next section.

